mirror of
https://github.com/mamedev/mame.git
synced 2024-11-18 10:06:19 +01:00
d4589e0b29
osd/modules/input, emu/inpttype.cpp: Made most default joystick assignments supplied by input modules. Input modules take available controls into consideration when generating default assignments. emu/inpttype.ipp: Added a separate "Back" UI input separate from Cancel. You may want an easier to hit combination for moving to the previous menu than for exiting or cancelling input. They both default to Escape. emu/inpttype.ipp: Added a UI Help control. Currently only used by analog inputs menu emu/inpttype.h: Moved I/O port field type enum to its own header and sorted UI controls so they appear in a more logical order. ui: Don't use UI Select to restore defaults - people should be getting used to the UI Clear input by now. UI Select cycles multi-value items instead. ui/inputmap.cpp: Don't use immediate cancel to cycle between clearing and restoring default assignment (use UI Clear instead). osd: Reduced the number of files needing to include the dreaded emu.h. Got some implementation out of headers.
368 lines
11 KiB
Lua
368 lines
11 KiB
Lua
local lib = {}
|
|
|
|
-- Common UI helper library
|
|
local commonui
|
|
|
|
-- Set of all menus
|
|
local MENU_TYPES = { MAIN = 0, EDIT = 1, ADD = 2, BUTTON = 3 }
|
|
|
|
-- Set of sections within a menu
|
|
local MENU_SECTIONS = { HEADER = 0, CONTENT = 1, FOOTER = 2 }
|
|
|
|
-- Last index of header items (above main content) in menu
|
|
local header_height = 0
|
|
|
|
-- Last index of content items (below header, above footer) in menu
|
|
local content_height = 0
|
|
|
|
-- Stack of menus (see MENU_TYPES)
|
|
local menu_stack = { MENU_TYPES.MAIN }
|
|
|
|
-- Button to select when showing the main menu (so newly added button can be selected)
|
|
local initial_button
|
|
|
|
-- Saved selection on main menu (to restore after configure menu is dismissed)
|
|
local main_selection_save
|
|
|
|
-- Whether configure menu is active (so first item can be selected initially)
|
|
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
|
|
|
|
-- Handler for BUTTON menu
|
|
local input_menu
|
|
|
|
-- Returns the section (from MENU_SECTIONS) and the index within that section
|
|
local function menu_section(index)
|
|
if index <= header_height then
|
|
return MENU_SECTIONS.HEADER, index
|
|
elseif index <= content_height then
|
|
return MENU_SECTIONS.CONTENT, index - header_height
|
|
else
|
|
return MENU_SECTIONS.FOOTER, index - content_height
|
|
end
|
|
end
|
|
|
|
local function create_new_button()
|
|
return {
|
|
on_frames = 1,
|
|
off_frames = 1,
|
|
counter = 0
|
|
}
|
|
end
|
|
|
|
local function is_button_complete(button)
|
|
return button.port and button.mask and button.type and button.key and button.on_frames and button.off_frames and button.button and button.counter
|
|
end
|
|
|
|
-- Main menu
|
|
|
|
local function populate_main_menu(buttons)
|
|
local ioport = manager.machine.ioport
|
|
local input = manager.machine.input
|
|
local menu = {}
|
|
table.insert(menu, {_p('plugin-autofire', 'Autofire buttons'), '', 'off'})
|
|
table.insert(menu, {string.format(_p('plugin-autofire', 'Press %s to delete'), manager.ui:get_general_input_setting(ioport:token_to_input_type('UI_CLEAR'))), '', 'off'})
|
|
table.insert(menu, {'---', '', ''})
|
|
header_height = #menu
|
|
|
|
-- Use frame rate of first screen or 60Hz if no screens
|
|
local freq = 60
|
|
local screen = manager.machine.screens:at(1)
|
|
if screen then
|
|
freq = 1 / screen.frame_period
|
|
end
|
|
|
|
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
|
|
if button.button then
|
|
text = string.format(_p('plugin-autofire', '%s [%g Hz]'), button.button.name, rate)
|
|
else
|
|
text = string.format(_p('plugin-autofire', 'n/a [%g Hz]'), rate)
|
|
end
|
|
table.insert(menu, {text, input:seq_name(button.key), ''})
|
|
if index == initial_button then
|
|
main_selection_save = #menu
|
|
end
|
|
end
|
|
else
|
|
table.insert(menu, {_p('plugin-autofire', '[no autofire buttons]'), '', 'off'})
|
|
end
|
|
initial_button = nil
|
|
content_height = #menu
|
|
|
|
table.insert(menu, {'---', '', ''})
|
|
table.insert(menu, {_p('plugin-autofire', 'Add autofire button'), '', ''})
|
|
|
|
local selection = main_selection_save
|
|
main_selection_save = nil
|
|
return menu, selection
|
|
end
|
|
|
|
local function handle_main_menu(index, event, buttons)
|
|
local section, adjusted_index = menu_section(index)
|
|
if section == MENU_SECTIONS.CONTENT then
|
|
if event == 'select' then
|
|
main_selection_save = index
|
|
current_button = buttons[adjusted_index]
|
|
table.insert(menu_stack, MENU_TYPES.EDIT)
|
|
return true
|
|
elseif event == 'clear' then
|
|
table.remove(buttons, adjusted_index)
|
|
main_selection_save = index
|
|
if adjusted_index > #buttons then
|
|
main_selection_save = main_selection_save - 1
|
|
end
|
|
return true
|
|
end
|
|
elseif section == MENU_SECTIONS.FOOTER then
|
|
if event == 'select' then
|
|
main_selection_save = index
|
|
current_button = create_new_button()
|
|
table.insert(menu_stack, MENU_TYPES.ADD)
|
|
return true
|
|
end
|
|
end
|
|
return false
|
|
end
|
|
|
|
-- Add/edit menus (mostly identical)
|
|
|
|
local function populate_configure_menu(menu)
|
|
local button_name
|
|
if current_button.button then
|
|
button_name = current_button.button.name
|
|
elseif current_button.port then
|
|
button_name = _p('plugin-autofire', 'n/a')
|
|
else
|
|
button_name = _p('plugin-autofire', '[not set]')
|
|
end
|
|
local key_name = current_button.key and manager.machine.input:seq_name(current_button.key) or _p('plugin-autofire', '[not set]')
|
|
table.insert(menu, {_p('plugin-autofire', 'Input'), button_name, ''})
|
|
if not (configure_menu_active or configure_selection_save) then
|
|
configure_selection_save = #menu
|
|
end
|
|
table.insert(menu, {_p('plugin-autofire', 'Hotkey'), key_name, hotkey_poller and 'lr' or ''})
|
|
table.insert(menu, {_p('plugin-autofire', 'On frames'), tostring(current_button.on_frames), current_button.on_frames > 1 and 'lr' or 'r'})
|
|
table.insert(menu, {_p('plugin-autofire', 'Off frames'), tostring(current_button.off_frames), current_button.off_frames > 1 and 'lr' or 'r'})
|
|
configure_menu_active = true
|
|
end
|
|
|
|
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
|
|
current_button.key_cfg = manager.machine.input:seq_to_tokens(hotkey_poller.sequence)
|
|
end
|
|
hotkey_poller = nil
|
|
return true
|
|
end
|
|
return false
|
|
end
|
|
|
|
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.button then
|
|
initial_input = current_button.button
|
|
end
|
|
return true
|
|
end
|
|
elseif index == 2 then
|
|
-- Hotkey
|
|
if event == 'select' then
|
|
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(_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
|
|
elseif event == 'right' then
|
|
current_button.on_frames = current_button.on_frames + 1
|
|
return true
|
|
elseif event == 'clear' then
|
|
current_button.on_frames = 1
|
|
return true
|
|
end
|
|
elseif index == 4 then
|
|
-- Off frames
|
|
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
|
|
elseif event == 'right' then
|
|
current_button.off_frames = current_button.off_frames + 1
|
|
return true
|
|
elseif event == 'clear' then
|
|
current_button.off_frames = 1
|
|
return true
|
|
end
|
|
end
|
|
return false
|
|
end
|
|
|
|
local function populate_edit_menu()
|
|
local menu = {}
|
|
table.insert(menu, {_p('plugin-autofire', 'Edit autofire button'), '', 'off'})
|
|
table.insert(menu, {'---', '', ''})
|
|
header_height = #menu
|
|
|
|
populate_configure_menu(menu)
|
|
content_height = #menu
|
|
|
|
table.insert(menu, {'---', '', ''})
|
|
table.insert(menu, {_p('plugin-autofire', 'Done'), '', ''})
|
|
|
|
local selection = configure_selection_save
|
|
configure_selection_save = nil
|
|
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 == 'back') then
|
|
configure_menu_active = false
|
|
table.remove(menu_stack)
|
|
return true
|
|
elseif section == MENU_SECTIONS.CONTENT then
|
|
return handle_configure_menu(adjusted_index, event)
|
|
end
|
|
return false
|
|
end
|
|
|
|
local function populate_add_menu()
|
|
local menu = {}
|
|
table.insert(menu, {_p('plugin-autofire', 'Add autofire button'), '', 'off'})
|
|
table.insert(menu, {'---', '', ''})
|
|
header_height = #menu
|
|
|
|
populate_configure_menu(menu)
|
|
content_height = #menu
|
|
|
|
table.insert(menu, {'---', '', ''})
|
|
if is_button_complete(current_button) then
|
|
table.insert(menu, {_p('plugin-autofire', 'Create'), '', ''})
|
|
else
|
|
table.insert(menu, {_p('plugin-autofire', 'Cancel'), '', ''})
|
|
end
|
|
|
|
local selection = configure_selection_save
|
|
configure_selection_save = nil
|
|
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 == 'back') then
|
|
configure_menu_active = false
|
|
table.remove(menu_stack)
|
|
if is_button_complete(current_button) and (event == 'select') then
|
|
table.insert(buttons, current_button)
|
|
initial_button = #buttons
|
|
end
|
|
return true
|
|
elseif section == MENU_SECTIONS.CONTENT then
|
|
return handle_configure_menu(adjusted_index, event)
|
|
end
|
|
return false
|
|
end
|
|
|
|
-- Button selection menu
|
|
|
|
local function populate_button_menu()
|
|
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 function action(field)
|
|
if field then
|
|
current_button.port = field.port.tag
|
|
current_button.mask = field.mask
|
|
current_button.type = field.type
|
|
current_button.button = field
|
|
end
|
|
initial_input = nil
|
|
input_menu = nil
|
|
table.remove(menu_stack)
|
|
end
|
|
|
|
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)
|
|
return input_menu:handle(index, event)
|
|
end
|
|
|
|
function lib:init_menu(buttons)
|
|
header_height = 0
|
|
content_height = 0
|
|
menu_stack = { MENU_TYPES.MAIN }
|
|
current_button = {}
|
|
input_menu = nil
|
|
end
|
|
|
|
function lib:populate_menu(buttons)
|
|
local current_menu = menu_stack[#menu_stack]
|
|
if current_menu == MENU_TYPES.MAIN then
|
|
return populate_main_menu(buttons)
|
|
elseif current_menu == MENU_TYPES.EDIT then
|
|
return populate_edit_menu()
|
|
elseif current_menu == MENU_TYPES.ADD then
|
|
return populate_add_menu()
|
|
elseif current_menu == MENU_TYPES.BUTTON then
|
|
return populate_button_menu()
|
|
end
|
|
end
|
|
|
|
function lib:handle_menu_event(index, event, buttons)
|
|
manager.machine:popmessage()
|
|
local current_menu = menu_stack[#menu_stack]
|
|
if current_menu == MENU_TYPES.MAIN then
|
|
return handle_main_menu(index, event, buttons)
|
|
elseif current_menu == MENU_TYPES.EDIT then
|
|
return handle_edit_menu(index, event, buttons)
|
|
elseif current_menu == MENU_TYPES.ADD then
|
|
return handle_add_menu(index, event, buttons)
|
|
elseif current_menu == MENU_TYPES.BUTTON then
|
|
return handle_button_menu(index, event)
|
|
end
|
|
end
|
|
|
|
return lib
|