From f459eb6e137252301fefeff443d10ae8b9a69828 Mon Sep 17 00:00:00 2001 From: Vas Crabb Date: Fri, 22 Oct 2021 01:14:05 +1100 Subject: Plugin usability improvements: * autofire, inputmacro: Made left/right repeat when held (makes setting long delays/durations easier). * autofire, inputmacro: Added headings for devices in input selection menus (helps when controller buttons have identical names, e.g. AES) * autofire: Made intial selection when moving between menus intuitive, log some errors on saving/loading configuration. * autofire: Fixed two errors in Chinese localisations. --- language/Chinese_Simplified/strings.po | 4 +- language/Chinese_Traditional/strings.po | 4 +- plugins/autofire/autofire_menu.lua | 172 ++++++++++++++++++++++++-------- plugins/autofire/autofire_save.lua | 16 ++- plugins/inputmacro/inputmacro_menu.lua | 48 +++++++-- src/frontend/mame/luaengine.cpp | 16 +-- src/frontend/mame/luaengine.h | 4 +- src/frontend/mame/ui/menu.h | 2 +- src/frontend/mame/ui/pluginopt.cpp | 103 +++++++++++++------ src/frontend/mame/ui/pluginopt.h | 7 +- 10 files changed, 277 insertions(+), 99 deletions(-) diff --git a/language/Chinese_Simplified/strings.po b/language/Chinese_Simplified/strings.po index 26832773750..a6acc3d2240 100644 --- a/language/Chinese_Simplified/strings.po +++ b/language/Chinese_Simplified/strings.po @@ -6697,7 +6697,7 @@ msgstr "总计发现 %d 符合" #: plugins/cheatfind/init.lua:623 #, lua-format msgid "Perform Compare : Slot %d %s Slot %d" -msgstr "执行比较:插槽 $d %s 插槽 %d" +msgstr "执行比较:插槽 %d %s 插槽 %d" #: plugins/cheatfind/init.lua:624 #, lua-format @@ -6886,7 +6886,7 @@ msgstr "连发按钮" #: plugins/autofire/autofire_menu.lua:59 #, lua-format msgid "Press %s to delete" -msgstr "按下 $s 删除" +msgstr "按下 %s 删除" #: plugins/autofire/autofire_menu.lua:68 #, lua-format diff --git a/language/Chinese_Traditional/strings.po b/language/Chinese_Traditional/strings.po index f124a63946b..92a58274f58 100644 --- a/language/Chinese_Traditional/strings.po +++ b/language/Chinese_Traditional/strings.po @@ -6697,7 +6697,7 @@ msgstr "總計發現 %d 符合" #: plugins/cheatfind/init.lua:623 #, lua-format msgid "Perform Compare : Slot %d %s Slot %d" -msgstr "執行比較:插槽 $d %s 插槽 %d" +msgstr "執行比較:插槽 %d %s 插槽 %d" #: plugins/cheatfind/init.lua:624 #, lua-format @@ -6886,7 +6886,7 @@ msgstr "連射按鈕" #: plugins/autofire/autofire_menu.lua:59 #, lua-format msgid "Press %s to delete" -msgstr "按下 $s 刪除" +msgstr "按下 %s 刪除" #: plugins/autofire/autofire_menu.lua:68 #, lua-format diff --git a/plugins/autofire/autofire_menu.lua b/plugins/autofire/autofire_menu.lua index c9afa90e94f..18000bfbd99 100644 --- a/plugins/autofire/autofire_menu.lua +++ b/plugins/autofire/autofire_menu.lua @@ -15,11 +15,26 @@ 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 + -- 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 = {} +local inputs -- Returns the section (from MENU_SECTIONS) and the index within that section local function menu_section(index) @@ -60,35 +75,54 @@ local function populate_main_menu(buttons) menu[#menu + 1] = {'---', '', ''} 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 + for index, button in ipairs(buttons) do - -- Assume refresh rate of 60 Hz; maybe better to use screen_device refresh()? - local rate = 60 / (button.on_frames + button.off_frames) - -- Round to two decimal places + -- 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 [%d Hz]'), _p('input-name', button.button.name), rate) + 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 + end end + initial_button = nil content_height = #menu menu[#menu + 1] = {'---', '', ''} menu[#menu + 1] = {_('Add autofire button'), '', ''} - return menu + + 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 @@ -103,9 +137,13 @@ 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, ''} + 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'} + configure_menu_active = true end -- Borrowed from the cheat plugin @@ -138,7 +176,11 @@ 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} + end return true end elseif index == 2 then @@ -159,6 +201,9 @@ local function handle_configure_menu(index, event) 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 @@ -169,6 +214,9 @@ local function handle_configure_menu(index, event) 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 @@ -185,12 +233,17 @@ local function populate_edit_menu() menu[#menu + 1] = {'---', '', ''} menu[#menu + 1] = {_('Done'), '', ''} - return menu + + local selection = configure_selection_save + configure_selection_save = nil + return menu, selection, 'lrrepeat' 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 elseif section == MENU_SECTIONS.CONTENT then @@ -214,15 +267,21 @@ local function populate_add_menu() else menu[#menu + 1] = {_('Cancel'), '', ''} end - return menu + + local selection = configure_selection_save + configure_selection_save = nil + return menu, selection, 'lrrepeat' 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 - buttons[#buttons + 1] = current_button + table.insert(buttons, current_button) + initial_button = #buttons end return true elseif section == MENU_SECTIONS.CONTENT then @@ -236,54 +295,85 @@ end local function populate_button_menu() local ioport = manager.machine.ioport menu = {} - inputs = {} menu[#menu + 1] = {_('Select an input for autofire'), '', 'off'} menu[#menu + 1] = {'---', '', ''} header_height = #menu - 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 - } + 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 - 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 + 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 - 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 + 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 end - table.sort(inputs, compare) - for i, input in pairs(inputs) do - menu[header_height + i] = { _p('input-name', input.ioport_field.name), '', '' } + 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 + end end content_height = #menu + initial_input = nil menu[#menu + 1] = {'---', '', ''} menu[#menu + 1] = {_('Cancel'), '', ''} - return menu + return menu, selection end local function handle_button_menu(index, event) @@ -307,7 +397,7 @@ function lib:init_menu(buttons) content_height = 0 menu_stack = { MENU_TYPES.MAIN } current_button = {} - inputs = {} + inputs = nil end function lib:populate_menu(buttons) diff --git a/plugins/autofire/autofire_save.lua b/plugins/autofire/autofire_save.lua index e75b44c71e3..3692540cd5b 100644 --- a/plugins/autofire/autofire_save.lua +++ b/plugins/autofire/autofire_save.lua @@ -50,13 +50,15 @@ end function lib:load_settings() local buttons = {} local json = require('json') - local file = io.open(get_settings_path() .. get_settings_filename(), 'r') + local filename = get_settings_path() .. get_settings_filename() + local file = io.open(filename, 'r') if not file then return buttons end local loaded_settings = json.parse(file:read('a')) file:close() if not loaded_settings then + emu.print_error(string.format('Error loading autofire settings: error parsing file "%s" as JSON\n', filename)) return buttons end for index, button_settings in ipairs(loaded_settings) do @@ -74,6 +76,7 @@ function lib:save_settings(buttons) if not attr then lfs.mkdir(path) elseif attr.mode ~= 'directory' then + emu.print_error(string.format('Error autofire settings macros: "%s" is not a directory\n', path)) return end if #buttons == 0 then @@ -83,11 +86,14 @@ function lib:save_settings(buttons) local json = require('json') local settings = serialize_settings(buttons) local data = json.stringify(settings, {indent = true}) - local file = io.open(path .. get_settings_filename(), 'w') - if file then - file:write(data) - file:close() + local filename = path .. get_settings_filename() + local file = io.open(filename, 'w') + if not file then + emu.print_error(string.format('Error saving autofire settings: error opening file "%s" for writing\n', filename)) + return end + file:write(data) + file:close() end return lib diff --git a/plugins/inputmacro/inputmacro_menu.lua b/plugins/inputmacro/inputmacro_menu.lua index 8b62148ab67..24c8caff29e 100644 --- a/plugins/inputmacro/inputmacro_menu.lua +++ b/plugins/inputmacro/inputmacro_menu.lua @@ -114,20 +114,42 @@ function populate_input() for tag, port in pairs(manager.machine.ioport.ports) do for name, field in pairs(port.fields) do if supported(field) then - input_choices[#input_choices + 1] = field + table.insert(input_choices, field) end end end table.sort(input_choices, compare) + + local index = 1 + local prev + while index <= #input_choices do + local current = input_choices[index] + if (not prev) or (prev.device.tag ~= current.device.tag) then + table.insert(input_choices, index, false) + index = index + 2 + else + index = index + 1 + end + prev = current + end end input_item_first_choice = #items + 1 local selection = input_item_first_choice for index, field in ipairs(input_choices) do - items[#items + 1] = { _p('input-name', field.name), '', '' } - if input_start_field and (field.port.tag == input_start_field.port.tag) and (field.mask == input_start_field.mask) and (field.type == input_start_field.type) then - selection = #items - input_start_field = nil + if field then + items[#items + 1] = { _p('input-name', field.name), '', '' } + if input_start_field and (field.port.tag == input_start_field.port.tag) and (field.mask == input_start_field.mask) and (field.type == input_start_field.type) then + selection = #items + input_start_field = nil + end + else + local device = input_choices[index + 1].device + if device.owner then + items[#items + 1] = { string.format(_('plugin-inputmacro', '%s [root%s]'), device.name, device.tag), '', 'heading' } + else + items[#items + 1] = { string.format(_('plugin-inputmacro', '[root%s]'), device.tag), '', 'heading' } + end end end input_start_field = nil @@ -145,6 +167,7 @@ end local edit_current_macro local edit_start_selection local edit_start_step +local edit_menu_active local edit_insert_position local edit_name_buffer local edit_items @@ -379,6 +402,10 @@ local function add_edit_items(items) items[#items + 1] = { _p('plugin-inputmacro', 'Name'), edit_name_buffer and (edit_name_buffer .. '_') or edit_current_macro.name, '' } edit_items[#items] = { action = 'name' } + if not (edit_start_selection or edit_start_step or edit_menu_active) then + edit_start_selection = #items + end + edit_menu_active = true local binding = edit_current_macro.binding local activation = binding and input:seq_name(binding) or _p('plugin-inputmacro', '[not set]') @@ -453,7 +480,9 @@ local function handle_add(index, event) if handle_edit_items(index, event) then return true elseif event == 'cancel' then + input_choices = nil edit_current_macro = nil + edit_menu_active = false edit_items = nil table.remove(menu_stack) return true @@ -462,6 +491,8 @@ local function handle_add(index, event) table.insert(macros, edit_current_macro) macros_start_macro = #macros end + input_choices = nil + edit_menu_active = false edit_current_macro = nil edit_items = nil table.remove(menu_stack) @@ -474,7 +505,9 @@ local function handle_edit(index, event) if handle_edit_items(index, event) then return true elseif (event == 'cancel') or ((index == edit_item_exit) and (event == 'select')) then + input_choices = nil edit_current_macro = nil + edit_menu_active = false edit_items = nil table.remove(menu_stack) return true @@ -500,7 +533,7 @@ local function populate_add() local selection = edit_start_selection edit_start_selection = nil - return items, selection + return items, selection, 'lrrepeat' end local function populate_edit() @@ -517,7 +550,7 @@ local function populate_edit() local selection = edit_start_selection edit_start_selection = nil - return items, selection + return items, selection, 'lrrepeat' end @@ -532,7 +565,6 @@ function handle_macros(index, event) if event == 'select' then edit_current_macro = new_macro() edit_insert_position = #edit_current_macro.steps + 1 - edit_start_selection = 1 -- not actually selectable, but it will take the first item macros_selection_save = index table.insert(menu_stack, MENU_TYPES.ADD) return true diff --git a/src/frontend/mame/luaengine.cpp b/src/frontend/mame/luaengine.cpp index 9169bdc9f50..e8e246b5efc 100644 --- a/src/frontend/mame/luaengine.cpp +++ b/src/frontend/mame/luaengine.cpp @@ -432,7 +432,7 @@ sol::object lua_engine::call_plugin(const std::string &name, sol::object in) return sol::lua_nil; } -std::optional lua_engine::menu_populate(const std::string &menu, std::vector> &menu_list) +std::optional lua_engine::menu_populate(const std::string &menu, std::vector > &menu_list, std::string &flags) { std::string field = "menu_pop_" + menu; sol::object obj = sol().registry()[field]; @@ -446,7 +446,7 @@ std::optional lua_engine::menu_populate(const std::string &menu, std::vect } else { - std::tuple > table = res; + std::tuple, std::string> table = res; for (auto &entry : std::get<0>(table)) { if (entry.second.is()) @@ -455,27 +455,31 @@ std::optional lua_engine::menu_populate(const std::string &menu, std::vect menu_list.emplace_back(enttable.get(1, 2, 3)); } } + flags = std::get<2>(table); return std::get<1>(table); } } + flags.clear(); return std::nullopt; } -bool lua_engine::menu_callback(const std::string &menu, int index, const std::string &event) +std::pair > lua_engine::menu_callback(const std::string &menu, int index, const std::string &event) { std::string field = "menu_cb_" + menu; - bool ret = false; + std::pair > ret(false, std::nullopt); sol::object obj = sol().registry()[field]; - if(obj.is()) + if (obj.is()) { auto res = invoke(obj.as(), index, event); - if(!res.valid()) + if (!res.valid()) { sol::error err = res; osd_printf_error("[LUA ERROR] in menu_callback: %s\n", err.what()); } else + { ret = res; + } } return ret; } diff --git a/src/frontend/mame/luaengine.h b/src/frontend/mame/luaengine.h index 5b945e864c9..f61baa8c083 100644 --- a/src/frontend/mame/luaengine.h +++ b/src/frontend/mame/luaengine.h @@ -48,8 +48,8 @@ public: bool frame_hook(); - std::optional menu_populate(const std::string &menu, std::vector> &menu_list); - bool menu_callback(const std::string &menu, int index, const std::string &event); + std::optional menu_populate(const std::string &menu, std::vector > &menu_list, std::string &flags); + std::pair > menu_callback(const std::string &menu, int index, const std::string &event); void set_machine(running_machine *machine); std::vector &get_menu() { return m_menu; } diff --git a/src/frontend/mame/ui/menu.h b/src/frontend/mame/ui/menu.h index d8fcbcd25ea..958c1e86af8 100644 --- a/src/frontend/mame/ui/menu.h +++ b/src/frontend/mame/ui/menu.h @@ -37,7 +37,7 @@ class menu { public: // flags for menu items - enum : unsigned + enum : uint32_t { FLAG_LEFT_ARROW = 1U << 0, FLAG_RIGHT_ARROW = 1U << 1, diff --git a/src/frontend/mame/ui/pluginopt.cpp b/src/frontend/mame/ui/pluginopt.cpp index e065582103b..d706780daae 100644 --- a/src/frontend/mame/ui/pluginopt.cpp +++ b/src/frontend/mame/ui/pluginopt.cpp @@ -62,15 +62,17 @@ menu_plugin::~menu_plugin() { } -menu_plugin_opt::menu_plugin_opt(mame_ui_manager &mui, render_container &container, char *menu) : - ui::menu(mui, container), - m_menu(menu) +menu_plugin_opt::menu_plugin_opt(mame_ui_manager &mui, render_container &container, std::string_view menu) : + ui::menu(mui, container), + m_menu(menu), + m_process_flags(0U), + m_need_idle(false) { } void menu_plugin_opt::handle() { - const event *menu_event = process(0); + const event *menu_event = process(m_process_flags); if (menu_event) { @@ -105,9 +107,13 @@ void menu_plugin_opt::handle() key = std::to_string((u32)menu_event->unichar); break; default: - return; + if (!m_need_idle) + return; } - if (mame_machine_manager::instance()->lua()->menu_callback(m_menu, uintptr_t(menu_event->itemref), key)) + auto const result = mame_machine_manager::instance()->lua()->menu_callback(m_menu, uintptr_t(menu_event->itemref), key); + if (result.second) + set_selection(reinterpret_cast(uintptr_t(*result.second))); + if (result.first) reset(reset_options::REMEMBER_REF); else if (menu_event->iptkey == IPT_UI_CANCEL) stack_pop(); @@ -117,41 +123,78 @@ void menu_plugin_opt::handle() void menu_plugin_opt::populate(float &customtop, float &custombottom) { std::vector> menu_list; - auto const sel = mame_machine_manager::instance()->lua()->menu_populate(m_menu, menu_list); + std::string flags; + auto const sel = mame_machine_manager::instance()->lua()->menu_populate(m_menu, menu_list, flags); uintptr_t i = 1; - for(auto &item : menu_list) + for (auto &item : menu_list) { - const std::string &text = std::get<0>(item); - const std::string &subtext = std::get<1>(item); - const std::string &tflags = std::get<2>(item); - - uint32_t flags = 0; - if (tflags == "off") - flags = FLAG_DISABLE; - else if (tflags == "heading") - flags = FLAG_DISABLE | FLAG_UI_HEADING; - else if (tflags == "l") - flags = FLAG_LEFT_ARROW; - else if (tflags == "r") - flags = FLAG_RIGHT_ARROW; - else if (tflags == "lr") - flags = FLAG_RIGHT_ARROW | FLAG_LEFT_ARROW; - - if(text == "---") + std::string &text = std::get<0>(item); + std::string &subtext = std::get<1>(item); + std::string_view tflags = std::get<2>(item); + + uint32_t item_flags_or = uint32_t(0); + uint32_t item_flags_and = ~uint32_t(0); + auto flag_start = tflags.find_first_not_of(' '); + while (std::string_view::npos != flag_start) { - item_append(menu_item_type::SEPARATOR); - i++; + tflags.remove_prefix(flag_start); + auto const flag_end = tflags.find(' '); + auto const flag = tflags.substr(0, flag_end); + tflags.remove_prefix(flag.length()); + flag_start = tflags.find_first_not_of(' '); + + if (flag == "off") + item_flags_or |= FLAG_DISABLE; + else if (flag == "on") + item_flags_and &= ~FLAG_DISABLE; + else if (flag == "l") + item_flags_or |= FLAG_LEFT_ARROW; + else if (flag == "r") + item_flags_or |= FLAG_RIGHT_ARROW; + else if (flag == "lr") + item_flags_or |= FLAG_RIGHT_ARROW | FLAG_LEFT_ARROW; + else if (flag == "invert") + item_flags_or |= FLAG_INVERT; + else if (flag == "heading") + item_flags_or |= FLAG_DISABLE | FLAG_UI_HEADING; } + + if (text == "---") + item_append(menu_item_type::SEPARATOR); else - { - item_append(text, subtext, flags, reinterpret_cast(i++)); - } + item_append(std::move(text), std::move(subtext), item_flags_or & item_flags_and, reinterpret_cast(i)); + ++i; } item_append(menu_item_type::SEPARATOR); if (sel) set_selection(reinterpret_cast(uintptr_t(*sel))); + + m_process_flags = 0U; + m_need_idle = false; + if (!flags.empty()) + { + std::string_view mflags = flags; + auto flag_start = mflags.find_first_not_of(' '); + while (std::string_view::npos != flag_start) + { + mflags.remove_prefix(flag_start); + auto const flag_end = mflags.find(' '); + auto const flag = mflags.substr(0, flag_end); + mflags.remove_prefix(flag.length()); + flag_start = mflags.find_first_not_of(' '); + + if (flag == "lralways") + m_process_flags |= PROCESS_LR_ALWAYS; + else if (flag == "lrrepeat") + m_process_flags |= PROCESS_LR_REPEAT; + else if (flag == "customnav") + m_process_flags |= PROCESS_CUSTOM_NAV; + else if (flag == "idle") + m_need_idle = true; + } + } } menu_plugin_opt::~menu_plugin_opt() diff --git a/src/frontend/mame/ui/pluginopt.h b/src/frontend/mame/ui/pluginopt.h index da2da131792..c639c3caa15 100644 --- a/src/frontend/mame/ui/pluginopt.h +++ b/src/frontend/mame/ui/pluginopt.h @@ -16,6 +16,7 @@ #include "ui/ui.h" #include +#include #include @@ -40,7 +41,7 @@ private: class menu_plugin_opt : public menu { public: - menu_plugin_opt(mame_ui_manager &mui, render_container &container, char *menu); + menu_plugin_opt(mame_ui_manager &mui, render_container &container, std::string_view menu); virtual ~menu_plugin_opt(); protected: @@ -50,7 +51,9 @@ private: virtual void populate(float &customtop, float &custombottom) override; virtual void handle() override; - std::string m_menu; + std::string const m_menu; + uint32_t m_process_flags; + bool m_need_idle; }; } // namespace ui -- cgit v1.2.3