diff options
author | 2021-10-31 12:31:16 +1100 | |
---|---|---|
committer | 2021-10-31 12:31:16 +1100 | |
commit | d64ea5331b2312f81df464fb22dcef0191216d86 (patch) | |
tree | a3f3784371da401e6a675e5b6b9734b88281a08d /plugins/autofire/autofire_menu.lua | |
parent | cfffc54b61cabc5ef9533396bf87324eb5eeb63e (diff) |
-frontend: Refactored menu event handling and fixed a number of issues. (#8777)
* Moved common code for drawing about box, info viewer, and other text box menus to a base class; removed the last of the info viewer logic and the multi-line item hack from the base menu class.
* Added previous/next group navigation for general inputs and plugin input selection menus.
* Moved message catalog logic to lib/util, allowing osd and emu to use localised messages.
* Made the base menu class use the UI manager’s feature for holding session state rather than a static map and mutex.
* Improved menu event handling model, and fixed many issues, particularly with menus behaving badly when hidden/shown.
* Added better support for menus that don’t participate in the usual menu stack, like the menuless sliders and the save/load state menus.
* Made a number of menus refresh state when being shown after being hidden (fixes MT08121 among other issues).
* Fixed indication of mounted slot option in the slot option details menu.
* Improved appearance of background menus when emulation isn't running - draw all menus in the stack, and darken the background menus to make the edges of the active menu clearer.
* Fixed locale issues in -listxml.
-debugger: Made GUI debuggers more uniform.
* Added new memory view features to Win32 debugger.
* Fixed spelling of hexadecimal in Cocoa debugger and added decimal address option.
* Fixed duplicate keyboard shortcut in Cocoa debugger (Shift-Cmd-D was both new device window and 64-bit float format).
* Made keyboard shortcuts slightly more consistent across debuggers.
-plugins: Moved input selection menu and sequence polling code to a common library. Fixed the issue that prevented keyboard inputs being mapped with -steadykey on.
-docs: Started adding some documentation for MAME's internal UI, and updated the list of example front-ends.
-Regenerated message catalog sources. For translators, the new strings are mostly:
* The names of the inputs provided by the OS-dependent layer for things like fullscreen and video features. These show up in the user interface inputs menu.
* The names for automatically generated views. These show up in the video options menu - test with a system with a lot of screens to see more variants.
* The input macro plugin UI.
* A few format strings for analog input assignments.
* A few strings for the about box header.
Diffstat (limited to 'plugins/autofire/autofire_menu.lua')
-rw-r--r-- | plugins/autofire/autofire_menu.lua | 233 |
1 files changed, 79 insertions, 154 deletions
diff --git a/plugins/autofire/autofire_menu.lua b/plugins/autofire/autofire_menu.lua index 18000bfbd99..ec2fd6311cf 100644 --- a/plugins/autofire/autofire_menu.lua +++ b/plugins/autofire/autofire_menu.lua @@ -1,5 +1,8 @@ local lib = {} +-- Common UI helper library +local commonui + -- Set of all menus local MENU_TYPES = { MAIN = 0, EDIT = 1, ADD = 2, BUTTON = 3 } @@ -27,14 +30,17 @@ local configure_menu_active = false -- Saved selection on configure menu (to restore after button menu is dismissed) local configure_selection_save +-- Helper for polling for hotkeys +local hotkey_poller + -- Button being created/edited local current_button = {} -- Initial button to select when opening buttons menu local initial_input --- Inputs that can be autofired (to list in BUTTON menu) -local inputs +-- Handler for BUTTON menu +local input_menu -- Returns the section (from MENU_SECTIONS) and the index within that section local function menu_section(index) @@ -59,19 +65,14 @@ local function is_button_complete(button) return button.port and button.field and button.key and button.on_frames and button.off_frames and button.button and button.counter end -local function is_supported_input(ioport_field) - -- IPT_BUTTON1 through IPT_BUTTON16 in ioport_type enum (ioport.h) - return ioport_field.type >= 64 and ioport_field.type <= 79 -end - -- Main menu local function populate_main_menu(buttons) local ioport = manager.machine.ioport local input = manager.machine.input local menu = {} - menu[#menu + 1] = {_('Autofire buttons'), '', 'off'} - menu[#menu + 1] = {string.format(_('Press %s to delete'), input:seq_name(ioport:type_seq(ioport:token_to_input_type('UI_CLEAR')))), '', 'off'} + menu[#menu + 1] = {_p('plugin-autofire', 'Autofire buttons'), '', 'off'} + menu[#menu + 1] = {string.format(_p('plugin-autofire', 'Press %s to delete'), manager.ui:get_general_input_setting(ioport:token_to_input_type('UI_CLEAR'))), '', 'off'} menu[#menu + 1] = {'---', '', ''} header_height = #menu @@ -82,22 +83,26 @@ local function populate_main_menu(buttons) freq = 1 / screen.frame_period end - for index, button in ipairs(buttons) do - -- Round rate to two decimal places - local rate = freq / (button.on_frames + button.off_frames) - rate = math.floor(rate * 100) / 100 - local text = string.format(_('%s [%g Hz]'), _p('input-name', button.button.name), rate) - local subtext = input:seq_name(button.key) - menu[#menu + 1] = {text, subtext, ''} - if index == initial_button then - main_selection_save = #menu + if #buttons > 0 then + for index, button in ipairs(buttons) do + -- Round rate to two decimal places + local rate = freq / (button.on_frames + button.off_frames) + rate = math.floor(rate * 100) / 100 + local text = string.format(_p('plugin-autofire', '%s [%g Hz]'), _p('input-name', button.button.name), rate) + local subtext = input:seq_name(button.key) + menu[#menu + 1] = {text, subtext, ''} + if index == initial_button then + main_selection_save = #menu + end end + else + menu[#menu + 1] = {_p('plugin-autofire', '[no autofire buttons]'), '', 'off'} end initial_button = nil content_height = #menu menu[#menu + 1] = {'---', '', ''} - menu[#menu + 1] = {_('Add autofire button'), '', ''} + menu[#menu + 1] = {_p('plugin-autofire', 'Add autofire button'), '', ''} local selection = main_selection_save main_selection_save = nil @@ -134,67 +139,53 @@ end -- Add/edit menus (mostly identical) local function populate_configure_menu(menu) - local button_name = current_button.button and _p('input-name', current_button.button.name) or _('NOT SET') - local key_name = current_button.key and manager.machine.input:seq_name(current_button.key) or _('NOT SET') - menu[#menu + 1] = {_('Input'), button_name, ''} + local button_name = current_button.button and _p('input-name', current_button.button.name) or _p('plugin-autofire', '[not set]') + local key_name = current_button.key and manager.machine.input:seq_name(current_button.key) or _p('plugin-autofire', '[not set]') + menu[#menu + 1] = {_p('plugin-autofire', 'Input'), button_name, ''} if not (configure_menu_active or configure_selection_save) then configure_selection_save = #menu end - menu[#menu + 1] = {_('Hotkey'), key_name, ''} - menu[#menu + 1] = {_('On frames'), current_button.on_frames, current_button.on_frames > 1 and 'lr' or 'r'} - menu[#menu + 1] = {_('Off frames'), current_button.off_frames, current_button.off_frames > 1 and 'lr' or 'r'} + menu[#menu + 1] = {_p('plugin-autofire', 'Hotkey'), key_name, hotkey_poller and 'lr' or ''} + menu[#menu + 1] = {_p('plugin-autofire', 'On frames'), current_button.on_frames, current_button.on_frames > 1 and 'lr' or 'r'} + menu[#menu + 1] = {_p('plugin-autofire', 'Off frames'), current_button.off_frames, current_button.off_frames > 1 and 'lr' or 'r'} configure_menu_active = true end --- Borrowed from the cheat plugin -local function poll_for_hotkey() - local input = manager.machine.input - local poller = input:switch_sequence_poller() - manager.machine:popmessage(_('Press button for hotkey or wait to leave unchanged')) - manager.machine.video:frame_update() - poller:start() - local time = os.clock() - local clearmsg = true - while (not poller:poll()) and (poller.modified or (os.clock() < time + 1)) do - if poller.modified then - if not poller.valid then - manager.machine:popmessage(_('Invalid sequence entered')) - clearmsg = false - break +local function handle_configure_menu(index, event) + if hotkey_poller then + -- special handling for polling for hotkey + if hotkey_poller:poll() then + if hotkey_poller.sequence then + current_button.key = hotkey_poller.sequence end - manager.machine:popmessage(input:seq_name(poller.sequence)) - manager.machine.video:frame_update() + hotkey_poller = nil + return true end + return false end - if clearmsg then - manager.machine:popmessage() - end - return poller.valid and poller.sequence or nil -end -local function handle_configure_menu(index, event) if index == 1 then -- Input if event == 'select' then configure_selection_save = header_height + index table.insert(menu_stack, MENU_TYPES.BUTTON) if current_button.port and current_button.field then - initial_input = {port_name = current_button.port, ioport_field = current_button.button} + initial_input = current_button.button end return true end elseif index == 2 then -- Hotkey if event == 'select' then - local keycode = poll_for_hotkey() - if keycode then - current_button.key = keycode - return true + if not commonui then + commonui = require('commonui') end + hotkey_poller = commonui.switch_polling_helper() + return true end elseif index == 3 then -- On frames - manager.machine:popmessage(_('Number of frames button will be pressed')) + manager.machine:popmessage(_p('plugin-autofire', 'Number of frames button will be pressed')) if event == 'left' then current_button.on_frames = current_button.on_frames - 1 return true @@ -207,7 +198,7 @@ local function handle_configure_menu(index, event) end elseif index == 4 then -- Off frames - manager.machine:popmessage(_('Number of frames button will be released')) + manager.machine:popmessage(_p('plugin-autofire', 'Number of frames button will be released')) if event == 'left' then current_button.off_frames = current_button.off_frames - 1 return true @@ -224,7 +215,7 @@ end local function populate_edit_menu() local menu = {} - menu[#menu + 1] = {_('Edit autofire button'), '', 'off'} + menu[#menu + 1] = {_p('plugin-autofire', 'Edit autofire button'), '', 'off'} menu[#menu + 1] = {'---', '', ''} header_height = #menu @@ -232,17 +223,20 @@ local function populate_edit_menu() content_height = #menu menu[#menu + 1] = {'---', '', ''} - menu[#menu + 1] = {_('Done'), '', ''} + menu[#menu + 1] = {_p('plugin-autofire', 'Done'), '', ''} local selection = configure_selection_save configure_selection_save = nil - return menu, selection, 'lrrepeat' + if hotkey_poller then + return hotkey_poller:overlay(menu, selection, 'lrrepeat') + else + return menu, selection, 'lrrepeat' + end end local function handle_edit_menu(index, event, buttons) local section, adjusted_index = menu_section(index) if ((section == MENU_SECTIONS.FOOTER) and (event == 'select')) or (event == 'cancel') then - inputs = nil configure_menu_active = false table.remove(menu_stack) return true @@ -254,7 +248,7 @@ end local function populate_add_menu() local menu = {} - menu[#menu + 1] = {_('Add autofire button'), '', 'off'} + menu[#menu + 1] = {_p('plugin-autofire', 'Add autofire button'), '', 'off'} menu[#menu + 1] = {'---', '', ''} header_height = #menu @@ -263,20 +257,23 @@ local function populate_add_menu() menu[#menu + 1] = {'---', '', ''} if is_button_complete(current_button) then - menu[#menu + 1] = {_('Create'), '', ''} + menu[#menu + 1] = {_p('plugin-autofire', 'Create'), '', ''} else - menu[#menu + 1] = {_('Cancel'), '', ''} + menu[#menu + 1] = {_p('plugin-autofire', 'Cancel'), '', ''} end local selection = configure_selection_save configure_selection_save = nil - return menu, selection, 'lrrepeat' + if hotkey_poller then + return hotkey_poller:overlay(menu, selection, 'lrrepeat') + else + return menu, selection, 'lrrepeat' + end end local function handle_add_menu(index, event, buttons) local section, adjusted_index = menu_section(index) if ((section == MENU_SECTIONS.FOOTER) and (event == 'select')) or (event == 'cancel') then - inputs = nil configure_menu_active = false table.remove(menu_stack) if is_button_complete(current_button) and (event == 'select') then @@ -293,103 +290,31 @@ end -- Button selection menu local function populate_button_menu() - local ioport = manager.machine.ioport - menu = {} - menu[#menu + 1] = {_('Select an input for autofire'), '', 'off'} - menu[#menu + 1] = {'---', '', ''} - header_height = #menu - - if not inputs then - inputs = {} - - for port_key, port in pairs(ioport.ports) do - for field_key, field in pairs(port.fields) do - if is_supported_input(field) then - inputs[#inputs + 1] = { - port_name = port_key, - field_name = field_key, - ioport_field = field - } - end - end - end - - local function compare(x, y) - if x.ioport_field.device.tag < y.ioport_field.device.tag then - return true - elseif x.ioport_field.device.tag > y.ioport_field.device.tag then - return false - end - groupx = ioport:type_group(x.ioport_field.type, x.ioport_field.player) - groupy = ioport:type_group(y.ioport_field.type, y.ioport_field.player) - if groupx < groupy then - return true - elseif groupx > groupy then - return false - elseif x.ioport_field.type < y.ioport_field.type then - return true - elseif x.ioport_field.type > y.ioport_field.type then - return false - else - return x.ioport_field.name < y.ioport_field.name - end - end - table.sort(inputs, compare) - - local i = 1 - local prev - while i <= #inputs do - local current = inputs[i] - if (not prev) or (prev.ioport_field.device.tag ~= current.ioport_field.device.tag) then - table.insert(inputs, i, false) - i = i + 2 - else - i = i + 1 - end - prev = current - end + local function is_supported_input(ioport_field) + -- IPT_BUTTON1 through IPT_BUTTON16 in ioport_type enum (ioport.h) + return ioport_field.type >= 64 and ioport_field.type <= 79 end - local selection = header_height + 1 - for i, input in ipairs(inputs) do - if input then - menu[header_height + i] = { _p('input-name', input.ioport_field.name), '', '' } - if initial_input and (initial_input.port_name == input.port_name) and (initial_input.ioport_field.mask == input.ioport_field.mask) and (initial_input.ioport_field.type == input.ioport_field.type) then - selection = header_height + i - initial_input = nil - end - else - local device = inputs[i + 1].ioport_field.device - if device.owner then - menu[header_height + i] = {string.format(_('%s [root%s]'), device.name, device.tag), '', 'heading'} - else - menu[header_height + i] = {string.format(_('[root%s]'), device.tag), '', 'heading'} - end + local function action(field) + if field then + current_button.port = field.port.tag + current_button.field = field.name + current_button.button = field end + initial_input = nil + input_menu = nil + table.remove(menu_stack) end - content_height = #menu - initial_input = nil - - menu[#menu + 1] = {'---', '', ''} - menu[#menu + 1] = {_('Cancel'), '', ''} - return menu, selection + if not commonui then + commonui = require('commonui') + end + input_menu = commonui.input_selection_menu(action, _p('plugin-autofire', 'Select an input for autofire'), is_supported_input) + return input_menu:populate(initial_input) end local function handle_button_menu(index, event) - local section, adjusted_index = menu_section(index) - if ((section == MENU_SECTIONS.FOOTER) and (event == 'select')) or (event == 'cancel') then - table.remove(menu_stack) - return true - elseif (section == MENU_SECTIONS.CONTENT) and (event == 'select') then - local selected_input = inputs[adjusted_index] - current_button.port = selected_input.port_name - current_button.field = selected_input.field_name - current_button.button = selected_input.ioport_field - table.remove(menu_stack) - return true - end - return false + return input_menu:handle(index, event) end function lib:init_menu(buttons) @@ -397,7 +322,7 @@ function lib:init_menu(buttons) content_height = 0 menu_stack = { MENU_TYPES.MAIN } current_button = {} - inputs = nil + input_menu = nil end function lib:populate_menu(buttons) |