From f47f9c3db3c7d20bea0526425cdbc469d5a10868 Mon Sep 17 00:00:00 2001 From: Vas Crabb Date: Sat, 11 Jun 2022 21:47:19 +1000 Subject: ui, docs: Added menus to fill a couple of gaps, improved consistency. (#9915) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Added menus for controlling toggle inputs, and showing recognised input devices and control state. Moved input menu options off main menu to a submenu, as there are a lot of them now. Moved menu heading drawing into base class, added headings to more menus, and made headings more consistent with the menu items used to reach them. Also made terminology more consistent. Changed the default names for buttons and hat switches/D-pads to use 1-based numbering. DirectInput still returns 0-based button numbers for some devices. Removed local copy of MinGW xaudio2.h as it’s now included in the MSYS2 package. Also fixed building the DirectSound sound output module with the SDL OSD on Windows - the Windows headers are sensitive to include order. Started adding documentation for menus, to hopefully help people find menus they remember seeing but can't recall how to access. For translators, this makes terminology more consistent. In particular: * "Settings" is preferred over "configuration" in a number of places, as the latter can be construed as referring specifically to settings stored in .cfg files in the cfg_directory folder. Also, references to saving machine configuration could be interpreted as relating to the settings on the "Machine Configuration" menu. * The controls on host input devices (e.g. keys, buttons, joystick axes) are referred to as "controls", while emulated inputs are referred to as "inputs". * The menus for assigning host controls to emulated inputs are called "input assignments" menus to distinguish them from other input settings menus. * Combinations of controls that can be assigned to emulated inputs are referred to as "combinations" rather than "sequences". * The potentially confusing term "ROM set" has been removed altogether. Use "short name" to refer to a device or system's identifier. * "System" is used in almost places to refer to a complete, runnable system rather than "Machine". * "Driver" is now only used to refer to source files where systems or devices are defined - it is no longer used to refer to individual systems. * A few more menus have message context for the messages. This makes it a bit easier to guess where the messages are used. It also means you can use different translations in different places if necessary (e.g. if the same English text should be translated differently as an item in one menu and as a heading in another). --- src/frontend/mame/ui/analogipt.cpp | 7 + src/frontend/mame/ui/auditmenu.cpp | 8 +- src/frontend/mame/ui/barcode.cpp | 5 +- src/frontend/mame/ui/confswitch.cpp | 5 +- src/frontend/mame/ui/custui.cpp | 98 ++------- src/frontend/mame/ui/custui.h | 1 - src/frontend/mame/ui/dirmenu.cpp | 370 ++++++++++++++++++--------------- src/frontend/mame/ui/dirmenu.h | 83 +------- src/frontend/mame/ui/filemngr.cpp | 3 +- src/frontend/mame/ui/info.cpp | 25 +-- src/frontend/mame/ui/info_pty.cpp | 4 +- src/frontend/mame/ui/inputdevices.cpp | 258 +++++++++++++++++++++++ src/frontend/mame/ui/inputdevices.h | 34 +++ src/frontend/mame/ui/inputmap.cpp | 37 +++- src/frontend/mame/ui/inputmap.h | 10 +- src/frontend/mame/ui/inputopts.cpp | 141 +++++++++++++ src/frontend/mame/ui/inputopts.h | 37 ++++ src/frontend/mame/ui/inputtoggle.cpp | 219 +++++++++++++++++++ src/frontend/mame/ui/inputtoggle.h | 42 ++++ src/frontend/mame/ui/keyboard.cpp | 7 +- src/frontend/mame/ui/mainmenu.cpp | 94 +++------ src/frontend/mame/ui/menu.cpp | 149 ++++++++----- src/frontend/mame/ui/menu.h | 20 +- src/frontend/mame/ui/miscmenu.cpp | 91 ++++---- src/frontend/mame/ui/miscmenu.h | 7 +- src/frontend/mame/ui/optsmenu.cpp | 84 +++----- src/frontend/mame/ui/optsmenu.h | 4 +- src/frontend/mame/ui/pluginopt.cpp | 1 + src/frontend/mame/ui/selector.cpp | 71 ++++--- src/frontend/mame/ui/selector.h | 13 +- src/frontend/mame/ui/selgame.cpp | 6 +- src/frontend/mame/ui/selmenu.cpp | 63 ++---- src/frontend/mame/ui/selsoft.cpp | 2 +- src/frontend/mame/ui/simpleselgame.cpp | 6 +- src/frontend/mame/ui/sliders.cpp | 1 + src/frontend/mame/ui/slotopt.cpp | 3 +- src/frontend/mame/ui/sndmenu.cpp | 20 +- src/frontend/mame/ui/sndmenu.h | 1 - src/frontend/mame/ui/state.cpp | 10 +- src/frontend/mame/ui/state.h | 1 - src/frontend/mame/ui/submenu.cpp | 12 +- src/frontend/mame/ui/tapectrl.cpp | 1 + src/frontend/mame/ui/textbox.cpp | 6 +- src/frontend/mame/ui/ui.cpp | 4 +- src/frontend/mame/ui/utils.cpp | 33 +-- src/frontend/mame/ui/videoopt.cpp | 32 +-- src/frontend/mame/ui/videoopt.h | 7 +- src/frontend/mame/ui/viewgfx.cpp | 119 +++++++---- 48 files changed, 1413 insertions(+), 842 deletions(-) create mode 100644 src/frontend/mame/ui/inputdevices.cpp create mode 100644 src/frontend/mame/ui/inputdevices.h create mode 100644 src/frontend/mame/ui/inputopts.cpp create mode 100644 src/frontend/mame/ui/inputopts.h create mode 100644 src/frontend/mame/ui/inputtoggle.cpp create mode 100644 src/frontend/mame/ui/inputtoggle.h (limited to 'src/frontend/mame') diff --git a/src/frontend/mame/ui/analogipt.cpp b/src/frontend/mame/ui/analogipt.cpp index 6dfe4165788..d8c22431ddd 100644 --- a/src/frontend/mame/ui/analogipt.cpp +++ b/src/frontend/mame/ui/analogipt.cpp @@ -57,6 +57,7 @@ menu_analog::menu_analog(mame_ui_manager &mui, render_container &container) , m_hide_menu(false) { set_process_flags(PROCESS_LR_REPEAT); + set_heading(_("Analog Input Adjustments")); } @@ -192,6 +193,8 @@ void menu_analog::custom_render(void *selectedref, float top, float bottom, floa void menu_analog::menu_activated() { // scripts could have changed something in the mean time + m_item_data.clear(); + m_field_data.clear(); reset(reset_options::REMEMBER_POSITION); } @@ -394,6 +397,10 @@ void menu_analog::populate(float &customtop, float &custombottom) &data); } + // display a message if there are toggle inputs enabled + if (!prev_owner) + item_append(_("[no analog inputs are enabled]"), FLAG_DISABLE, nullptr); + item_append(menu_item_type::SEPARATOR); // space for live display diff --git a/src/frontend/mame/ui/auditmenu.cpp b/src/frontend/mame/ui/auditmenu.cpp index 651464cfdab..ae585d6e2ed 100644 --- a/src/frontend/mame/ui/auditmenu.cpp +++ b/src/frontend/mame/ui/auditmenu.cpp @@ -56,6 +56,8 @@ menu_audit::menu_audit(mame_ui_manager &mui, render_container &container) , m_phase(phase::CONFIRMATION) , m_fast(true) { + set_heading(_("Audit Media")); + std::string filename(emulator_info::get_configname()); filename += "_avail.ini"; m_prompt = util::string_format(_("Results will be saved to %1$s"), filename); @@ -96,7 +98,7 @@ void menu_audit::custom_render(void *selectedref, float top, float bottom, float std::size_t const total(m_fast ? m_unavailable : m_availablesorted.size()); std::ostringstream text; util::stream_format(text, - _("Auditing media for machine %2$u of %3$u...\n%1$s"), + _("Auditing media for system %2$u of %3$u...\n%1$s"), system ? std::string_view(system->description) : std::string_view(), (std::min)(audited + 1, total), total); @@ -134,8 +136,8 @@ bool menu_audit::custom_ui_cancel() void menu_audit::populate(float &customtop, float &custombottom) { if (m_unavailable && (m_availablesorted.size() != m_unavailable)) - item_append(util::string_format(_("Audit media for %1$u machines marked unavailable"), m_unavailable), 0, ITEMREF_START_FAST); - item_append(util::string_format(_("Audit media for all %1$u machines"), m_availablesorted.size()), 0, ITEMREF_START_FULL); + item_append(util::string_format(_("Audit media for %1$u systems marked unavailable"), m_unavailable), 0, ITEMREF_START_FAST); + item_append(util::string_format(_("Audit media for all %1$u systems"), m_availablesorted.size()), 0, ITEMREF_START_FULL); item_append(menu_item_type::SEPARATOR, 0); custombottom = (ui().get_line_height() * 1.0f) + (ui().box_tb_border() * 3.0f); } diff --git a/src/frontend/mame/ui/barcode.cpp b/src/frontend/mame/ui/barcode.cpp index 7181445e240..a06e4b99673 100644 --- a/src/frontend/mame/ui/barcode.cpp +++ b/src/frontend/mame/ui/barcode.cpp @@ -37,6 +37,7 @@ namespace ui { menu_barcode_reader::menu_barcode_reader(mame_ui_manager &mui, render_container &container, barcode_reader_device *device) : menu_device_control(mui, container, device) { + set_heading(_("Barcode Reader")); set_process_flags(PROCESS_LR_REPEAT); } @@ -61,7 +62,7 @@ void menu_barcode_reader::populate(float &customtop, float &custombottom) const char *new_barcode; // selected device - item_append(current_display_name(), current_display_flags(), ITEMREF_SELECT_READER); + item_append(std::string(current_display_name()), std::string(current_device()->tag() + 1), current_display_flags(), ITEMREF_SELECT_READER); // append the "New Barcode" item if (get_selection_ref() == ITEMREF_NEW_BARCODE) @@ -79,8 +80,6 @@ void menu_barcode_reader::populate(float &customtop, float &custombottom) // finish up the menu item_append(_("Enter Code"), 0, ITEMREF_ENTER_BARCODE); item_append(menu_item_type::SEPARATOR); - - customtop = ui().get_line_height() + 3.0f * ui().box_tb_border(); } } diff --git a/src/frontend/mame/ui/confswitch.cpp b/src/frontend/mame/ui/confswitch.cpp index aeed0024b69..5440b5545ec 100644 --- a/src/frontend/mame/ui/confswitch.cpp +++ b/src/frontend/mame/ui/confswitch.cpp @@ -167,7 +167,7 @@ void menu_confswitch::populate(float &customtop, float &custombottom) } item_append(menu_item_type::SEPARATOR); - item_append(_("Reset Machine"), 0, (void *)1); + item_append(_("Reset System"), 0, (void *)1); } @@ -311,6 +311,7 @@ menu_settings_dip_switches::menu_settings_dip_switches(mame_ui_manager &mui, ren , m_first_nub(0.0f) , m_clickable_height(0.0f) { + set_heading(_("DIP Switches")); } @@ -504,11 +505,11 @@ void menu_settings_dip_switches::populate(float &customtop, float &custombottom) menu_settings_machine_config::menu_settings_machine_config(mame_ui_manager &mui, render_container &container) : menu_confswitch(mui, container, IPT_CONFIG) { + set_heading(_("Machine Configuration")); } menu_settings_machine_config::~menu_settings_machine_config() { } - } // namespace ui diff --git a/src/frontend/mame/ui/custui.cpp b/src/frontend/mame/ui/custui.cpp index 9359bc5d4a8..08cad10ccdd 100644 --- a/src/frontend/mame/ui/custui.cpp +++ b/src/frontend/mame/ui/custui.cpp @@ -79,6 +79,8 @@ menu_custom_ui::menu_custom_ui(mame_ui_manager &mui, render_container &container , m_currsysnames(0) { set_process_flags(PROCESS_LR_REPEAT); + set_heading(_("Customize UI")); + find_languages(); find_sysnames(); } @@ -137,7 +139,7 @@ void menu_custom_ui::handle(event const *ev) { // copying list of language names - expensive menu::stack_push( - ui(), container(), std::vector(m_languages), m_currlang, + ui(), container(), _("UI Language"), std::vector(m_languages), m_currlang, [this, item = ev->item] (int selection) { m_currlang = selection; @@ -162,7 +164,7 @@ void menu_custom_ui::handle(event const *ev) { // copying list of file names - expensive menu::stack_push( - ui(), container(), std::vector(m_sysnames), m_currsysnames, + ui(), container(), _("System Names"), std::vector(m_sysnames), m_currsysnames, [this, item = ev->item] (int selection) { m_currsysnames = selection; @@ -188,7 +190,7 @@ void menu_custom_ui::handle(event const *ev) std::vector s_sel(std::size(HIDE_STATUS)); std::transform(std::begin(HIDE_STATUS), std::end(HIDE_STATUS), s_sel.begin(), [](auto &s) { return _(s); }); menu::stack_push( - ui(), container(), std::move(s_sel), ui_globals::panels_status, + ui(), container(), _("Show Side Panels"), std::move(s_sel), ui_globals::panels_status, [item = ev->item] (int selection) { ui_globals::panels_status = selection; @@ -218,24 +220,9 @@ void menu_custom_ui::populate(float &customtop, float &custombottom) item_append(_("System Names"), m_sysnames[m_currsysnames], arrow_flags, (void *)(uintptr_t)SYSNAMES_MENU); arrow_flags = get_arrow_flags(0, HIDE_BOTH, ui_globals::panels_status); - item_append(_("Show side panels"), _(HIDE_STATUS[ui_globals::panels_status]), arrow_flags, (void *)(uintptr_t)HIDE_MENU); + item_append(_("Show Side Panels"), _(HIDE_STATUS[ui_globals::panels_status]), arrow_flags, (void *)(uintptr_t)HIDE_MENU); item_append(menu_item_type::SEPARATOR); - customtop = ui().get_line_height() + 3.0f * ui().box_tb_border(); -} - -//------------------------------------------------- -// perform our special rendering -//------------------------------------------------- - -void menu_custom_ui::custom_render(void *selectedref, float top, float bottom, float origx1, float origy1, float origx2, float origy2) -{ - char const *const text[] = { _("UI Customization Settings") }; - draw_text_box( - std::begin(text), std::end(text), - origx1, origx2, origy1 - top, origy1 - ui().box_tb_border(), - text_layout::text_justify::CENTER, text_layout::word_wrapping::TRUNCATE, false, - ui().colors().text_color(), UI_GREEN_COLOR, 1.0f); } //------------------------------------------------- @@ -344,6 +331,7 @@ menu_font_ui::menu_font_ui(mame_ui_manager &mui, render_container &container, st , m_actual(0U) { set_process_flags(PROCESS_LR_REPEAT); + set_heading(_("UI Fonts")); std::string name(mui.machine().options().ui_font()); list(); @@ -467,7 +455,7 @@ void menu_font_ui::handle(event const *ev) for (auto const &font : m_fonts) display_names.emplace_back(font.second); menu::stack_push( - ui(), container(), std::move(display_names), m_actual, + ui(), container(), _("UI Font"), std::move(display_names), m_actual, [this] (int selection) { m_changed = true; @@ -527,7 +515,7 @@ void menu_font_ui::populate(float &customtop, float &custombottom) item_append(menu_item_type::SEPARATOR); - custombottom = customtop = ui().get_line_height() + 3.0f * ui().box_tb_border(); + custombottom = ui().get_line_height() + 3.0f * ui().box_tb_border(); } //------------------------------------------------- @@ -536,14 +524,6 @@ void menu_font_ui::populate(float &customtop, float &custombottom) void menu_font_ui::custom_render(void *selectedref, float top, float bottom, float origx1, float origy1, float origx2, float origy2) { - // top text - char const *const toptext[] = { _("UI Fonts Settings") }; - draw_text_box( - std::begin(toptext), std::end(toptext), - origx1, origx2, origy1 - top, origy1 - ui().box_tb_border(), - text_layout::text_justify::CENTER, text_layout::word_wrapping::TRUNCATE, false, - ui().colors().text_color(), UI_GREEN_COLOR, 1.0f); - if (uintptr_t(selectedref) == INFOS_SIZE) { char const *const bottomtext[] = { _("Sample text - Lorem ipsum dolor sit amet, consectetur adipiscing elit.") }; @@ -562,6 +542,8 @@ void menu_font_ui::custom_render(void *selectedref, float top, float bottom, flo menu_colors_ui::menu_colors_ui(mame_ui_manager &mui, render_container &container) : menu(mui, container) { + set_heading(_("UI Colors")); + SET_COLOR_UI(m_color_table, UI_BACKGROUND_COLOR); SET_COLOR_UI(m_color_table, UI_BORDER_COLOR); SET_COLOR_UI(m_color_table, UI_CLONE_COLOR); @@ -644,7 +626,7 @@ void menu_colors_ui::populate(float &customtop, float &custombottom) item_append(_("Restore default colors"), 0, (void *)(uintptr_t)MUI_RESTORE); - custombottom = customtop = ui().get_line_height() + 3.0f * ui().box_tb_border(); + custombottom = ui().get_line_height() + 3.0f * ui().box_tb_border(); } //------------------------------------------------- @@ -653,15 +635,6 @@ void menu_colors_ui::populate(float &customtop, float &custombottom) void menu_colors_ui::custom_render(void *selectedref, float top, float bottom, float origx1, float origy1, float origx2, float origy2) { - // top text - char const *const toptext[] = { _("UI Color Settings") }; - draw_text_box( - std::begin(toptext), std::end(toptext), - origx1, origx2, origy1 - top, origy1 - ui().box_tb_border(), - text_layout::text_justify::CENTER, text_layout::word_wrapping::TRUNCATE, false, - ui().colors().text_color(), UI_GREEN_COLOR, 1.0f); - - // bottom text // get the text for 'UI Select' std::string const bottomtext[] = { util::string_format(_("Double-click or press %1$s to change color"), ui().get_general_input_setting(IPT_UI_SELECT)) }; draw_text_box( @@ -810,9 +783,9 @@ menu_rgb_ui::menu_rgb_ui(mame_ui_manager &mui, render_container &container, rgb_ , m_search() , m_key_active(false) , m_lock_ref(0) - , m_title(std::move(title)) { set_process_flags(PROCESS_LR_REPEAT); + set_heading(std::move(title)); } //------------------------------------------------- @@ -942,7 +915,7 @@ void menu_rgb_ui::populate(float &customtop, float &custombottom) item_append(_("Choose from palette"), 0, (void *)(uintptr_t)PALETTE_CHOOSE); item_append(menu_item_type::SEPARATOR); - custombottom = customtop = ui().get_line_height() + 3.0f * ui().box_tb_border(); + custombottom = ui().get_line_height() + 3.0f * ui().box_tb_border(); } //------------------------------------------------- @@ -951,42 +924,11 @@ void menu_rgb_ui::populate(float &customtop, float &custombottom) void menu_rgb_ui::custom_render(void *selectedref, float top, float bottom, float origx1, float origy1, float origx2, float origy2) { - float width, maxwidth = origx2 - origx1; - - // top text - ui().draw_text_full( - container(), - m_title, - 0.0f, 0.0f, 1.0f, - text_layout::text_justify::CENTER, text_layout::word_wrapping::NEVER, - mame_ui_manager::NONE, rgb_t::white(), rgb_t::black(), &width); const float lr_border = ui().box_lr_border() * machine().render().ui_aspect(&container()); - width += 2 * lr_border; - maxwidth = std::max(maxwidth, width); - - // compute our bounds - float x1 = 0.5f - 0.5f * maxwidth; - float x2 = x1 + maxwidth; - float y1 = origy1 - top; - float y2 = origy1 - ui().box_tb_border(); - - // draw a box - ui().draw_outlined_box(container(), x1, y1, x2, y2, UI_GREEN_COLOR); - - // take off the borders - x1 += lr_border; - x2 -= lr_border; - y1 += ui().box_tb_border(); - - // draw the text within it - ui().draw_text_full( - container(), - m_title, - x1, y1, x2 - x1, - text_layout::text_justify::CENTER, text_layout::word_wrapping::NEVER, - mame_ui_manager::NORMAL, ui().colors().text_color(), ui().colors().text_bg_color()); + float maxwidth = origx2 - origx1; std::string sampletxt(_("Color preview:")); + float width; ui().draw_text_full( container(), sampletxt, @@ -998,10 +940,10 @@ void menu_rgb_ui::custom_render(void *selectedref, float top, float bottom, floa maxwidth = std::max(origx2 - origx1, width); // compute our bounds - x1 = 0.5f - 0.5f * maxwidth; - x2 = x1 + maxwidth; - y1 = origy2 + ui().box_tb_border(); - y2 = origy2 + bottom; + float x1 = 0.5f - 0.5f * maxwidth; + float x2 = x1 + maxwidth; + float y1 = origy2 + ui().box_tb_border(); + float y2 = origy2 + bottom; // draw a box - force black to ensure the text is legible ui().draw_outlined_box(container(), x1, y1, x2, y2, rgb_t::black()); diff --git a/src/frontend/mame/ui/custui.h b/src/frontend/mame/ui/custui.h index 168934b5356..6a5e09ae954 100644 --- a/src/frontend/mame/ui/custui.h +++ b/src/frontend/mame/ui/custui.h @@ -30,7 +30,6 @@ public: menu_custom_ui(mame_ui_manager &mui, render_container &container, std::function &&handler); protected: - virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override; virtual void menu_dismissed() override; private: diff --git a/src/frontend/mame/ui/dirmenu.cpp b/src/frontend/mame/ui/dirmenu.cpp index 920a847c001..1aa4cb6a8fe 100644 --- a/src/frontend/mame/ui/dirmenu.cpp +++ b/src/frontend/mame/ui/dirmenu.cpp @@ -29,8 +29,8 @@ namespace ui { namespace { -static int ADDING = 1; -static int CHANGE = 2; +constexpr int ADDING = 1; +constexpr int CHANGE = 2; struct folders_entry { @@ -39,7 +39,7 @@ struct folders_entry const int action; }; -static const folders_entry s_folders[] = +const folders_entry f_folders[] = { { N_p("path-option", "ROMs"), OPTION_MEDIAPATH, ADDING }, { N_p("path-option", "Software Media"), OPTION_SWPATH, CHANGE }, @@ -74,167 +74,132 @@ static const folders_entry s_folders[] = { N_p("path-option", "Covers"), OPTION_COVER_PATH, ADDING } }; -} // anonymous namespace - /************************************************** - MENU DIRECTORY + MENU REMOVE FOLDER **************************************************/ -//------------------------------------------------- -// ctor / dtor -//------------------------------------------------- -menu_directory::menu_directory(mame_ui_manager &mui, render_container &container) : menu(mui, container) +class menu_remove_folder : public menu { -} +public: + menu_remove_folder(mame_ui_manager &mui, render_container &container, int ref); -menu_directory::~menu_directory() -{ - ui().save_ui_options(); - ui_globals::reset = true; -} +private: + virtual void populate(float &customtop, float &custombottom) override; + virtual void handle(event const *ev) override; -//------------------------------------------------- -// handle -//------------------------------------------------- - -void menu_directory::handle(event const *ev) -{ - // process the menu - if (ev && ev->itemref && ev->iptkey == IPT_UI_SELECT) - menu::stack_push(ui(), container(), selected_index()); -} - -//------------------------------------------------- -// populate -//------------------------------------------------- - -void menu_directory::populate(float &customtop, float &custombottom) -{ - for (auto & elem : s_folders) - item_append(_("path-option", elem.name), 0, (void *)(uintptr_t)elem.action); - - item_append(menu_item_type::SEPARATOR); - customtop = ui().get_line_height() + 3.0f * ui().box_tb_border(); -} - -//------------------------------------------------- -// perform our special rendering -//------------------------------------------------- - -void menu_directory::custom_render(void *selectedref, float top, float bottom, float origx1, float origy1, float origx2, float origy2) -{ - char const *const toptext[] = { _("Folders Setup") }; - draw_text_box( - std::begin(toptext), std::end(toptext), - origx1, origx2, origy1 - top, origy1 - ui().box_tb_border(), - text_layout::text_justify::CENTER, text_layout::word_wrapping::TRUNCATE, false, - ui().colors().text_color(), UI_GREEN_COLOR, 1.0f); -} + std::string m_searchpath; + int const m_ref; + std::vector m_folders; +}; -/************************************************** - MENU DISPLAY PATH -**************************************************/ //------------------------------------------------- // ctor / dtor //------------------------------------------------- -menu_display_actual::menu_display_actual(mame_ui_manager &mui, render_container &container, int ref) - : menu(mui, container), m_ref(ref) +menu_remove_folder::menu_remove_folder(mame_ui_manager &mui, render_container &container, int ref) + : menu(mui, container) + , m_ref(ref) { -} + set_heading(util::string_format(_("Remove %1$s Folder"), _("path-option", f_folders[m_ref].name))); -menu_display_actual::~menu_display_actual() -{ + if (mui.options().exists(f_folders[m_ref].option)) + m_searchpath.assign(mui.options().value(f_folders[m_ref].option)); + else + m_searchpath.assign(mui.machine().options().value(f_folders[m_ref].option)); + + path_iterator path(m_searchpath); + std::string curpath; + while (path.next(curpath)) + m_folders.push_back(curpath); } //------------------------------------------------- // handle //------------------------------------------------- -void menu_display_actual::handle(event const *ev) +void menu_remove_folder::handle(event const *ev) { // process the menu if (ev && ev->itemref && ev->iptkey == IPT_UI_SELECT) - switch ((uintptr_t)ev->itemref) + { + std::string tmppath, error_string; + m_folders.erase(m_folders.begin() + selected_index()); + for (int x = 0; x < m_folders.size(); ++x) { - case REMOVE: - menu::stack_push(ui(), container(), m_ref); - break; + tmppath.append(m_folders[x]); + if (x < m_folders.size() - 1) + tmppath.append(";"); + } - case ADD_CHANGE: - menu::stack_push(ui(), container(), m_ref); - break; + if (ui().options().exists(f_folders[m_ref].option)) + ui().options().set_value(f_folders[m_ref].option, tmppath, OPTION_PRIORITY_CMDLINE); + else if (machine().options().value(f_folders[m_ref].option) != tmppath) + { + machine().options().set_value(f_folders[m_ref].option, tmppath, OPTION_PRIORITY_CMDLINE); } + + reset_parent(reset_options::REMEMBER_REF); + stack_pop(); + } } //------------------------------------------------- -// populate +// populate menu //------------------------------------------------- -void menu_display_actual::populate(float &customtop, float &custombottom) +void menu_remove_folder::populate(float &customtop, float &custombottom) { - m_heading[0] = string_format(_("Current %1$s Folders"), _("path-option", s_folders[m_ref].name)); - if (ui().options().exists(s_folders[m_ref].option)) - m_searchpath.assign(ui().options().value(s_folders[m_ref].option)); - else - m_searchpath.assign(machine().options().value(s_folders[m_ref].option)); - - path_iterator path(m_searchpath); - std::string curpath; - m_folders.clear(); - while (path.next(curpath)) - m_folders.push_back(curpath); - - item_append((s_folders[m_ref].action == CHANGE) ? _("Change Folder") : _("Add Folder"), 0, (void *)ADD_CHANGE); - - if (m_folders.size() > 1) - item_append(_("Remove Folder"), 0, (void *)REMOVE); + int folders_count = 0; + for (auto & elem : m_folders) + item_append(elem, 0, (void *)(uintptr_t)++folders_count); item_append(menu_item_type::SEPARATOR); - customtop = (m_folders.size() + 1) * ui().get_line_height() + 6.0f * ui().box_tb_border(); } -//------------------------------------------------- -// perform our special rendering -//------------------------------------------------- - -void menu_display_actual::custom_render(void *selectedref, float top, float bottom, float origx1, float origy1, float origx2, float origy2) -{ - float const lineheight(ui().get_line_height()); - float const maxwidth(draw_text_box( - std::begin(m_folders), std::end(m_folders), - origx1, origx2, origy1 - (3.0f * ui().box_tb_border()) - (m_folders.size() * lineheight), origy1 - ui().box_tb_border(), - text_layout::text_justify::CENTER, text_layout::word_wrapping::TRUNCATE, false, - ui().colors().text_color(), ui().colors().background_color(), 1.0f)); - draw_text_box( - std::begin(m_heading), std::end(m_heading), - 0.5f * (1.0f - maxwidth), 0.5f * (1.0f + maxwidth), origy1 - top, origy1 - top + lineheight + (2.0f * ui().box_tb_border()), - text_layout::text_justify::CENTER, text_layout::word_wrapping::TRUNCATE, false, - ui().colors().text_color(), UI_GREEN_COLOR, 1.0f); -} /************************************************** -MENU ADD FOLDER + MENU ADD FOLDER **************************************************/ + +class menu_add_change_folder : public menu +{ +public: + menu_add_change_folder(mame_ui_manager &mui, render_container &container, int ref); + +protected: + virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override; + + virtual bool custom_ui_cancel() override { return !m_search.empty(); } + +private: + virtual void populate(float &customtop, float &custombottom) override; + virtual void handle(event const *ev) override; + + int const m_ref; + std::string m_current_path; + std::string m_search; + bool const m_change; + std::vector m_folders; +}; + //------------------------------------------------- -// ctor / dtor +// ctor //------------------------------------------------- -menu_add_change_folder::menu_add_change_folder(mame_ui_manager &mui, render_container &container, int ref) : menu(mui, container) +menu_add_change_folder::menu_add_change_folder(mame_ui_manager &mui, render_container &container, int ref) + : menu(mui, container) + , m_ref(ref) + , m_change(f_folders[ref].action == CHANGE) { - m_ref = ref; - m_change = (s_folders[ref].action == CHANGE); - m_search.clear(); - // configure the starting path osd_get_full_path(m_current_path, "."); std::string searchpath; - if (mui.options().exists(s_folders[m_ref].option)) - searchpath = mui.options().value(s_folders[m_ref].option); + if (mui.options().exists(f_folders[m_ref].option)) + searchpath = mui.options().value(f_folders[m_ref].option); else - searchpath = mui.machine().options().value(s_folders[m_ref].option); + searchpath = mui.machine().options().value(f_folders[m_ref].option); path_iterator path(searchpath); std::string curpath; @@ -242,10 +207,6 @@ menu_add_change_folder::menu_add_change_folder(mame_ui_manager &mui, render_cont m_folders.push_back(curpath); } -menu_add_change_folder::~menu_add_change_folder() -{ -} - //------------------------------------------------- // handle //------------------------------------------------- @@ -290,10 +251,10 @@ void menu_add_change_folder::handle(event const *ev) std::string error_string; if (m_change) { - if (ui().options().exists(s_folders[m_ref].option)) - ui().options().set_value(s_folders[m_ref].option, m_current_path, OPTION_PRIORITY_CMDLINE); - else if (machine().options().value(s_folders[m_ref].option) != m_current_path) - machine().options().set_value(s_folders[m_ref].option, m_current_path, OPTION_PRIORITY_CMDLINE); + if (ui().options().exists(f_folders[m_ref].option)) + ui().options().set_value(f_folders[m_ref].option, m_current_path, OPTION_PRIORITY_CMDLINE); + else if (machine().options().value(f_folders[m_ref].option) != m_current_path) + machine().options().set_value(f_folders[m_ref].option, m_current_path, OPTION_PRIORITY_CMDLINE); } else { @@ -306,10 +267,10 @@ void menu_add_change_folder::handle(event const *ev) tmppath.append(";"); } - if (ui().options().exists(s_folders[m_ref].option)) - ui().options().set_value(s_folders[m_ref].option, tmppath, OPTION_PRIORITY_CMDLINE); - else if (machine().options().value(s_folders[m_ref].option) != tmppath) - machine().options().set_value(s_folders[m_ref].option, tmppath, OPTION_PRIORITY_CMDLINE); + if (ui().options().exists(f_folders[m_ref].option)) + ui().options().set_value(f_folders[m_ref].option, tmppath, OPTION_PRIORITY_CMDLINE); + else if (machine().options().value(f_folders[m_ref].option) != tmppath) + machine().options().set_value(f_folders[m_ref].option, tmppath, OPTION_PRIORITY_CMDLINE); } reset_parent(reset_options::SELECT_FIRST); @@ -429,7 +390,7 @@ void menu_add_change_folder::custom_render(void *selectedref, float top, float b std::string const toptext[] = { util::string_format( m_change ? _("Change %1$s Folder - Search: %2$s_") : _("Add %1$s Folder - Search: %2$s_"), - _("path-option", s_folders[m_ref].name), + _("path-option", f_folders[m_ref].name), m_search), m_current_path }; draw_text_box( @@ -447,87 +408,150 @@ void menu_add_change_folder::custom_render(void *selectedref, float top, float b ui().colors().text_color(), ui().colors().background_color(), 1.0f); } + /************************************************** - MENU REMOVE FOLDER + MENU DISPLAY PATH **************************************************/ -//------------------------------------------------- -// ctor / dtor -//------------------------------------------------- -menu_remove_folder::menu_remove_folder(mame_ui_manager &mui, render_container &container, int ref) : menu(mui, container) +class menu_display_actual : public menu { - m_ref = ref; - if (mui.options().exists(s_folders[m_ref].option)) - m_searchpath.assign(mui.options().value(s_folders[m_ref].option)); - else - m_searchpath.assign(mui.machine().options().value(s_folders[m_ref].option)); +public: + menu_display_actual(mame_ui_manager &mui, render_container &container, int selectedref) + : menu(mui, container) + , m_heading{ util::string_format((f_folders[selectedref].action == ADDING) ? _("%1$s Folders") : _("%1$s Folder"), _("path-option", f_folders[selectedref].name)) } + , m_ref(selectedref) + { + } - path_iterator path(m_searchpath); - std::string curpath; - while (path.next(curpath)) - m_folders.push_back(curpath); -} +protected: + virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override; -menu_remove_folder::~menu_remove_folder() -{ -} +private: + enum + { + ADD_CHANGE = 1, + REMOVE, + }; + + virtual void populate(float &customtop, float &custombottom) override; + virtual void handle(event const *ev) override; + + std::string const m_heading[1]; + std::string m_searchpath; + std::vector m_folders; + int const m_ref; +}; //------------------------------------------------- // handle //------------------------------------------------- -void menu_remove_folder::handle(event const *ev) +void menu_display_actual::handle(event const *ev) { // process the menu if (ev && ev->itemref && ev->iptkey == IPT_UI_SELECT) { - std::string tmppath, error_string; - m_folders.erase(m_folders.begin() + selected_index()); - for (int x = 0; x < m_folders.size(); ++x) + switch ((uintptr_t)ev->itemref) { - tmppath.append(m_folders[x]); - if (x < m_folders.size() - 1) - tmppath.append(";"); - } + case REMOVE: + menu::stack_push(ui(), container(), m_ref); + break; - if (ui().options().exists(s_folders[m_ref].option)) - ui().options().set_value(s_folders[m_ref].option, tmppath, OPTION_PRIORITY_CMDLINE); - else if (machine().options().value(s_folders[m_ref].option) != tmppath) - { - machine().options().set_value(s_folders[m_ref].option, tmppath, OPTION_PRIORITY_CMDLINE); + case ADD_CHANGE: + menu::stack_push(ui(), container(), m_ref); + break; } - - reset_parent(reset_options::REMEMBER_REF); - stack_pop(); } } //------------------------------------------------- -// populate menu +// populate //------------------------------------------------- -void menu_remove_folder::populate(float &customtop, float &custombottom) +void menu_display_actual::populate(float &customtop, float &custombottom) { - int folders_count = 0; - for (auto & elem : m_folders) - item_append(elem, 0, (void *)(uintptr_t)++folders_count); + if (ui().options().exists(f_folders[m_ref].option)) + m_searchpath.assign(ui().options().value(f_folders[m_ref].option)); + else + m_searchpath.assign(machine().options().value(f_folders[m_ref].option)); + + path_iterator path(m_searchpath); + std::string curpath; + m_folders.clear(); + while (path.next(curpath)) + m_folders.push_back(curpath); + + item_append((f_folders[m_ref].action == CHANGE) ? _("Change Folder") : _("Add Folder"), 0, (void *)ADD_CHANGE); + + if (m_folders.size() > 1) + item_append(_("Remove Folder"), 0, (void *)REMOVE); item_append(menu_item_type::SEPARATOR); - customtop = ui().get_line_height() + 3.0f * ui().box_tb_border(); + + customtop = (m_folders.size() + 1) * ui().get_line_height() + 6.0f * ui().box_tb_border(); } //------------------------------------------------- // perform our special rendering //------------------------------------------------- -void menu_remove_folder::custom_render(void *selectedref, float top, float bottom, float origx1, float origy1, float origx2, float origy2) +void menu_display_actual::custom_render(void *selectedref, float top, float bottom, float origx1, float origy1, float origx2, float origy2) { - std::string const toptext[] = {string_format(_("Remove %1$s Folder"), _("path-option", s_folders[m_ref].name)) }; + float const lineheight(ui().get_line_height()); + float const maxwidth(draw_text_box( + std::begin(m_folders), std::end(m_folders), + origx1, origx2, origy1 - (3.0f * ui().box_tb_border()) - (m_folders.size() * lineheight), origy1 - ui().box_tb_border(), + text_layout::text_justify::CENTER, text_layout::word_wrapping::TRUNCATE, false, + ui().colors().text_color(), ui().colors().background_color(), 1.0f)); draw_text_box( - std::begin(toptext), std::end(toptext), - origx1, origx2, origy1 - top, origy1 - ui().box_tb_border(), + std::begin(m_heading), std::end(m_heading), + 0.5f * (1.0f - maxwidth), 0.5f * (1.0f + maxwidth), origy1 - top, origy1 - top + lineheight + (2.0f * ui().box_tb_border()), text_layout::text_justify::CENTER, text_layout::word_wrapping::TRUNCATE, false, ui().colors().text_color(), UI_GREEN_COLOR, 1.0f); } +} // anonymous namespace + + +/************************************************** + MENU DIRECTORY +**************************************************/ +//------------------------------------------------- +// ctor / dtor +//------------------------------------------------- + +menu_directory::menu_directory(mame_ui_manager &mui, render_container &container) : menu(mui, container) +{ + set_heading(_("Configure Folders")); +} + +menu_directory::~menu_directory() +{ + ui().save_ui_options(); + ui_globals::reset = true; +} + +//------------------------------------------------- +// handle +//------------------------------------------------- + +void menu_directory::handle(event const *ev) +{ + // process the menu + if (ev && ev->itemref && ev->iptkey == IPT_UI_SELECT) + menu::stack_push(ui(), container(), selected_index()); +} + +//------------------------------------------------- +// populate +//------------------------------------------------- + +void menu_directory::populate(float &customtop, float &custombottom) +{ + for (auto & elem : f_folders) + item_append(_("path-option", elem.name), 0, (void *)(uintptr_t)elem.action); + + item_append(menu_item_type::SEPARATOR); +} + } // namespace ui diff --git a/src/frontend/mame/ui/dirmenu.h b/src/frontend/mame/ui/dirmenu.h index 556427425e0..644a71ba564 100644 --- a/src/frontend/mame/ui/dirmenu.h +++ b/src/frontend/mame/ui/dirmenu.h @@ -8,11 +8,11 @@ ***************************************************************************/ -#pragma once - #ifndef MAME_FRONTEND_UI_DIRMENU_H #define MAME_FRONTEND_UI_DIRMENU_H +#pragma once + #include "ui/menu.h" #include @@ -30,88 +30,9 @@ public: menu_directory(mame_ui_manager &mui, render_container &container); virtual ~menu_directory() override; -protected: - virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override; - -private: - virtual void populate(float &customtop, float &custombottom) override; - virtual void handle(event const *ev) override; -}; - -//------------------------------------------------- -// class directory specific menu -//------------------------------------------------- - -class menu_display_actual : public menu -{ -public: - menu_display_actual(mame_ui_manager &mui, render_container &container, int selectedref); - virtual ~menu_display_actual() override; - -protected: - virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override; - -private: - enum - { - ADD_CHANGE = 1, - REMOVE, - }; - - virtual void populate(float &customtop, float &custombottom) override; - virtual void handle(event const *ev) override; - - std::string m_heading[1], m_searchpath; - std::vector m_folders; - int m_ref; -}; - -//------------------------------------------------- -// class remove folder menu -//------------------------------------------------- - -class menu_remove_folder : public menu -{ -public: - menu_remove_folder(mame_ui_manager &mui, render_container &container, int ref); - virtual ~menu_remove_folder() override; - -protected: - virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override; - private: virtual void populate(float &customtop, float &custombottom) override; virtual void handle(event const *ev) override; - - std::string m_searchpath; - int m_ref; - std::vector m_folders; -}; - -//------------------------------------------------- -// class add / change folder menu -//------------------------------------------------- - -class menu_add_change_folder : public menu -{ -public: - menu_add_change_folder(mame_ui_manager &mui, render_container &container, int ref); - virtual ~menu_add_change_folder() override; - -protected: - virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override; - - virtual bool custom_ui_cancel() override { return !m_search.empty(); } - -private: - virtual void populate(float &customtop, float &custombottom) override; - virtual void handle(event const *ev) override; - - int m_ref; - std::string m_current_path; - std::string m_search; - bool m_change; - std::vector m_folders; }; } // namespace ui diff --git a/src/frontend/mame/ui/filemngr.cpp b/src/frontend/mame/ui/filemngr.cpp index 06c2d822b1e..ec346940586 100644 --- a/src/frontend/mame/ui/filemngr.cpp +++ b/src/frontend/mame/ui/filemngr.cpp @@ -40,6 +40,7 @@ menu_file_manager::menu_file_manager(mame_ui_manager &mui, render_container &con { // The warning string is used when accessing from the force_file_manager call, i.e. // when the file manager is loaded top front in the case of mandatory image devices + set_heading(_("File Manager")); } @@ -150,7 +151,7 @@ void menu_file_manager::populate(float &customtop, float &custombottom) item_append(menu_item_type::SEPARATOR); if (m_warnings.empty() || !missing_mandatory) - item_append(m_warnings.empty() ? _("Reset Machine") : _("Start Machine"), 0, (void *)1); + item_append(m_warnings.empty() ? _("Reset System") : _("Start System"), 0, (void *)1); custombottom = ui().get_line_height() + 3.0f * ui().box_tb_border(); } diff --git a/src/frontend/mame/ui/info.cpp b/src/frontend/mame/ui/info.cpp index 5d4b8c61cb2..fdabab41290 100644 --- a/src/frontend/mame/ui/info.cpp +++ b/src/frontend/mame/ui/info.cpp @@ -64,7 +64,7 @@ void get_general_warnings(std::ostream &buf, running_machine &machine, machine_f if (machine.rom_load().warnings() > 0) { bad_roms = true; - buf << _("One or more ROMs/CHDs for this machine are incorrect. The machine may not run correctly.\n"); + buf << _("One or more ROMs/disk images for this system are incorrect. The system may not run correctly.\n"); } if (!machine.rom_load().software_load_warnings_message().empty()) { @@ -77,12 +77,12 @@ void get_general_warnings(std::ostream &buf, running_machine &machine, machine_f { if (bad_roms) buf << '\n'; - buf << _("There are known problems with this machine\n\n"); + buf << _("There are known problems with this system\n\n"); } // add a warning if any ROMs are flagged BAD_DUMP/NO_DUMP if (machine.rom_load().knownbad() > 0) - buf << _("One or more ROMs/CHDs for this machine have not been correctly dumped.\n"); + buf << _("One or more ROMs/disk images for this system have not been correctly dumped.\n"); } void get_device_warnings(std::ostream &buf, device_t::feature_type unemulated, device_t::feature_type imperfect) @@ -129,17 +129,17 @@ void get_system_warnings(std::ostream &buf, running_machine &machine, machine_fl if (flags & ::machine_flags::NO_COCKTAIL) buf << _("Screen flipping in cocktail mode is not supported.\n"); if (flags & ::machine_flags::REQUIRES_ARTWORK) - buf << _("This machine requires external artwork files.\n"); + buf << _("This system requires external artwork files.\n"); if (flags & ::machine_flags::IS_INCOMPLETE) - buf << _("This machine was never completed. It may exhibit strange behavior or missing elements that are not bugs in the emulation.\n"); + buf << _("This system was never completed. It may exhibit strange behavior or missing elements that are not bugs in the emulation.\n"); if (flags & ::machine_flags::NO_SOUND_HW) - buf << _("This machine has no sound hardware, MAME will produce no sounds, this is expected behaviour.\n"); + buf << _("This system has no sound hardware, MAME will produce no sounds, this is expected behaviour.\n"); // these are more severe warnings if (flags & ::machine_flags::NOT_WORKING) - buf << _("\nTHIS MACHINE DOESN'T WORK. The emulation for this machine is not yet complete. There is nothing you can do to fix this problem except wait for the developers to improve the emulation.\n"); + buf << _("\nTHIS SYSTEM DOESN'T WORK. The emulation for this system is not yet complete. There is nothing you can do to fix this problem except wait for the developers to improve the emulation.\n"); if (flags & ::machine_flags::MECHANICAL) - buf << _("\nElements of this machine cannot be emulated as they require physical interaction or consist of mechanical devices. It is not possible to fully experience this machine.\n"); + buf << _("\nElements of this system cannot be emulated as they require physical interaction or consist of mechanical devices. It is not possible to fully experience this system.\n"); if ((flags & MACHINE_ERRORS) || ((machine.system().type.unemulated_features() | machine.system().type.imperfect_features()) & device_t::feature::PROTECTION)) { @@ -161,7 +161,7 @@ void get_system_warnings(std::ostream &buf, running_machine &machine, machine_fl { // this one works, add a header and display the name of the clone if (!foundworking) - util::stream_format(buf, _("\n\nThere are working clones of this machine: %s"), driver.name); + util::stream_format(buf, _("\n\nThere are working clones of this system: %s"), driver.name); else util::stream_format(buf, _(", %s"), driver.name); foundworking = true; @@ -615,6 +615,7 @@ void menu_warn_info::handle(event const *ev) menu_image_info::menu_image_info(mame_ui_manager &mui, render_container &container) : menu(mui, container) { + set_heading(_("Media Image Information")); } menu_image_info::~menu_image_info() @@ -628,10 +629,6 @@ void menu_image_info::menu_activated() void menu_image_info::populate(float &customtop, float &custombottom) { - ui_system_info const &system(system_list::instance().systems()[driver_list::find(machine().system().name)]); - item_append(system.description, FLAG_DISABLE, nullptr); - item_append(std::string(), FLAG_DISABLE, nullptr); - for (device_image_interface &image : image_interface_enumerator(machine().root_device())) image_info(&image); } @@ -680,7 +677,7 @@ void menu_image_info::image_info(device_image_interface *image) { item_append(image->brief_instance_name(), _("[empty]"), 0, nullptr); } - item_append(std::string(), FLAG_DISABLE, nullptr); + item_append(menu_item_type::SEPARATOR); } } // namespace ui diff --git a/src/frontend/mame/ui/info_pty.cpp b/src/frontend/mame/ui/info_pty.cpp index 4e541a7988c..1aadb85deb9 100644 --- a/src/frontend/mame/ui/info_pty.cpp +++ b/src/frontend/mame/ui/info_pty.cpp @@ -19,6 +19,7 @@ namespace ui { menu_pty_info::menu_pty_info(mame_ui_manager &mui, render_container &container) : menu(mui, container) { + set_heading(_("Pseudo Terminals")); } menu_pty_info::~menu_pty_info() @@ -27,9 +28,6 @@ menu_pty_info::~menu_pty_info() void menu_pty_info::populate(float &customtop, float &custombottom) { - item_append(_("Pseudo terminals"), FLAG_DISABLE, nullptr); - item_append(std::string(), FLAG_DISABLE, nullptr); - for (device_pty_interface &pty : pty_interface_enumerator(machine().root_device())) { const char *port_name = pty.device().owner()->tag() + 1; diff --git a/src/frontend/mame/ui/inputdevices.cpp b/src/frontend/mame/ui/inputdevices.cpp new file mode 100644 index 00000000000..e1e39f0467f --- /dev/null +++ b/src/frontend/mame/ui/inputdevices.cpp @@ -0,0 +1,258 @@ +// license:BSD-3-Clause +// copyright-holders:Vas Crabb +/*************************************************************************** + + ui/inputdevices.cpp + + Input devices menu. + +***************************************************************************/ + +#include "emu.h" +#include "inputdevices.h" + +#include "inputdev.h" + + +namespace ui { + +namespace { + +class menu_input_device : public menu +{ +public: + menu_input_device(mame_ui_manager &mui, render_container &container, input_device &device) + : menu(mui, container) + , m_device(device) + { + set_heading( + util::string_format(_("menu-inputdev", "%1$s (%2$s %3$d)"), + device.name(), + machine().input().device_class(device.devclass()).name(), + device.devindex() + 1)); + } + +protected: + virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override + { + if (selectedref) + { + input_device_item &input = *reinterpret_cast(selectedref); + switch (input.itemclass()) + { + case ITEM_CLASS_ABSOLUTE: + case ITEM_CLASS_RELATIVE: + { + // draw the outer box + ui().draw_outlined_box(container(), x, y2 + ui().box_tb_border(), x2, y2 + bottom, ui().colors().background_color()); + + // draw the indicator + rgb_t const fgcolor(ui().colors().text_color()); + float const border = ui().box_lr_border() * machine().render().ui_aspect(&container()); + float const lineheight = ui().get_line_height(); + float const indleft = x + border; + float const indright = x2 - border; + float const indtop = y2 + (ui().box_tb_border() * 2.0F) + (lineheight * 0.2F); + float const indbottom = y2 + (ui().box_tb_border() * 2.0F) + (lineheight * 0.8F); + float const indcentre = (x + x2) * 0.5F; + s32 const value = (input.itemclass() == ITEM_CLASS_ABSOLUTE) ? input.read_as_absolute(ITEM_MODIFIER_NONE) : input.read_as_relative(ITEM_MODIFIER_NONE); + if (0 < value) + { + float const fillright = indcentre + (float(value) / float(INPUT_ABSOLUTE_MAX) * (indright - indcentre)); + container().add_rect(indcentre, indtop, (std::min)(fillright, indright), indbottom, fgcolor, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA)); + } + else if (0 > value) + { + float const fillleft = indcentre - (float(value) / float(INPUT_ABSOLUTE_MIN) * (indcentre - indleft)); + container().add_rect((std::max)(fillleft, indleft), indtop, indcentre, indbottom, fgcolor, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA)); + } + container().add_line(indleft, indtop, indright, indtop, UI_LINE_WIDTH, fgcolor, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA)); + container().add_line(indright, indtop, indright, indbottom, UI_LINE_WIDTH, fgcolor, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA)); + container().add_line(indright, indbottom, indleft, indbottom, UI_LINE_WIDTH, fgcolor, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA)); + container().add_line(indleft, indbottom, indleft, indtop, UI_LINE_WIDTH, fgcolor, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA)); + container().add_line(indcentre, indtop, indcentre, indbottom, UI_LINE_WIDTH, fgcolor, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA)); + } + break; + default: + break; + } + } + } + +private: + virtual void populate(float &customtop, float &custombottom) override + { + bool haveanalog = false; + for (input_item_id itemid = ITEM_ID_FIRST_VALID; m_device.maxitem() >= itemid; ++itemid) + { + input_device_item *const input = m_device.item(itemid); + if (input) + { + switch (input->itemclass()) + { + case ITEM_CLASS_ABSOLUTE: + case ITEM_CLASS_RELATIVE: + haveanalog = true; + break; + default: + break; + } + item_append(input->name(), format_value(*input), 0U, input); + } + } + + item_append(menu_item_type::SEPARATOR); + + if (haveanalog) + custombottom = ui().get_line_height() + (ui().box_tb_border() * 3.0F); + } + + virtual void handle(event const *ev) override + { + for (int i = 0; item_count() > i; ++i) + { + void *const ref(item(i).ref()); + if (ref) + { + input_device_item &input = *reinterpret_cast(ref); + item(i).set_subtext(format_value(input)); + } + } + } + + static std::string format_value(input_device_item &input) + { + switch (input.itemclass()) + { + default: + case ITEM_CLASS_SWITCH: + return util::string_format("%d", input.read_as_switch(ITEM_MODIFIER_NONE)); + case ITEM_CLASS_ABSOLUTE: + return util::string_format("%d", input.read_as_absolute(ITEM_MODIFIER_NONE)); + case ITEM_CLASS_RELATIVE: + return util::string_format("%d", input.read_as_relative(ITEM_MODIFIER_NONE)); + } + } + + input_device &m_device; +}; + +} // anonymous namespace + + + +menu_input_devices::menu_input_devices(mame_ui_manager &mui, render_container &container) + : menu(mui, container) +{ + set_heading(_("menu-inputdev", "Input Devices")); +} + + +menu_input_devices::~menu_input_devices() +{ +} + + +void menu_input_devices::populate(float &customtop, float &custombottom) +{ + // iterate input device classes and devices within each class + bool found = false; + for (input_device_class classno = DEVICE_CLASS_FIRST_VALID; DEVICE_CLASS_LAST_VALID >= classno; ++classno) + { + input_class &devclass = machine().input().device_class(classno); + if (devclass.enabled()) + { + bool first = true; + for (int devnum = 0; devclass.maxindex() >= devnum; ++devnum) + { + input_device *const device = devclass.device(devnum); + if (device) + { + // add a device class heading + found = true; + if (first) + { + first = false; + item_append(devclass.name(), FLAG_UI_HEADING | FLAG_DISABLE, nullptr); + } + + // add the item for the device itself + item_append(util::string_format("%d", device->devindex() + 1), device->name(), 0U, device); + } + } + } + } + + // highly unlikely - at least one keyboard or mouse will be enabled in almost all cases + if (!found) + item_append(_("menu-inputdev", "[no input devices are enabled]"), FLAG_DISABLE, nullptr); + + item_append(menu_item_type::SEPARATOR); +} + + +void menu_input_devices::handle(event const *ev) +{ + if (ev && ev->itemref) + { + input_device &dev = *reinterpret_cast(ev->itemref); + switch (ev->iptkey) + { + case IPT_UI_SELECT: + stack_push(ui(), container(), dev); + break; + + case IPT_UI_PREV_GROUP: + { + auto group = dev.devclass(); + bool found_break = false; + int target = 0; + for (auto i = selected_index(); 0 < i--; ) + { + input_device *const candidate = reinterpret_cast(item(i).ref()); + if (candidate) + { + if (candidate->devclass() == group) + { + target = i; + } + else if (!found_break) + { + group = candidate->devclass(); + found_break = true; + target = i; + } + else + { + set_selected_index(target); + break; + } + } + if (!i && found_break) + { + set_selected_index(target); + break; + } + } + } + break; + + case IPT_UI_NEXT_GROUP: + { + auto const group = dev.devclass(); + for (auto i = selected_index(); item_count() > ++i; ) + { + input_device *const candidate = reinterpret_cast(item(i).ref()); + if (candidate && (candidate->devclass() != group)) + { + set_selected_index(i); + break; + } + } + } + break; + } + } +} + +} // namespace ui diff --git a/src/frontend/mame/ui/inputdevices.h b/src/frontend/mame/ui/inputdevices.h new file mode 100644 index 00000000000..cb81caaaf47 --- /dev/null +++ b/src/frontend/mame/ui/inputdevices.h @@ -0,0 +1,34 @@ +// license:BSD-3-Clause +// copyright-holders:Vas Crabb +/*************************************************************************** + + ui/inputdevices.h + + Input devices menu. + +***************************************************************************/ + +#ifndef MAME_FRONTEND_UI_INPUTDEVICES_H +#define MAME_FRONTEND_UI_INPUTDEVICES_H + +#pragma once + +#include "ui/menu.h" + + +namespace ui { + +class menu_input_devices : public menu +{ +public: + menu_input_devices(mame_ui_manager &mui, render_container &container); + virtual ~menu_input_devices(); + +private: + virtual void populate(float &customtop, float &custombottom) override; + virtual void handle(event const *ev) override; +}; + +} // namespace ui + +#endif // MAME_FRONTEND_UI_INPUTDEVICES_H diff --git a/src/frontend/mame/ui/inputmap.cpp b/src/frontend/mame/ui/inputmap.cpp index 38dd73111be..161ce0f03c6 100644 --- a/src/frontend/mame/ui/inputmap.cpp +++ b/src/frontend/mame/ui/inputmap.cpp @@ -26,6 +26,7 @@ namespace ui { menu_input_groups::menu_input_groups(mame_ui_manager &mui, render_container &container) : menu(mui, container) { + set_heading(_("Input Assignments (general)")); } menu_input_groups::~menu_input_groups() @@ -49,7 +50,13 @@ void menu_input_groups::handle(event const *ev) { // process the menu if (ev && (ev->iptkey == IPT_UI_SELECT)) - menu::stack_push(ui(), container(), int(uintptr_t(ev->itemref) - 1)); + { + menu::stack_push( + ui(), + container(), + int(uintptr_t(ev->itemref) - 1), + util::string_format(_("Input Assignments (%1$s)"), ev->item->text())); + } } @@ -58,16 +65,23 @@ void menu_input_groups::handle(event const *ev) input menu -------------------------------------------------*/ -menu_input_general::menu_input_general(mame_ui_manager &mui, render_container &container, int _group) +menu_input_general::menu_input_general(mame_ui_manager &mui, render_container &container, int _group, std::string &&heading) : menu_input(mui, container) , group(_group) { + set_heading(std::move(heading)); } menu_input_general::~menu_input_general() { } +void menu_input_general::menu_activated() +{ + // scripts can change settings out from under us + reset(reset_options::REMEMBER_POSITION); +} + void menu_input_general::populate(float &customtop, float &custombottom) { if (data.empty()) @@ -135,12 +149,21 @@ void menu_input_general::update_input(input_item_data &seqchangeditem) menu_input_specific::menu_input_specific(mame_ui_manager &mui, render_container &container) : menu_input(mui, container) { + set_heading(_("Input Assignments (this system)")); } menu_input_specific::~menu_input_specific() { } +void menu_input_specific::menu_activated() +{ + // scripts can change settings out from under us + assert(!pollingitem); + data.clear(); + reset(reset_options::REMEMBER_POSITION); +} + void menu_input_specific::populate(float &customtop, float &custombottom) { if (data.empty()) @@ -228,7 +251,7 @@ void menu_input_specific::populate(float &customtop, float &custombottom) if (!data.empty()) populate_sorted(customtop, custombottom); else - item_append(_("This machine has no configurable inputs."), FLAG_DISABLE, nullptr); + item_append(_("[no assignable inputs are enabled]"), FLAG_DISABLE, nullptr); item_append(menu_item_type::SEPARATOR); } @@ -274,12 +297,6 @@ menu_input::~menu_input() { } -void menu_input::menu_activated() -{ - // scripts can change settings out from under us - reset(reset_options::REMEMBER_POSITION); -} - /*------------------------------------------------- toggle_none_default - toggle between "NONE" @@ -398,7 +415,7 @@ void menu_input::handle(event const *ev) { // entered invalid sequence - abandon change invalidate = true; - errormsg = _("Invalid sequence entered"); + errormsg = _("Invalid combination entered"); erroritem = item; } seq_poll.reset(); diff --git a/src/frontend/mame/ui/inputmap.h b/src/frontend/mame/ui/inputmap.h index a43a6829b06..c651a8cc3d3 100644 --- a/src/frontend/mame/ui/inputmap.h +++ b/src/frontend/mame/ui/inputmap.h @@ -64,8 +64,6 @@ protected: menu_input(mame_ui_manager &mui, render_container &container); - virtual void menu_activated() override; - void populate_sorted(float &customtop, float &custombottom); void toggle_none_default(input_seq &selected_seq, input_seq &original_seq, const input_seq &selected_defseq); @@ -92,9 +90,12 @@ private: class menu_input_general : public menu_input { public: - menu_input_general(mame_ui_manager &mui, render_container &container, int group); + menu_input_general(mame_ui_manager &mui, render_container &container, int group, std::string &&heading); virtual ~menu_input_general() override; +protected: + virtual void menu_activated() override; + private: virtual void populate(float &customtop, float &custombottom) override; virtual void update_input(input_item_data &seqchangeditem) override; @@ -109,6 +110,9 @@ public: menu_input_specific(mame_ui_manager &mui, render_container &container); virtual ~menu_input_specific() override; +protected: + virtual void menu_activated() override; + private: virtual void populate(float &customtop, float &custombottom) override; virtual void update_input(input_item_data &seqchangeditem) override; diff --git a/src/frontend/mame/ui/inputopts.cpp b/src/frontend/mame/ui/inputopts.cpp new file mode 100644 index 00000000000..6884574c6a5 --- /dev/null +++ b/src/frontend/mame/ui/inputopts.cpp @@ -0,0 +1,141 @@ +// license:BSD-3-Clause +// copyright-holders:Vas Crabb +/*************************************************************************** + + ui/inputopts.cpp + + Input options submenu. + +***************************************************************************/ + +#include "emu.h" +#include "ui/inputopts.h" + +#include "ui/analogipt.h" +#include "ui/inputdevices.h" +#include "ui/inputmap.h" +#include "ui/inputtoggle.h" +#include "ui/keyboard.h" + +#include "natkeyboard.h" + + +namespace ui { + +namespace { + +enum : unsigned +{ + INPUTMAP_GENERAL = 1, + INPUTMAP_MACHINE, + ANALOG, + KEYBOARD, + TOGGLES, + INPUTDEV +}; + + +void scan_inputs(running_machine &machine, bool &inputmap, bool &analog, bool &toggle) +{ + inputmap = analog = toggle = false; + for (auto &port : machine.ioport().ports()) + { + for (ioport_field &field : port.second->fields()) + { + if (field.enabled()) + { + switch (field.type_class()) + { + case INPUT_CLASS_CONTROLLER: + case INPUT_CLASS_MISC: + case INPUT_CLASS_KEYBOARD: + inputmap = true; + if (field.live().toggle) + toggle = true; + break; + default: + break; + } + if (field.is_analog()) + analog = true; + + if (inputmap && analog && toggle) + return; + } + } + } +} + +} // anonymous namespace + + +menu_input_options::menu_input_options(mame_ui_manager &mui, render_container &container) + : menu(mui, container) +{ + set_heading(_("menu-inputopts", "Input Settings")); +} + + +menu_input_options::~menu_input_options() +{ +} + + +void menu_input_options::menu_activated() +{ + reset(reset_options::REMEMBER_REF); +} + + +void menu_input_options::populate(float &customtop, float &custombottom) +{ + bool inputmap, analog, toggle; + scan_inputs(machine(), inputmap, analog, toggle); + + item_append(_("menu-inputopts", "Input Assignments (general)"), 0, (void *)INPUTMAP_GENERAL); + if (inputmap) + item_append(_("menu-inputopts", "Input Assignments (this system)"), 0, (void *)INPUTMAP_MACHINE); + if (analog) + item_append(_("menu-inputopts", "Analog Input Adjustments"), 0, (void *)ANALOG); + if (machine().natkeyboard().keyboard_count()) + item_append(_("menu-inputopts", "Keyboard Selection"), 0, (void *)KEYBOARD); + if (toggle) + item_append(_("menu-inputopts", "Toggle Inputs"), 0, (void *)TOGGLES); + + item_append(menu_item_type::SEPARATOR); + + item_append(_("menu-inputopts", "Input Devices"), 0, (void *)INPUTDEV); + + item_append(menu_item_type::SEPARATOR); +} + + +void menu_input_options::handle(event const *ev) +{ + if (ev && (IPT_UI_SELECT == ev->iptkey)) + { + switch (uintptr_t(ev->itemref)) + { + case INPUTMAP_GENERAL: + stack_push(ui(), container()); + break; + case INPUTMAP_MACHINE: + stack_push(ui(), container()); + break; + case ANALOG: + stack_push(ui(), container()); + break; + case KEYBOARD: + stack_push(ui(), container()); + break; + case TOGGLES: + stack_push(ui(), container()); + break; + case INPUTDEV: + stack_push(ui(), container()); + break; + } + } +} + +} // namespace ui diff --git a/src/frontend/mame/ui/inputopts.h b/src/frontend/mame/ui/inputopts.h new file mode 100644 index 00000000000..11432ce5035 --- /dev/null +++ b/src/frontend/mame/ui/inputopts.h @@ -0,0 +1,37 @@ +// license:BSD-3-Clause +// copyright-holders:Vas Crabb +/*************************************************************************** + + ui/inputopts.h + + Input options submenu. + +***************************************************************************/ + +#ifndef MAME_FRONTEND_UI_INPUTOPTS_H +#define MAME_FRONTEND_UI_INPUTOPTS_H + +#pragma once + +#include "ui/menu.h" + + +namespace ui { + +class menu_input_options : public menu +{ +public: + menu_input_options(mame_ui_manager &mui, render_container &container); + virtual ~menu_input_options(); + +protected: + virtual void menu_activated() override; + +private: + virtual void populate(float &customtop, float &custombottom) override; + virtual void handle(event const *ev) override; +}; + +} // namespace ui + +#endif // MAME_FRONTEND_UI_INPUTOPTS_H diff --git a/src/frontend/mame/ui/inputtoggle.cpp b/src/frontend/mame/ui/inputtoggle.cpp new file mode 100644 index 00000000000..b21cd572c1d --- /dev/null +++ b/src/frontend/mame/ui/inputtoggle.cpp @@ -0,0 +1,219 @@ +// license:BSD-3-Clause +// copyright-holders:Vas Crabb +/*************************************************************************** + + ui/inputtoggle.cpp + + Toggle inputs menu. + +***************************************************************************/ + +#include "emu.h" +#include "ui/inputtoggle.h" + +#include + + +namespace ui { + +menu_input_toggles::menu_input_toggles(mame_ui_manager &mui, render_container &container) + : menu(mui, container) +{ + set_heading(_("menu-inputtoggle", "Toggle Inputs")); +} + + +menu_input_toggles::~menu_input_toggles() +{ +} + + +void menu_input_toggles::menu_activated() +{ + // enabled inputs and state of inputs can change while menu is inactive + reset(reset_options::REMEMBER_REF); +} + + +void menu_input_toggles::populate(float &customtop, float &custombottom) +{ + // find toggle fields + if (m_fields.empty()) + { + for (auto &port : machine().ioport().ports()) + { + for (ioport_field &field : port.second->fields()) + { + switch (field.type_class()) + { + case INPUT_CLASS_CONTROLLER: + case INPUT_CLASS_MISC: + case INPUT_CLASS_KEYBOARD: + if (field.live().toggle) + m_fields.emplace_back(field); + break; + default: + break; + } + } + } + } + + // create corresponding items for enabled fields + device_t *prev_owner = nullptr; + for (auto &field : m_fields) + { + if (field.get().enabled()) + { + // add a device heading if necessary + if (&field.get().device() != prev_owner) + { + prev_owner = &field.get().device(); + if (prev_owner->owner()) + item_append(string_format(_("%1$s [root%2$s]"), prev_owner->type().fullname(), prev_owner->tag()), FLAG_UI_HEADING | FLAG_DISABLE, nullptr); + else + item_append(string_format(_("[root%1$s]"), prev_owner->tag()), FLAG_UI_HEADING | FLAG_DISABLE, nullptr); + } + + // choose the display name for the value + char const *setting; + u32 flags = 0U; + if (!field.get().settings().empty()) + { + setting = field.get().setting_name(); + if (field.get().has_previous_setting()) + flags |= FLAG_LEFT_ARROW; + if (field.get().has_next_setting()) + flags |= FLAG_RIGHT_ARROW; + } + else if (field.get().defvalue() == field.get().live().value) + { + setting = _("Off"); + flags = FLAG_RIGHT_ARROW; + } + else + { + setting = _("On"); + flags = FLAG_LEFT_ARROW; + } + + // actually create the item + item_append(field.get().name(), setting, flags, &field); + } + } + + // display a message if there are toggle inputs enabled + if (!prev_owner) + item_append(_("menu-inputtoggle", "[no toggle inputs are enabled]"), FLAG_DISABLE, nullptr); + + item_append(menu_item_type::SEPARATOR); +} + + +void menu_input_toggles::handle(event const *ev) +{ + if (ev && ev->itemref) + { + auto const ref = reinterpret_cast *>(ev->itemref); + ioport_field &field = ref->get(); + bool invalidate = false; + switch (ev->iptkey) + { + case IPT_UI_SELECT: // toggle regular items, set multi-value items to default + if (field.settings().empty()) + { + field.live().value ^= field.mask(); + invalidate = true; + break; + } + [[fallthrough]]; + + case IPT_UI_CLEAR: // set to default + if (field.defvalue() != field.live().value) + { + field.live().value = field.defvalue(); + invalidate = true; + } + break; + + case IPT_UI_LEFT: // toggle or select previous setting + if (field.settings().empty()) + field.live().value ^= field.mask(); + else + field.select_previous_setting(); + invalidate = true; + break; + + case IPT_UI_RIGHT: // toggle or select next setting + if (field.settings().empty()) + field.live().value ^= field.mask(); + else + field.select_next_setting(); + invalidate = true; + break; + + case IPT_UI_PREV_GROUP: // previous device if any + { + auto current = std::distance(m_fields.data(), ref); + device_t const *dev = &field.device(); + bool found_break = false; + void *candidate = nullptr; + while (0 < current) + { + if (!found_break) + { + if (m_fields[--current].get().enabled()) + { + device_t const *prev = &m_fields[current].get().device(); + if (prev != dev) + { + dev = prev; + found_break = true; + candidate = &m_fields[current]; + } + } + } + else if (&m_fields[--current].get().device() != dev) + { + set_selection(candidate); + set_top_line(selected_index() - 1); + break; + } + else if (m_fields[current].get().enabled()) + { + candidate = &m_fields[current]; + } + if (found_break && !current) + { + set_selection(candidate); + set_top_line(selected_index() - 1); + break; + } + } + } + break; + + case IPT_UI_NEXT_GROUP: // next device if any + { + auto current = std::distance(m_fields.data(), ref); + device_t const *const dev = &field.device(); + while (m_fields.size() > ++current) + { + if (m_fields[current].get().enabled() && (&m_fields[current].get().device() != dev)) + { + set_selection(&m_fields[current]); + set_top_line(selected_index() - 1); + break; + } + } + } + break; + } + + // changing value can enable or disable other fields + if (invalidate) + reset(reset_options::REMEMBER_REF); + } +} + +} // namespace ui diff --git a/src/frontend/mame/ui/inputtoggle.h b/src/frontend/mame/ui/inputtoggle.h new file mode 100644 index 00000000000..7a3016f6254 --- /dev/null +++ b/src/frontend/mame/ui/inputtoggle.h @@ -0,0 +1,42 @@ +// license:BSD-3-Clause +// copyright-holders:Vas Crabb +/*************************************************************************** + + ui/inputtoggle.h + + Toggle inputs menu. + +***************************************************************************/ + +#ifndef MAME_FRONTEND_UI_INPUTTOGGLE_H +#define MAME_FRONTEND_UI_INPUTTOGGLE_H + +#pragma once + +#include "ui/menu.h" + +#include +#include + + +namespace ui { + +class menu_input_toggles : public menu +{ +public: + menu_input_toggles(mame_ui_manager &mui, render_container &container); + virtual ~menu_input_toggles(); + +protected: + virtual void menu_activated() override; + +private: + virtual void populate(float &customtop, float &custombottom) override; + virtual void handle(event const *ev) override; + + std::vector > m_fields; +}; + +} // namespace ui + +#endif // MAME_FRONTEND_UI_INPUTTOGGLE_H diff --git a/src/frontend/mame/ui/keyboard.cpp b/src/frontend/mame/ui/keyboard.cpp index cbdc3324212..7efebefd64c 100644 --- a/src/frontend/mame/ui/keyboard.cpp +++ b/src/frontend/mame/ui/keyboard.cpp @@ -26,6 +26,7 @@ constexpr uintptr_t ITEM_KBDEV_FIRST = 0x00000200; menu_keyboard_mode::menu_keyboard_mode(mame_ui_manager &mui, render_container &container) : menu(mui, container) { + set_heading(_("menu-keyboard", "Keyboard Selection")); } void menu_keyboard_mode::menu_activated() @@ -42,8 +43,8 @@ void menu_keyboard_mode::populate(float &customtop, float &custombottom) { bool const natmode(natkbd.in_use()); item_append( - _("Keyboard Mode"), - natmode ? _("Natural") : _("Emulated"), + _("menu-keyboard", "Keyboard Mode"), + natmode ? _("menu-keyboard", "Natural") : _("menu-keyboard", "Emulated"), natmode ? FLAG_LEFT_ARROW : FLAG_RIGHT_ARROW, reinterpret_cast(ITEM_KBMODE)); item_append(menu_item_type::SEPARATOR); @@ -88,7 +89,7 @@ void menu_keyboard_mode::handle(event const *ev) if ((left || right) && (natkbd.in_use() != right)) { natkbd.set_in_use(right); - ev->item->set_subtext(right ? _("Natural") : _("Emulated")); + ev->item->set_subtext(right ? _("menu-keyboard", "Natural") : _("menu-keyboard", "Emulated")); ev->item->set_flags(right ? FLAG_LEFT_ARROW : FLAG_RIGHT_ARROW); } } diff --git a/src/frontend/mame/ui/mainmenu.cpp b/src/frontend/mame/ui/mainmenu.cpp index 74f0060b6df..aebe9a5886b 100644 --- a/src/frontend/mame/ui/mainmenu.cpp +++ b/src/frontend/mame/ui/mainmenu.cpp @@ -12,7 +12,6 @@ #include "ui/mainmenu.h" #include "ui/about.h" -#include "ui/analogipt.h" #include "ui/barcode.h" #include "ui/cheatopt.h" #include "ui/confswitch.h" @@ -21,8 +20,7 @@ #include "ui/info.h" #include "ui/info_pty.h" #include "ui/inifile.h" -#include "ui/inputmap.h" -#include "ui/keyboard.h" +#include "ui/inputopts.h" #include "ui/miscmenu.h" #include "ui/pluginopt.h" #include "ui/selgame.h" @@ -35,23 +33,20 @@ #include "mame.h" #include "luaengine.h" -#include "machine/bcreader.h" #include "imagedev/cassette.h" +#include "machine/bcreader.h" #include "crsshair.h" #include "dipty.h" #include "emuopts.h" -#include "natkeyboard.h" namespace ui { enum : unsigned { - INPUT_GROUPS, - INPUT_SPECIFIC, + INPUT_OPTIONS, SETTINGS_DIP_SWITCHES, SETTINGS_DRIVER_CONFIG, - ANALOG, BOOKKEEPING, GAME_INFO, WARN_INFO, @@ -60,10 +55,8 @@ enum : unsigned { TAPE_CONTROL, SLOT_DEVICES, NETWORK_DEVICES, - KEYBOARD_MODE, SLIDERS, VIDEO_TARGETS, - VIDEO_OPTIONS, CROSSHAIR, CHEAT, PLUGINS, @@ -118,99 +111,92 @@ void menu_main::populate(float &customtop, float &custombottom) { m_phase = machine().phase(); - item_append(_("Input (general)"), 0, (void *)INPUT_GROUPS); - - item_append(_("Input (this machine)"), 0, (void *)INPUT_SPECIFIC); + item_append(_("menu-main", "Input Settings"), 0, (void *)INPUT_OPTIONS); - if (ui().machine_info().has_analog()) - item_append(_("Analog Controls"), 0, (void *)ANALOG); if (ui().machine_info().has_dips()) - item_append(_("DIP Switches"), 0, (void *)SETTINGS_DIP_SWITCHES); + item_append(_("menu-main", "DIP Switches"), 0, (void *)SETTINGS_DIP_SWITCHES); if (ui().machine_info().has_configs()) - item_append(_("Machine Configuration"), 0, (void *)SETTINGS_DRIVER_CONFIG); + item_append(_("menu-main", "Machine Configuration"), 0, (void *)SETTINGS_DRIVER_CONFIG); - item_append(_("Bookkeeping Info"), 0, (void *)BOOKKEEPING); + item_append(_("menu-main", "Bookkeeping Info"), 0, (void *)BOOKKEEPING); - item_append(_("Machine Information"), 0, (void *)GAME_INFO); + item_append(_("menu-main", "System Information"), 0, (void *)GAME_INFO); if (ui().found_machine_warnings()) - item_append(_("Warning Information"), 0, (void *)WARN_INFO); + item_append(_("menu-main", "Warning Information"), 0, (void *)WARN_INFO); for (device_image_interface &image : image_interface_enumerator(machine().root_device())) { if (image.user_loadable()) { - item_append(_("Image Information"), 0, (void *)IMAGE_MENU_IMAGE_INFO); + item_append(_("menu-main", "Media Image Information"), 0, (void *)IMAGE_MENU_IMAGE_INFO); - item_append(_("File Manager"), 0, (void *)IMAGE_MENU_FILE_MANAGER); + item_append(_("menu-main", "File Manager"), 0, (void *)IMAGE_MENU_FILE_MANAGER); break; } } if (cassette_device_enumerator(machine().root_device()).first() != nullptr) - item_append(_("Tape Control"), 0, (void *)TAPE_CONTROL); + item_append(_("menu-main", "Tape Control"), 0, (void *)TAPE_CONTROL); if (pty_interface_enumerator(machine().root_device()).first() != nullptr) - item_append(_("Pseudo Terminals"), 0, (void *)PTY_INFO); + item_append(_("menu-main", "Pseudo Terminals"), 0, (void *)PTY_INFO); if (ui().machine_info().has_bioses()) - item_append(_("BIOS Selection"), 0, (void *)BIOS_SELECTION); + item_append(_("menu-main", "BIOS Selection"), 0, (void *)BIOS_SELECTION); if (slot_interface_enumerator(machine().root_device()).first() != nullptr) - item_append(_("Slot Devices"), 0, (void *)SLOT_DEVICES); + item_append(_("menu-main", "Slot Devices"), 0, (void *)SLOT_DEVICES); if (barcode_reader_device_enumerator(machine().root_device()).first() != nullptr) - item_append(_("Barcode Reader"), 0, (void *)BARCODE_READ); + item_append(_("menu-main", "Barcode Reader"), 0, (void *)BARCODE_READ); if (network_interface_enumerator(machine().root_device()).first() != nullptr) - item_append(_("Network Devices"), 0, (void*)NETWORK_DEVICES); + item_append(_("menu-main", "Network Devices"), 0, (void*)NETWORK_DEVICES); - if (machine().natkeyboard().keyboard_count()) - item_append(_("Keyboard Mode"), 0, (void *)KEYBOARD_MODE); + item_append(_("menu-main", "Slider Controls"), 0, (void *)SLIDERS); - item_append(_("Slider Controls"), 0, (void *)SLIDERS); - - item_append(_("Video Options"), 0, (void *)VIDEO_TARGETS); + item_append(_("menu-main", "Video Options"), 0, (void *)VIDEO_TARGETS); if (machine().crosshair().get_usage()) - item_append(_("Crosshair Options"), 0, (void *)CROSSHAIR); + item_append(_("menu-main", "Crosshair Options"), 0, (void *)CROSSHAIR); if (machine().options().cheat()) - item_append(_("Cheat"), 0, (void *)CHEAT); + item_append(_("menu-main", "Cheat"), 0, (void *)CHEAT); if (machine_phase::RESET <= m_phase) { if (machine().options().plugins() && !mame_machine_manager::instance()->lua()->get_menu().empty()) - item_append(_("Plugin Options"), 0, (void *)PLUGINS); + item_append(_("menu-main", "Plugin Options"), 0, (void *)PLUGINS); if (mame_machine_manager::instance()->lua()->call_plugin_check("data_list", "", true)) - item_append(_("External DAT View"), 0, (void *)EXTERNAL_DATS); + item_append(_("menu-main", "External DAT View"), 0, (void *)EXTERNAL_DATS); } item_append(menu_item_type::SEPARATOR); if (!mame_machine_manager::instance()->favorite().is_favorite(machine())) - item_append(_("Add To Favorites"), 0, (void *)ADD_FAVORITE); + item_append(_("menu-main", "Add To Favorites"), 0, (void *)ADD_FAVORITE); else - item_append(_("Remove From Favorites"), 0, (void *)REMOVE_FAVORITE); + item_append(_("menu-main", "Remove From Favorites"), 0, (void *)REMOVE_FAVORITE); item_append(menu_item_type::SEPARATOR); - item_append(string_format(_("About %1$s"), emulator_info::get_appname()), 0, (void *)ABOUT); + item_append(string_format(_("menu-main", "About %1$s"), emulator_info::get_appname()), 0, (void *)ABOUT); item_append(menu_item_type::SEPARATOR); -// item_append(_("Quit from Machine"), 0, (void *)QUIT_GAME); +// item_append(_("menu-main", "Quit from System"), 0, (void *)QUIT_GAME); if (machine_phase::INIT == m_phase) { - item_append(_("Start Machine"), 0, (void *)DISMISS); + item_append(_("menu-main", "Start System"), 0, (void *)DISMISS); } else { - item_append(_("Select New Machine"), 0, (void *)SELECT_GAME); - item_append(_("Return to Machine"), 0, (void *)DISMISS); + item_append(_("menu-main", "Select New System"), 0, (void *)SELECT_GAME); + item_append(_("menu-main", "Close Menu"), 0, (void *)DISMISS); } } @@ -226,12 +212,8 @@ void menu_main::handle(event const *ev) { switch (uintptr_t(ev->itemref)) { - case INPUT_GROUPS: - menu::stack_push(ui(), container()); - break; - - case INPUT_SPECIFIC: - menu::stack_push(ui(), container()); + case INPUT_OPTIONS: + menu::stack_push(ui(), container()); break; case SETTINGS_DIP_SWITCHES: @@ -242,10 +224,6 @@ void menu_main::handle(event const *ev) menu::stack_push(ui(), container()); break; - case ANALOG: - menu::stack_push(ui(), container()); - break; - case BOOKKEEPING: menu::stack_push(ui(), container()); break; @@ -282,10 +260,6 @@ void menu_main::handle(event const *ev) menu::stack_push(ui(), container()); break; - case KEYBOARD_MODE: - menu::stack_push(ui(), container()); - break; - case SLIDERS: menu::stack_push(ui(), container(), false); break; @@ -294,10 +268,6 @@ void menu_main::handle(event const *ev) menu::stack_push(ui(), container()); break; - case VIDEO_OPTIONS: - menu::stack_push(ui(), container(), *machine().render().first_target(), false); - break; - case CROSSHAIR: menu::stack_push(ui(), container()); break; diff --git a/src/frontend/mame/ui/menu.cpp b/src/frontend/mame/ui/menu.cpp index c69b792e1c0..dbe1b29a813 100644 --- a/src/frontend/mame/ui/menu.cpp +++ b/src/frontend/mame/ui/menu.cpp @@ -28,7 +28,6 @@ #include #include #include -#include namespace ui { @@ -236,7 +235,9 @@ menu::menu(mame_ui_manager &mui, render_container &container) , m_ui(mui) , m_container(container) , m_parent() + , m_heading() , m_items() + , m_rebuilding(false) , m_process_flags(0) , m_selected(0) , m_hover(1) @@ -245,14 +246,14 @@ menu::menu(mame_ui_manager &mui, render_container &container) , m_needs_prev_menu_item(true) , m_active(false) , m_event() - , m_customtop(0.0f) - , m_custombottom(0.0f) + , m_customtop(0.0F) + , m_custombottom(0.0F) , m_resetpos(0) , m_resetref(nullptr) , m_mouse_hit(false) , m_mouse_button(false) - , m_mouse_x(-1.0f) - , m_mouse_y(-1.0f) + , m_mouse_x(-1.0F) + , m_mouse_y(-1.0F) { reset(reset_options::SELECT_FIRST); @@ -321,6 +322,8 @@ void menu::item_append(menu_item_type type, uint32_t flags) void menu::item_append(std::string &&text, std::string &&subtext, uint32_t flags, void *ref, menu_item_type type) { + assert(m_rebuilding); + // allocate a new item and populate it menu_item pitem(type, ref, flags); pitem.set_text(std::move(text)); @@ -386,7 +389,7 @@ const menu::event *menu::process() return true; }; if (draw_parent(draw_parent, m_parent.get())) - container().add_rect(0.0f, 0.0f, 1.0f, 1.0f, rgb_t(114, 0, 0, 0), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA)); + container().add_rect(0.0F, 0.0F, 1.0F, 1.0F, rgb_t(114, 0, 0, 0), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA)); // draw the menu proper draw(m_process_flags); @@ -447,12 +450,13 @@ void menu::set_selection(void *selected_itemref) void menu::draw(uint32_t flags) { // first draw the FPS counter + // FIXME: provide a way to do this in the UI manager itself while menus are on-screen if (ui().show_fps_counter()) { ui().draw_text_full( container(), machine().video().speed_text(), - 0.0f, 0.0f, 1.0f, + 0.0F, 0.0F, 1.0F, text_layout::text_justify::RIGHT, text_layout::word_wrapping::WORD, mame_ui_manager::OPAQUE_, rgb_t::white(), rgb_t::black(), nullptr, nullptr); @@ -462,10 +466,11 @@ void menu::draw(uint32_t flags) bool const noinput = (flags & PROCESS_NOINPUT); float const aspect = machine().render().ui_aspect(&container()); float const line_height = ui().get_line_height(); - float const lr_arrow_width = 0.4f * line_height * aspect; + float const lr_arrow_width = 0.4F * line_height * aspect; float const ud_arrow_width = line_height * aspect; - float const gutter_width = lr_arrow_width * 1.3f; + float const gutter_width = 0.5F * line_height * aspect; float const lr_border = ui().box_lr_border() * aspect; + float const max_width = 1.0F - ((lr_border + (aspect * UI_LINE_WIDTH)) * 2.0F); if (is_special_main_menu()) draw_background(); @@ -480,38 +485,46 @@ void menu::draw(uint32_t flags) // add in width of right hand side if (!pitem.subtext().empty()) - total_width += 2.0f * gutter_width + ui().get_string_width(pitem.subtext()); + total_width += 2.0F * gutter_width + ui().get_string_width(pitem.subtext()); else if (pitem.flags() & FLAG_UI_HEADING) - total_width += 4.0f * ud_arrow_width; + total_width += 4.0F * ud_arrow_width; // track the maximum - if (total_width > visible_width) - visible_width = total_width; + visible_width = std::max(total_width, visible_width); // track the height as well visible_main_menu_height += line_height; } + // lay out the heading if present + std::optional heading_layout; + if (m_heading) + { + heading_layout.emplace(ui().create_layout(container(), max_width - (gutter_width * 2.0F), text_layout::text_justify::CENTER)); + heading_layout->add_text(*m_heading, ui().colors().text_color()); + } + // account for extra space at the top and bottom - float const visible_extra_menu_height = m_customtop + m_custombottom; + float const top_extra_menu_height = m_customtop + (heading_layout ? (heading_layout->actual_height() + (ui().box_tb_border() * 3.0F)) : 0.0F); + float const visible_extra_menu_height = top_extra_menu_height + m_custombottom; // add a little bit of slop for rounding - visible_width += 0.01f; - visible_main_menu_height += 0.01f; + visible_width += 0.01F; + visible_main_menu_height += 0.01F; // if we are too wide or too tall, clamp it down - visible_width = std::min(visible_width, 1.0f - ((lr_border + (aspect * UI_LINE_WIDTH)) * 2.0f)); + visible_width = std::min(visible_width, max_width); // if the menu and extra menu won't fit, take away part of the regular menu, it will scroll - if (visible_main_menu_height + visible_extra_menu_height + 2.0f * ui().box_tb_border() > 1.0f) - visible_main_menu_height = 1.0f - 2.0f * ui().box_tb_border() - visible_extra_menu_height; + if (visible_main_menu_height + visible_extra_menu_height + 2.0F * ui().box_tb_border() > 1.0F) + visible_main_menu_height = 1.0F - 2.0F * ui().box_tb_border() - visible_extra_menu_height; m_visible_lines = std::min(int(std::floor(visible_main_menu_height / line_height)), int(unsigned(m_items.size()))); visible_main_menu_height = float(m_visible_lines) * line_height; // compute top/left of inner menu area by centering - float const visible_left = (1.0f - visible_width) * 0.5f; - float const visible_top = ((1.0f - visible_main_menu_height - visible_extra_menu_height) * 0.5f) + m_customtop; + float const visible_left = (1.0F - visible_width) * 0.5F; + float const visible_top = ((1.0F - visible_main_menu_height - visible_extra_menu_height) * 0.5F) + top_extra_menu_height; // first add us a box float const x1 = visible_left - lr_border; @@ -519,7 +532,26 @@ void menu::draw(uint32_t flags) float const x2 = visible_left + visible_width + lr_border; float const y2 = visible_top + visible_main_menu_height + ui().box_tb_border(); if (!customonly) - ui().draw_outlined_box(container(), x1, y1, x2, y2, ui().colors().background_color()); + { + if (heading_layout) + { + float const heading_width = heading_layout->actual_width(); + float const heading_left = (1.0F - heading_width) * 0.5F; + float const hx1 = std::min(x1, heading_left - gutter_width - lr_border); + float const hx2 = std::max(x2, heading_left + heading_width + gutter_width + lr_border); + ui().draw_outlined_box( + container(), + hx1, y1 - top_extra_menu_height, + hx2, y1 - m_customtop - ui().box_tb_border(), + UI_GREEN_COLOR); + heading_layout->emit(container(), (1.0F - heading_layout->width()) * 0.5F, y1 - top_extra_menu_height + ui().box_tb_border()); + } + ui().draw_outlined_box( + container(), + x1, y1, + x2, y2, + ui().colors().background_color()); + } if ((m_selected >= (top_line + m_visible_lines)) || (m_selected < (top_line + 1))) top_line = m_selected - (m_visible_lines / 2); @@ -538,7 +570,7 @@ void menu::draw(uint32_t flags) m_visible_items = m_visible_lines - (show_top_arrow ? 1 : 0) - (show_bottom_arrow ? 1 : 0); // determine effective positions taking into account the hilighting arrows - float const effective_width = visible_width - 2.0f * gutter_width; + float const effective_width = visible_width - 2.0F * gutter_width; float const effective_left = visible_left + gutter_width; // locate mouse @@ -550,8 +582,8 @@ void menu::draw(uint32_t flags) // loop over visible lines m_hover = m_items.size() + 1; bool selected_subitem_too_big = false; - float const line_x0 = x1 + 0.5f * UI_LINE_WIDTH; - float const line_x1 = x2 - 0.5f * UI_LINE_WIDTH; + float const line_x0 = x1 + 0.5F * UI_LINE_WIDTH; + float const line_x1 = x2 - 0.5F * UI_LINE_WIDTH; if (!customonly) { for (int linenum = 0; linenum < m_visible_lines; linenum++) @@ -603,10 +635,10 @@ void menu::draw(uint32_t flags) { // if we're on the top line, display the up arrow draw_arrow( - 0.5f * (x1 + x2) - 0.5f * ud_arrow_width, - line_y0 + 0.25f * line_height, - 0.5f * (x1 + x2) + 0.5f * ud_arrow_width, - line_y0 + 0.75f * line_height, + 0.5F * (x1 + x2) - 0.5F * ud_arrow_width, + line_y0 + 0.25F * line_height, + 0.5F * (x1 + x2) + 0.5F * ud_arrow_width, + line_y0 + 0.75F * line_height, fgcolor, ROT0); } @@ -614,17 +646,17 @@ void menu::draw(uint32_t flags) { // if we're on the bottom line, display the down arrow draw_arrow( - 0.5f * (x1 + x2) - 0.5f * ud_arrow_width, - line_y0 + 0.25f * line_height, - 0.5f * (x1 + x2) + 0.5f * ud_arrow_width, - line_y0 + 0.75f * line_height, + 0.5F * (x1 + x2) - 0.5F * ud_arrow_width, + line_y0 + 0.25F * line_height, + 0.5F * (x1 + x2) + 0.5F * ud_arrow_width, + line_y0 + 0.75F * line_height, fgcolor, ROT0 ^ ORIENTATION_FLIP_Y); } else if (pitem.type() == menu_item_type::SEPARATOR) { // if we're just a divider, draw a line - container().add_line(visible_left, line_y0 + 0.5f * line_height, visible_left + visible_width, line_y0 + 0.5f * line_height, UI_LINE_WIDTH, ui().colors().border_color(), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA)); + container().add_line(visible_left, line_y0 + 0.5F * line_height, visible_left + visible_width, line_y0 + 0.5F * line_height, UI_LINE_WIDTH, ui().colors().border_color(), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA)); } else if (pitem.subtext().empty()) { @@ -632,8 +664,8 @@ void menu::draw(uint32_t flags) if (pitem.flags() & FLAG_UI_HEADING) { float heading_width = ui().get_string_width(itemtext); - container().add_line(visible_left, line_y0 + 0.5f * line_height, visible_left + ((visible_width - heading_width) / 2) - lr_border, line_y0 + 0.5f * line_height, UI_LINE_WIDTH, ui().colors().border_color(), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA)); - container().add_line(visible_left + visible_width - ((visible_width - heading_width) / 2) + lr_border, line_y0 + 0.5f * line_height, visible_left + visible_width, line_y0 + 0.5f * line_height, UI_LINE_WIDTH, ui().colors().border_color(), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA)); + container().add_line(visible_left, line_y0 + 0.5F * line_height, visible_left + ((visible_width - heading_width) / 2) - lr_border, line_y0 + 0.5F * line_height, UI_LINE_WIDTH, ui().colors().border_color(), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA)); + container().add_line(visible_left + visible_width - ((visible_width - heading_width) / 2) + lr_border, line_y0 + 0.5F * line_height, visible_left + visible_width, line_y0 + 0.5F * line_height, UI_LINE_WIDTH, ui().colors().border_color(), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA)); } ui().draw_text_full( container(), @@ -667,8 +699,8 @@ void menu::draw(uint32_t flags) ui().draw_outlined_box( container(), - effective_left + effective_width - subitem_width, line_y0 + (UI_LINE_WIDTH * 2.0f), - effective_left + effective_width, line_y1 - (UI_LINE_WIDTH * 2.0f), + effective_left + effective_width - subitem_width, line_y0 + (UI_LINE_WIDTH * 2.0F), + effective_left + effective_width, line_y1 - (UI_LINE_WIDTH * 2.0F), color); } else @@ -676,7 +708,7 @@ void menu::draw(uint32_t flags) std::string_view subitem_text(pitem.subtext()); // give 2 spaces worth of padding - item_width += 2.0f * gutter_width; + item_width += 2.0F * gutter_width; // if the subitem doesn't fit here, display dots if (ui().get_string_width(subitem_text) > effective_width - item_width) @@ -712,10 +744,10 @@ void menu::draw(uint32_t flags) float const l = effective_left + effective_width - subitem_width - gutter_width; float const r = l + lr_arrow_width; draw_arrow( - l, line_y0 + 0.1f * line_height, r, line_y0 + 0.9f * line_height, + l, line_y0 + 0.1F * line_height, r, line_y0 + 0.9F * line_height, fgcolor, ROT90 ^ ORIENTATION_FLIP_X); - if (mouse_in_rect(l, line_y0 + 0.1f * line_height, r, line_y0 + 0.9f * line_height)) + if (mouse_in_rect(l, line_y0 + 0.1F * line_height, r, line_y0 + 0.9F * line_height)) m_hover = HOVER_UI_LEFT; } if (is_selected(itemnum) && (pitem.flags() & FLAG_RIGHT_ARROW)) @@ -723,10 +755,10 @@ void menu::draw(uint32_t flags) float const r = effective_left + effective_width + gutter_width; float const l = r - lr_arrow_width; draw_arrow( - l, line_y0 + 0.1f * line_height, r, line_y0 + 0.9f * line_height, + l, line_y0 + 0.1F * line_height, r, line_y0 + 0.9F * line_height, fgcolor, ROT90); - if (mouse_in_rect(l, line_y0 + 0.1f * line_height, r, line_y0 + 0.9f * line_height)) + if (mouse_in_rect(l, line_y0 + 0.1F * line_height, r, line_y0 + 0.9F * line_height)) m_hover = HOVER_UI_RIGHT; } } @@ -746,7 +778,7 @@ void menu::draw(uint32_t flags) ui().draw_text_full( container(), pitem.subtext(), - 0, 0, visible_width * 0.75f, + 0, 0, visible_width * 0.75F, text_layout::text_justify::RIGHT, text_layout::word_wrapping::WORD, mame_ui_manager::NONE, rgb_t::white(), rgb_t::black(), &target_width, &target_height); @@ -809,8 +841,8 @@ void menu::ignore_mouse() { m_mouse_hit = false; m_mouse_button = false; - m_mouse_x = -1.0f; - m_mouse_y = -1.0f; + m_mouse_x = -1.0F; + m_mouse_y = -1.0F; } @@ -1193,12 +1225,23 @@ void menu::do_handle() { if (m_items.empty()) { - // add an item to return - this is a really hacky way of doing this - if (m_needs_prev_menu_item) - item_append(_("Return to Previous Menu"), 0, nullptr); + m_rebuilding = true; + try + { + // add an item to return - this is a really hacky way of doing this + if (m_needs_prev_menu_item) + item_append(_("Return to Previous Menu"), 0, nullptr); - // let implementation add other items - populate(m_customtop, m_custombottom); + // let implementation add other items + populate(m_customtop, m_custombottom); + } + catch (...) + { + m_items.clear(); + m_rebuilding = false; + throw; + } + m_rebuilding = false; } handle(process()); } @@ -1274,7 +1317,7 @@ void menu::draw_background() { // draw background image if available if (ui().options().use_background_image() && m_global_state.bgrnd_bitmap() && m_global_state.bgrnd_bitmap()->valid()) - container().add_quad(0.0f, 0.0f, 1.0f, 1.0f, rgb_t::white(), m_global_state.bgrnd_texture(), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA)); + container().add_quad(0.0F, 0.0F, 1.0F, 1.0F, rgb_t::white(), m_global_state.bgrnd_texture(), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA)); } @@ -1290,7 +1333,7 @@ void menu::extra_text_position(float origx1, float origx2, float origy, float ys float maxwidth = std::max(width, origx2 - origx1); // compute our bounds - x1 = 0.5f - 0.5f * maxwidth; + x1 = 0.5F - (0.5F * maxwidth); x2 = x1 + maxwidth; y1 = origy + (yspan * direction); y2 = origy + (ui().box_tb_border() * direction); diff --git a/src/frontend/mame/ui/menu.h b/src/frontend/mame/ui/menu.h index 6b137a99631..ca1f3b7384d 100644 --- a/src/frontend/mame/ui/menu.h +++ b/src/frontend/mame/ui/menu.h @@ -23,7 +23,9 @@ #include #include #include +#include #include +#include #include @@ -49,6 +51,16 @@ public: virtual ~menu(); + // setting menu heading + template + void set_heading(T &&... args) + { + if (!m_heading) + m_heading.emplace(std::forward(args)...); + else + m_heading->assign(std::forward(args)...); + } + // append a new item to the end of the menu void item_append(const std::string &text, uint32_t flags, void *ref, menu_item_type type = menu_item_type::UNKNOWN) { item_append(std::string(text), std::string(), flags, ref, type); } void item_append(const std::string &text, const std::string &subtext, uint32_t flags, void *ref, menu_item_type type = menu_item_type::UNKNOWN) { item_append(std::string(text), std::string(subtext), flags, ref, type); } @@ -348,14 +360,14 @@ private: // to be implemented in derived classes virtual void handle(event const *ev) = 0; - // push a new menu onto the stack - static void stack_push(std::unique_ptr &&menu) { menu->m_global_state.stack_push(std::move(menu)); } - void extra_text_draw_box(float origx1, float origx2, float origy, float yspan, std::string_view text, int direction); bool first_item_visible() const { return top_line <= 0; } bool last_item_visible() const { return (top_line + m_visible_lines) >= m_items.size(); } + // push a new menu onto the stack + static void stack_push(std::unique_ptr &&menu) { menu->m_global_state.stack_push(std::move(menu)); } + static global_state &get_global_state(mame_ui_manager &ui); protected: // TODO: remove need to expose these - only used here and in selmenu.cpp @@ -369,7 +381,9 @@ private: render_container &m_container; // render_container we render to std::unique_ptr m_parent; // pointer to parent menu in the stack + std::optional m_heading; // menu heading std::vector m_items; // array of items + bool m_rebuilding; // ensure items are only added during rebuild uint32_t m_process_flags; // event processing options int m_selected; // which item is selected diff --git a/src/frontend/mame/ui/miscmenu.cpp b/src/frontend/mame/ui/miscmenu.cpp index aef5a60a7c3..58792ef56c8 100644 --- a/src/frontend/mame/ui/miscmenu.cpp +++ b/src/frontend/mame/ui/miscmenu.cpp @@ -49,6 +49,7 @@ namespace ui { menu_bios_selection::menu_bios_selection(mame_ui_manager &mui, render_container &container) : menu(mui, container) { + set_heading(_("BIOS Selection")); } void menu_bios_selection::populate(float &customtop, float &custombottom) @@ -70,7 +71,7 @@ void menu_bios_selection::populate(float &customtop, float &custombottom) val = rom->hashdata; } if (val) - item_append(!parent ? "driver" : (device.tag() + 1), val, FLAG_LEFT_ARROW | FLAG_RIGHT_ARROW, (void *)&device); + item_append(!parent ? _("System") : (device.tag() + 1), val, FLAG_LEFT_ARROW | FLAG_RIGHT_ARROW, (void *)&device); } } } @@ -144,6 +145,7 @@ void menu_bios_selection::handle(event const *ev) menu_network_devices::menu_network_devices(mame_ui_manager &mui, render_container &container) : menu(mui, container) { + set_heading(_("Network Devices")); } menu_network_devices::~menu_network_devices() @@ -349,10 +351,10 @@ void menu_crosshair::handle(event const *ev) { std::vector sel; sel.reserve(m_pics.size() + 1); - sel.push_back("DEFAULT"); + sel.push_back(_("menu-crosshair", "[built-in]")); std::copy(m_pics.begin(), m_pics.end(), std::back_inserter(sel)); menu::stack_push( - ui(), container(), std::move(sel), data.cur, + ui(), container(), std::string(ev->item->text()), std::move(sel), data.cur, [this, &data] (int selection) { if (!selection) @@ -390,6 +392,7 @@ void menu_crosshair::handle(event const *ev) menu_crosshair::menu_crosshair(mame_ui_manager &mui, render_container &container) : menu(mui, container) { set_process_flags(PROCESS_LR_REPEAT); + set_heading(_("menu-crosshair", "Crosshair Options")); } void menu_crosshair::populate(float &customtop, float &custombottom) @@ -449,7 +452,10 @@ void menu_crosshair::populate(float &customtop, float &custombottom) } // Make sure to keep these matched to the CROSSHAIR_VISIBILITY_xxx types - static char const *const vis_text[] = { "Off", "On", "Auto" }; + static char const *const vis_text[] = { + N_p("menu-crosshair", "Always"), + N_p("menu-crosshair", "Never"), + N_p("menu-crosshair", "When moved") }; bool use_auto = false; for (crosshair_item_data &data : m_data) @@ -472,7 +478,11 @@ void menu_crosshair::populate(float &customtop, float &custombottom) flags |= FLAG_RIGHT_ARROW; // add CROSSHAIR_ITEM_VIS menu */ - item_append(util::string_format(_("P%d Visibility"), data.player + 1), vis_text[data.crosshair->mode()], flags, &data); + item_append( + util::string_format(_("menu-crosshair", "P%1$d Visibility"), data.player + 1), + _("menu-crosshair", vis_text[data.crosshair->mode()]), + flags, + &data); } break; @@ -526,7 +536,12 @@ void menu_crosshair::populate(float &customtop, float &custombottom) flags |= FLAG_LEFT_ARROW; // add CROSSHAIR_ITEM_PIC menu - item_append(util::string_format(_("P%d Crosshair"), data.player + 1), using_default ? "DEFAULT" : data.crosshair->bitmap_name(), flags, &data); + item_append( + util::string_format(_("menu-crosshair", "P%1$d Crosshair"), data.player + 1), + using_default ? _("menu-crosshair", "[built-in]") : data.crosshair->bitmap_name(), + flags, + &data); + item_append(menu_item_type::SEPARATOR); } break; @@ -543,18 +558,16 @@ void menu_crosshair::populate(float &customtop, float &custombottom) flags |= FLAG_RIGHT_ARROW; // add CROSSHAIR_ITEM_AUTO_TIME menu - item_append(_("Visible Delay"), util::string_format("%d", data.cur), flags, &data); - } - else - { - // leave a blank filler line when not in auto time so size does not rescale - //item_append("", "", nullptr, nullptr); + item_append( + _("menu-crosshair", "Auto-Hide Delay"), + util::string_format(_("menu-crosshair", "%1$d s"), data.cur), + flags, + &data); + item_append(menu_item_type::SEPARATOR); } break; } } - - item_append(menu_item_type::SEPARATOR); } menu_crosshair::~menu_crosshair() @@ -568,6 +581,7 @@ menu_crosshair::~menu_crosshair() menu_export::menu_export(mame_ui_manager &mui, render_container &container, std::vector &&drvlist) : menu(mui, container), m_list(std::move(drvlist)) { + set_heading(_("Export Displayed List to File")); } menu_export::~menu_export() @@ -708,6 +722,7 @@ menu_machine_configure::menu_machine_configure( osd_setup_osd_specific_emu_options(m_opts); mame_options::parse_standard_inis(m_opts, error, m_sys.driver); setup_bios(); + set_heading(util::string_format(_("System Settings:\n%1$s"), m_sys.description)); } menu_machine_configure::~menu_machine_configure() @@ -746,7 +761,7 @@ void menu_machine_configure::handle(event const *ev) { std::string inistring = m_opts.output_ini(); file.puts(inistring); - ui().popup_time(2, "%s", _("\n Configuration saved \n\n")); + ui().popup_time(2, "%s", _("\n Settings saved \n\n")); } } break; @@ -758,14 +773,14 @@ void menu_machine_configure::handle(event const *ev) m_want_favorite = false; reset(reset_options::REMEMBER_POSITION); break; - case CONTROLLER: - if (ev->iptkey == IPT_UI_SELECT) - menu::stack_push(ui(), container(), submenu::control_options(), m_sys.driver, &m_opts); - break; case VIDEO: if (ev->iptkey == IPT_UI_SELECT) menu::stack_push(ui(), container(), submenu::video_options(), m_sys.driver, &m_opts); break; + case CONTROLLER: + if (ev->iptkey == IPT_UI_SELECT) + menu::stack_push(ui(), container(), submenu::control_options(), m_sys.driver, &m_opts); + break; case ADVANCED: if (ev->iptkey == IPT_UI_SELECT) menu::stack_push(ui(), container(), submenu::advanced_options(), m_sys.driver, &m_opts); @@ -794,10 +809,10 @@ void menu_machine_configure::populate(float &customtop, float &custombottom) if (!m_bios.empty()) { uint32_t arrows = get_arrow_flags(std::size_t(0), m_bios.size() - 1, m_curbios); - item_append(_("Driver"), m_bios[m_curbios].first, arrows, (void *)(uintptr_t)BIOS); + item_append(_("System"), m_bios[m_curbios].first, arrows, (void *)(uintptr_t)BIOS); } else - item_append(_("This machine has no BIOS."), FLAG_DISABLE, nullptr); + item_append(_("[this system has no BIOS settings]"), FLAG_DISABLE, nullptr); item_append(menu_item_type::SEPARATOR); item_append(_(submenu::advanced_options()[0].description), 0, (void *)(uintptr_t)ADVANCED); @@ -811,25 +826,13 @@ void menu_machine_configure::populate(float &customtop, float &custombottom) item_append(_("Remove From Favorites"), 0, (void *)DELFAV); item_append(menu_item_type::SEPARATOR); - item_append(_("Save Machine Configuration"), 0, (void *)(uintptr_t)SAVE); - - customtop = 2.0f * ui().get_line_height() + 3.0f * ui().box_tb_border(); + item_append(_("Save System Settings"), 0, (void *)(uintptr_t)SAVE); } //------------------------------------------------- // perform our special rendering //------------------------------------------------- -void menu_machine_configure::custom_render(void *selectedref, float top, float bottom, float origx1, float origy1, float origx2, float origy2) -{ - char const *const text[] = { _("Configure Machine:"), m_sys.description.c_str() }; - draw_text_box( - std::begin(text), std::end(text), - origx1, origx2, origy1 - top, origy1 - ui().box_tb_border(), - text_layout::text_justify::CENTER, text_layout::word_wrapping::TRUNCATE, false, - ui().colors().text_color(), UI_GREEN_COLOR, 1.0f); -} - void menu_machine_configure::setup_bios() { if (!m_sys.driver->rom) @@ -850,7 +853,7 @@ void menu_machine_configure::setup_bios() u32 const bios_flags(bios.get_value()); std::string const bios_number(std::to_string(bios_flags - 1)); - // check biosnumber and name + // check BIOS number and name if ((bios_number == specbios) || (specbios == bios.get_name())) m_curbios = bios_count; @@ -873,6 +876,7 @@ void menu_machine_configure::setup_bios() menu_plugins_configure::menu_plugins_configure(mame_ui_manager &mui, render_container &container) : menu(mui, container) { + set_heading(_("Plugins")); } menu_plugins_configure::~menu_plugins_configure() @@ -932,23 +936,8 @@ void menu_plugins_configure::populate(float &customtop, float &custombottom) } } if (first) - item_append(_("No plugins found"), 0, nullptr); + item_append(_("No plugins found"), FLAG_DISABLE, nullptr); item_append(menu_item_type::SEPARATOR); - customtop = ui().get_line_height() + (3.0f * ui().box_tb_border()); -} - -//------------------------------------------------- -// perform our special rendering -//------------------------------------------------- - -void menu_plugins_configure::custom_render(void *selectedref, float top, float bottom, float origx1, float origy1, float origx2, float origy2) -{ - char const *const toptext[] = { _("Plugins") }; - draw_text_box( - std::begin(toptext), std::end(toptext), - origx1, origx2, origy1 - top, origy1 - ui().box_tb_border(), - text_layout::text_justify::CENTER, text_layout::word_wrapping::TRUNCATE, false, - ui().colors().text_color(), UI_GREEN_COLOR, 1.0f); } } // namespace ui diff --git a/src/frontend/mame/ui/miscmenu.h b/src/frontend/mame/ui/miscmenu.h index b17e6713597..22a2d1dc135 100644 --- a/src/frontend/mame/ui/miscmenu.h +++ b/src/frontend/mame/ui/miscmenu.h @@ -133,9 +133,6 @@ public: std::function &&handler = nullptr); virtual ~menu_machine_configure(); -protected: - virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override; - private: using s_bios = std::vector>; @@ -144,8 +141,8 @@ private: ADDFAV = 1, DELFAV, SAVE, - CONTROLLER, VIDEO, + CONTROLLER, BIOS, ADVANCED, LAST = ADVANCED @@ -179,8 +176,6 @@ public: protected: virtual void populate(float &customtop, float &custombottom) override; virtual void handle(event const *ev) override; - - virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override; }; } // namespace ui diff --git a/src/frontend/mame/ui/optsmenu.cpp b/src/frontend/mame/ui/optsmenu.cpp index bafbe9d2af0..225e2ef3af4 100644 --- a/src/frontend/mame/ui/optsmenu.cpp +++ b/src/frontend/mame/ui/optsmenu.cpp @@ -13,6 +13,7 @@ #include "ui/custui.h" #include "ui/dirmenu.h" +#include "ui/inputdevices.h" #include "ui/inputmap.h" #include "ui/miscmenu.h" #include "ui/selector.h" @@ -41,6 +42,7 @@ menu_simple_game_options::menu_simple_game_options( , m_handler(std::move(handler)) { set_process_flags(PROCESS_LR_REPEAT); + set_heading(_("General Settings")); } //------------------------------------------------- @@ -75,15 +77,16 @@ void menu_simple_game_options::populate(float &customtop, float &custombottom) item_append(_("Sound Options"), 0, (void *)(uintptr_t)SOUND_MENU); item_append(_(submenu::misc_options()[0].description), 0, (void *)(uintptr_t)MISC_MENU); item_append(_(submenu::control_options()[0].description), 0, (void *)(uintptr_t)CONTROLLER_MENU); - item_append(_("General Inputs"), 0, (void *)(uintptr_t)CGI_MENU); + item_append(_("Input Assignments"), 0, (void *)(uintptr_t)INPUTASSIGN_MENU); item_append(_(submenu::advanced_options()[0].description), 0, (void *)(uintptr_t)ADVANCED_MENU); if (machine().options().plugins()) item_append(_("Plugins"), 0, (void *)(uintptr_t)PLUGINS_MENU); item_append(menu_item_type::SEPARATOR); - item_append(_("Save Configuration"), 0, (void *)(uintptr_t)SAVE_CONFIG); + item_append(_("Input Devices"), 0, (void *)(uintptr_t)INPUTDEV_MENU); + item_append(menu_item_type::SEPARATOR); + item_append(_("Save Settings"), 0, (void *)(uintptr_t)SAVE_CONFIG); custombottom = 2.0f * ui().get_line_height() + 3.0f * ui().box_tb_border(); - customtop = ui().get_line_height() + 3.0f * ui().box_tb_border(); } //------------------------------------------------- @@ -92,69 +95,45 @@ void menu_simple_game_options::populate(float &customtop, float &custombottom) void menu_simple_game_options::handle_item_event(event const &menu_event) { - switch ((uintptr_t)menu_event.itemref) + if (IPT_UI_SELECT == menu_event.iptkey) { - case MISC_MENU: - if (menu_event.iptkey == IPT_UI_SELECT) + switch ((uintptr_t)menu_event.itemref) { + case MISC_MENU: menu::stack_push(ui(), container(), submenu::misc_options()); ui_globals::reset = true; - } - break; - case SOUND_MENU: - if (menu_event.iptkey == IPT_UI_SELECT) - { + break; + case SOUND_MENU: menu::stack_push(ui(), container()); ui_globals::reset = true; - } - break; - case DISPLAY_MENU: - if (menu_event.iptkey == IPT_UI_SELECT) - { + break; + case DISPLAY_MENU: menu::stack_push(ui(), container(), submenu::video_options()); ui_globals::reset = true; - } - break; - case CONTROLLER_MENU: - if (menu_event.iptkey == IPT_UI_SELECT) + break; + case CONTROLLER_MENU: menu::stack_push(ui(), container(), submenu::control_options()); - break; - case CGI_MENU: - if (menu_event.iptkey == IPT_UI_SELECT) + break; + case INPUTASSIGN_MENU: menu::stack_push(ui(), container()); - break; - case ADVANCED_MENU: - if (menu_event.iptkey == IPT_UI_SELECT) - { + break; + case ADVANCED_MENU: menu::stack_push(ui(), container(), submenu::advanced_options()); ui_globals::reset = true; - } - break; - case PLUGINS_MENU: - if (menu_event.iptkey == IPT_UI_SELECT) + break; + case PLUGINS_MENU: menu::stack_push(ui(), container()); - break; - case SAVE_CONFIG: - if (menu_event.iptkey == IPT_UI_SELECT) + break; + case INPUTDEV_MENU: + menu::stack_push(ui(), container()); + break; + case SAVE_CONFIG: ui().save_main_option(); - break; + break; + } } } -//------------------------------------------------- -// perform our special rendering -//------------------------------------------------- - -void menu_simple_game_options::custom_render(void *selectedref, float top, float bottom, float origx1, float origy1, float origx2, float origy2) -{ - char const *const toptext[] = { _("Settings") }; - draw_text_box( - std::begin(toptext), std::end(toptext), - origx1, origx2, origy1 - top, origy1 - ui().box_tb_border(), - text_layout::text_justify::CENTER, text_layout::word_wrapping::TRUNCATE, false, - ui().colors().text_color(), UI_GREEN_COLOR, 1.0f); -} - //------------------------------------------------- // ctor @@ -169,7 +148,6 @@ menu_game_options::menu_game_options( , m_filter_data(filter_data) , m_main_filter(filter_data.get_current_filter_type()) { - set_process_flags(PROCESS_LR_REPEAT); } //------------------------------------------------- @@ -204,7 +182,7 @@ void menu_game_options::populate(float &customtop, float &custombottom) // add filter item uint32_t arrow_flags = get_arrow_flags(machine_filter::FIRST, machine_filter::LAST, m_main_filter); machine_filter &active_filter(m_filter_data.get_filter(m_main_filter)); - item_append(_("Filter"), active_filter.display_name(), arrow_flags, (void *)(uintptr_t)FILTER_MENU); + item_append(_("System Filter"), active_filter.display_name(), arrow_flags, (void *)(uintptr_t)FILTER_MENU); // add subitem if the filter wants it if (active_filter.wants_adjuster()) @@ -217,7 +195,7 @@ void menu_game_options::populate(float &customtop, float &custombottom) // add options items item_append(_("Customize UI"), 0, (void *)(uintptr_t)CUSTOM_MENU); - item_append(_("Configure Directories"), 0, (void *)(uintptr_t)CONF_DIR); + item_append(_("Configure Folders"), 0, (void *)(uintptr_t)CONF_DIR); // add the options that don't relate to the UI menu_simple_game_options::populate(customtop, custombottom); @@ -246,7 +224,7 @@ void menu_game_options::handle_item_event(event const &menu_event) s_sel[index] = machine_filter::display_name(machine_filter::type(index)); menu::stack_push( - ui(), container(), std::move(s_sel), m_main_filter, + ui(), container(), _("System Filter"), std::move(s_sel), m_main_filter, [this] (int selection) { m_main_filter = machine_filter::type(selection); diff --git a/src/frontend/mame/ui/optsmenu.h b/src/frontend/mame/ui/optsmenu.h index 297ec7aa64f..b10d6601926 100644 --- a/src/frontend/mame/ui/optsmenu.h +++ b/src/frontend/mame/ui/optsmenu.h @@ -28,7 +28,6 @@ public: virtual ~menu_simple_game_options() override; protected: - virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override; virtual void handle(event const *ev) override; virtual void populate(float &customtop, float &custombottom) override; @@ -41,9 +40,10 @@ private: SOUND_MENU, MISC_MENU, CONTROLLER_MENU, - CGI_MENU, + INPUTASSIGN_MENU, ADVANCED_MENU, PLUGINS_MENU, + INPUTDEV_MENU, SAVE_CONFIG }; diff --git a/src/frontend/mame/ui/pluginopt.cpp b/src/frontend/mame/ui/pluginopt.cpp index 6f6a980d871..08f7f84a752 100644 --- a/src/frontend/mame/ui/pluginopt.cpp +++ b/src/frontend/mame/ui/pluginopt.cpp @@ -32,6 +32,7 @@ menu_plugin::menu_plugin(mame_ui_manager &mui, render_container &container) : menu(mui, container), m_plugins(mame_machine_manager::instance()->lua()->get_menu()) { + set_heading(_("Plugin Options")); } void menu_plugin::populate(float &customtop, float &custombottom) diff --git a/src/frontend/mame/ui/selector.cpp b/src/frontend/mame/ui/selector.cpp index 6a583346400..f8791a37887 100644 --- a/src/frontend/mame/ui/selector.cpp +++ b/src/frontend/mame/ui/selector.cpp @@ -27,10 +27,12 @@ namespace ui { menu_selector::menu_selector( mame_ui_manager &mui, render_container &container, + std::string &&title, std::vector &&sel, int initial, std::function &&handler) : menu(mui, container) + , m_title(std::move(title)) , m_search() , m_str_items(std::move(sel)) , m_handler(std::move(handler)) @@ -50,30 +52,36 @@ menu_selector::~menu_selector() void menu_selector::handle(event const *ev) { // process the menu - if (ev && ev->itemref) + if (ev) { - if (ev->iptkey == IPT_UI_SELECT) + switch (ev->iptkey) { - int selection(-1); - for (size_t idx = 0; (m_str_items.size() > idx) && (0 > selection); ++idx) - if ((void*)&m_str_items[idx] == ev->itemref) - selection = int(unsigned(idx)); + case IPT_UI_SELECT: + if (ev->itemref) + { + int selection(-1); + for (size_t idx = 0; (m_str_items.size() > idx) && (0 > selection); ++idx) + if ((void*)&m_str_items[idx] == ev->itemref) + selection = int(unsigned(idx)); - m_handler(selection); + m_handler(selection); + stack_pop(); + } + break; - stack_pop(); - } - else if (ev->iptkey == IPT_SPECIAL) - { + case IPT_SPECIAL: if (input_character(m_search, ev->unichar, uchar_is_printable)) reset(reset_options::SELECT_FIRST); - } + break; - // escape pressed with non-empty text clears the text - else if (ev->iptkey == IPT_UI_CANCEL && !m_search.empty()) - { - m_search.clear(); - reset(reset_options::SELECT_FIRST); + case IPT_UI_CANCEL: + if (!m_search.empty()) + { + // escape pressed with non-empty search text clears the search text + m_search.clear(); + reset(reset_options::SELECT_FIRST); + } + break; } } } @@ -84,12 +92,17 @@ void menu_selector::handle(event const *ev) void menu_selector::populate(float &customtop, float &custombottom) { + set_heading(util::string_format(_("menu-selector", "%1$s - Search: %2$s_"), m_title, m_search)); + if (!m_search.empty()) { find_matches(m_search.c_str()); - for (int curitem = 0; m_searchlist[curitem]; ++curitem) + int curitem; + for (curitem = 0; m_searchlist[curitem]; ++curitem) item_append(*m_searchlist[curitem], 0, (void *)m_searchlist[curitem]); + if (!curitem) + item_append(_("menu-selector", "[no matches]"), FLAG_DISABLE, nullptr); } else { @@ -100,10 +113,13 @@ void menu_selector::populate(float &customtop, float &custombottom) item_append(m_str_items[index], 0, (void *)&m_str_items[index]); } + + if (m_str_items.empty()) + item_append(_("menu-selector", "[no choices]"), FLAG_DISABLE, nullptr); // the caller was probably being dumb } item_append(menu_item_type::SEPARATOR); - customtop = custombottom = ui().get_line_height() + 3.0f * ui().box_tb_border(); + custombottom = ui().get_line_height() + 3.0f * ui().box_tb_border(); m_initial = -1; } @@ -113,15 +129,8 @@ void menu_selector::populate(float &customtop, float &custombottom) void menu_selector::custom_render(void *selectedref, float top, float bottom, float origx1, float origy1, float origx2, float origy2) { - std::string tempbuf[1] = { std::string(_("Selection List - Search: ")).append(m_search).append("_") }; - draw_text_box( - std::begin(tempbuf), std::end(tempbuf), - origx1, origx2, origy1 - top, origy1 - ui().box_tb_border(), - text_layout::text_justify::CENTER, text_layout::word_wrapping::TRUNCATE, false, - ui().colors().text_color(), UI_GREEN_COLOR, 1.0f); - // get the text for 'UI Select' - tempbuf[0] = string_format(_("Double-click or press %1$s to select"), ui().get_general_input_setting(IPT_UI_SELECT)); + std::string const tempbuf[] = { util::string_format(_("menu-selector", "Double-click or press %1$s to select"), ui().get_general_input_setting(IPT_UI_SELECT)) }; draw_text_box( std::begin(tempbuf), std::end(tempbuf), origx1, origx2, origy2 + ui().box_tb_border(), origy2 + bottom, @@ -137,7 +146,7 @@ void menu_selector::find_matches(const char *str) { // allocate memory to track the penalty value m_ucs_items.reserve(m_str_items.size()); - std::vector penalty(VISIBLE_GAMES_IN_SEARCH, 1.0); + std::vector penalty(VISIBLE_SEARCH_ITEMS, 2.0); // impossibly high penalty for unpopulated slots std::u32string const search(ustr_from_utf8(normalize_unicode(str, unicode_normalization_form::D, true))); int index = 0; @@ -149,14 +158,14 @@ void menu_selector::find_matches(const char *str) double const curpenalty(util::edit_distance(search, m_ucs_items[index])); // insert into the sorted table of matches - for (int matchnum = VISIBLE_GAMES_IN_SEARCH - 1; matchnum >= 0; --matchnum) + for (int matchnum = VISIBLE_SEARCH_ITEMS - 1; matchnum >= 0; --matchnum) { // stop if we're worse than the current entry if (curpenalty >= penalty[matchnum]) break; // as long as this isn't the last entry, bump this one down - if (matchnum < VISIBLE_GAMES_IN_SEARCH - 1) + if (matchnum < VISIBLE_SEARCH_ITEMS - 1) { penalty[matchnum + 1] = penalty[matchnum]; m_searchlist[matchnum + 1] = m_searchlist[matchnum]; @@ -166,7 +175,7 @@ void menu_selector::find_matches(const char *str) penalty[matchnum] = curpenalty; } } - (index < VISIBLE_GAMES_IN_SEARCH) ? m_searchlist[index] = nullptr : m_searchlist[VISIBLE_GAMES_IN_SEARCH] = nullptr; + (index < VISIBLE_SEARCH_ITEMS) ? m_searchlist[index] = nullptr : m_searchlist[VISIBLE_SEARCH_ITEMS] = nullptr; } } // namespace ui diff --git a/src/frontend/mame/ui/selector.h b/src/frontend/mame/ui/selector.h index d8b0abc0472..17fdb972343 100644 --- a/src/frontend/mame/ui/selector.h +++ b/src/frontend/mame/ui/selector.h @@ -12,9 +12,12 @@ #pragma once - #include "ui/menu.h" +#include +#include +#include + namespace ui { @@ -28,6 +31,7 @@ public: menu_selector( mame_ui_manager &mui, render_container &container, + std::string &&title, std::vector &&sel, int initial, std::function &&handler); @@ -38,21 +42,22 @@ protected: virtual bool custom_ui_cancel() override { return !m_search.empty(); } private: - enum { VISIBLE_GAMES_IN_SEARCH = 200 }; + enum { VISIBLE_SEARCH_ITEMS = 200 }; virtual void populate(float &customtop, float &custombottom) override; virtual void handle(event const *ev) override; void find_matches(const char *str); + std::string const m_title; std::string m_search; std::vector m_str_items; std::function m_handler; std::vector m_ucs_items; int m_initial; - std::string *m_searchlist[VISIBLE_GAMES_IN_SEARCH + 1]; + std::string *m_searchlist[VISIBLE_SEARCH_ITEMS + 1]; }; } // namespace ui -#endif /* MAME_FRONTEND_UI_SELECTOR_H */ +#endif // MAME_FRONTEND_UI_SELECTOR_H diff --git a/src/frontend/mame/ui/selgame.cpp b/src/frontend/mame/ui/selgame.cpp index abda7047971..cfb41d2c3b9 100644 --- a/src/frontend/mame/ui/selgame.cpp +++ b/src/frontend/mame/ui/selgame.cpp @@ -438,8 +438,8 @@ void menu_select_game::populate(float &customtop, float &custombottom) if (stack_has_special_main_menu()) { item_append(menu_item_type::SEPARATOR, 0); - item_append(_("Configure Options"), 0, (void *)(uintptr_t)CONF_OPTS); - item_append(_("Configure Machine"), 0, (void *)(uintptr_t)CONF_MACHINE); + item_append(_("General Settings"), 0, (void *)(uintptr_t)CONF_OPTS); + item_append(_("System Settings"), 0, (void *)(uintptr_t)CONF_MACHINE); skip_main_items = 3; if (m_prev_selected && !have_prev_selected) @@ -1055,7 +1055,7 @@ void menu_select_game::get_selection(ui_software_info const *&software, ui_syste void menu_select_game::make_topbox_text(std::string &line0, std::string &line1, std::string &line2) const { - line0 = string_format(_("%1$s %2$s ( %3$d / %4$d machines (%5$d BIOS) )"), + line0 = string_format(_("%1$s %2$s ( %3$d / %4$d systems (%5$d BIOS) )"), emulator_info::get_appname(), bare_build_version, m_available_items, diff --git a/src/frontend/mame/ui/selmenu.cpp b/src/frontend/mame/ui/selmenu.cpp index 85efff4b8cd..bc43ee4b4b8 100644 --- a/src/frontend/mame/ui/selmenu.cpp +++ b/src/frontend/mame/ui/selmenu.cpp @@ -167,9 +167,6 @@ public: software_parts(mame_ui_manager &mui, render_container &container, s_parts &&parts, ui_software_info const &ui_info); virtual ~software_parts() override; -protected: - virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override; - private: virtual void populate(float &customtop, float &custombottom) override; virtual void handle(event const *ev) override; @@ -185,9 +182,6 @@ public: bios_selection(mame_ui_manager &mui, render_container &container, s_bios &&biosname, ui_software_info const &swinfo, bool inlist); virtual ~bios_selection() override; -protected: - virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override; - private: bios_selection(mame_ui_manager &mui, render_container &container, s_bios &&biosname, void const *driver, bool software, bool inlist); @@ -263,6 +257,7 @@ menu_select_launch::software_parts::software_parts(mame_ui_manager &mui, render_ , m_uiinfo(ui_info) , m_parts(std::move(parts)) { + set_heading(_("Select Software Package Part")); } //------------------------------------------------- @@ -288,7 +283,6 @@ void menu_select_launch::software_parts::populate(float &customtop, float &custo item_append(elem->first, elem->second, 0, (void *)&*elem); item_append(menu_item_type::SEPARATOR); - customtop = ui().get_line_height() + (3.0f * ui().box_tb_border()); } //------------------------------------------------- @@ -311,20 +305,6 @@ void menu_select_launch::software_parts::handle(event const *ev) } } -//------------------------------------------------- -// perform our special rendering -//------------------------------------------------- - -void menu_select_launch::software_parts::custom_render(void *selectedref, float top, float bottom, float origx1, float origy1, float origx2, float origy2) -{ - char const *const text[] = { _("Software part selection:") }; - draw_text_box( - std::begin(text), std::end(text), - origx1, origx2, origy1 - top, origy1 - ui().box_tb_border(), - text_layout::text_justify::CENTER, text_layout::word_wrapping::TRUNCATE, false, - ui().colors().text_color(), UI_GREEN_COLOR, 1.0f); -} - //------------------------------------------------- // ctor @@ -347,6 +327,7 @@ menu_select_launch::bios_selection::bios_selection(mame_ui_manager &mui, render_ , m_inlist(inlist) , m_bios(std::move(biosname)) { + set_heading(_("Select System BIOS")); } //------------------------------------------------- @@ -363,11 +344,10 @@ menu_select_launch::bios_selection::~bios_selection() void menu_select_launch::bios_selection::populate(float &customtop, float &custombottom) { - for (auto & elem : m_bios) + for (auto &elem : m_bios) item_append(elem.first, 0, (void *)&elem.first); item_append(menu_item_type::SEPARATOR); - customtop = ui().get_line_height() + (3.0f * ui().box_tb_border()); } //------------------------------------------------- @@ -416,20 +396,6 @@ void menu_select_launch::bios_selection::handle(event const *ev) } } -//------------------------------------------------- -// perform our special rendering -//------------------------------------------------- - -void menu_select_launch::bios_selection::custom_render(void *selectedref, float top, float bottom, float origx1, float origy1, float origx2, float origy2) -{ - char const *const text[] = { _("BIOS selection:") }; - draw_text_box( - std::begin(text), std::end(text), - origx1, origx2, origy1 - top, origy1 - ui().box_tb_border(), - text_layout::text_justify::CENTER, text_layout::word_wrapping::TRUNCATE, false, - ui().colors().text_color(), UI_GREEN_COLOR, 1.0f); -} - menu_select_launch::cache::cache(running_machine &machine) : m_snapx_bitmap(std::make_unique(0, 0)) @@ -712,11 +678,11 @@ void menu_select_launch::custom_render(void *selectedref, float top, float botto int cloneof = driver_list::non_bios_clone(driver); if (0 > cloneof) - tempbuf[1] = _("Driver is parent"); + tempbuf[1] = _("System is parent"); else if (system) - tempbuf[1] = string_format(_("Driver is clone of: %1$s"), system->parent); + tempbuf[1] = string_format(_("System is clone of: %1$s"), system->parent); else - tempbuf[1] = string_format(_("Driver is clone of: %1$s"), driver_list::driver(cloneof).type.fullname()); + tempbuf[1] = string_format(_("System is clone of: %1$s"), driver_list::driver(cloneof).type.fullname()); // next line is overall driver status system_flags const &flags(get_system_flags(driver)); @@ -869,9 +835,10 @@ void menu_select_launch::inkey_dats() void menu_select_launch::draw_common_arrow(float origx1, float origy1, float origx2, float origy2, int current, int dmin, int dmax, float title_size) { - auto line_height = ui().get_line_height(); - auto lr_arrow_width = 0.4f * line_height * machine().render().ui_aspect(&container()); - auto gutter_width = lr_arrow_width * 1.3f; + float const aspect = machine().render().ui_aspect(&container()); + float const line_height = ui().get_line_height(); + float const lr_arrow_width = 0.4f * line_height * aspect; + float const gutter_width = 0.5f * line_height * aspect; // set left-right arrows dimension float const ar_x0 = 0.5f * (origx2 + origx1) + 0.5f * title_size + gutter_width - lr_arrow_width; @@ -2894,7 +2861,7 @@ void menu_select_launch::general_info(ui_system_info const *system, game_driver str << driver.type.fullname(); str << "\t\n\n"; - util::stream_format(str, _("Romset\t%1$s\n"), driver.name); + util::stream_format(str, _("Short Name\t%1$s\n"), driver.name); util::stream_format(str, _("Year\t%1$s\n"), driver.year); util::stream_format(str, _("Manufacturer\t%1$s\n"), driver.manufacturer); @@ -2903,12 +2870,12 @@ void menu_select_launch::general_info(ui_system_info const *system, game_driver { util::stream_format( str, - _("Driver is Clone of\t%1$s\n"), + _("System is Clone of\t%1$s\n"), system ? std::string_view(system->parent) : std::string_view(driver_list::driver(cloneof).type.fullname())); } else { - str << _("Driver is Parent\t\n"); + str << _("System is Parent\t\n"); } if (flags.has_analog()) @@ -3028,12 +2995,12 @@ void menu_select_launch::general_info(ui_system_info const *system, game_driver else if (flags.imperfect_features() & device_t::feature::TIMING) str << _("Timing\tImperfect\n"); - str << ((flags.machine_flags() & machine_flags::MECHANICAL) ? _("Mechanical Machine\tYes\n") : _("Mechanical Machine\tNo\n")); + str << ((flags.machine_flags() & machine_flags::MECHANICAL) ? _("Mechanical System\tYes\n") : _("Mechanical System\tNo\n")); str << ((flags.machine_flags() & machine_flags::REQUIRES_ARTWORK) ? _("Requires Artwork\tYes\n") : _("Requires Artwork\tNo\n")); str << ((flags.machine_flags() & machine_flags::CLICKABLE_ARTWORK) ? _("Requires Clickable Artwork\tYes\n") : _("Requires Clickable Artwork\tNo\n")); if (flags.machine_flags() & machine_flags::NO_COCKTAIL) str << _("Support Cocktail\tNo\n"); - str << ((flags.machine_flags() & machine_flags::IS_BIOS_ROOT) ? _("Driver is BIOS\tYes\n") : _("Driver is BIOS\tNo\n")); + str << ((flags.machine_flags() & machine_flags::IS_BIOS_ROOT) ? _("System is BIOS\tYes\n") : _("System is BIOS\tNo\n")); str << ((flags.machine_flags() & machine_flags::SUPPORTS_SAVE) ? _("Support Save\tYes\n") : _("Support Save\tNo\n")); str << ((flags.machine_flags() & ORIENTATION_SWAP_XY) ? _("Screen Orientation\tVertical\n") : _("Screen Orientation\tHorizontal\n")); bool found = false; diff --git a/src/frontend/mame/ui/selsoft.cpp b/src/frontend/mame/ui/selsoft.cpp index dc3904f2169..da4ad722f2f 100644 --- a/src/frontend/mame/ui/selsoft.cpp +++ b/src/frontend/mame/ui/selsoft.cpp @@ -704,7 +704,7 @@ void menu_select_software::make_topbox_text(std::string &line0, std::string &lin // determine the text for the header int vis_item = !m_search.empty() ? m_available_items : (m_available_items - 1); line0 = string_format(_("%1$s %2$s ( %3$d / %4$d software packages )"), emulator_info::get_appname(), bare_build_version, vis_item, m_data->swinfo().size() - 1); - line1 = string_format(_("Driver: \"%1$s\" software list "), m_system.description); + line1 = string_format(_("System: \"%1$s\" software list "), m_system.description); software_filter const *const it(m_data->current_filter()); char const *const filter(it ? it->filter_text() : nullptr); diff --git a/src/frontend/mame/ui/simpleselgame.cpp b/src/frontend/mame/ui/simpleselgame.cpp index 3a230e88a89..7febc58e867 100644 --- a/src/frontend/mame/ui/simpleselgame.cpp +++ b/src/frontend/mame/ui/simpleselgame.cpp @@ -297,9 +297,9 @@ void simple_menu_select_game::custom_render(void *selectedref, float top, float ui().draw_text_box( container(), string_format( - _("No machines found. Please check the rompath specified in the %1$s.ini file.\n\n" - "If this is your first time using %2$s, please see the config.txt file in " - "the docs directory for information on configuring %2$s."), + _("No system ROMs found. Please check the rompath setting specified in the %1$s.ini file.\n\n" + "If this is your first time using %2$s, please see the %2$s.pdf file in " + "the docs folder for information on setting up and using %2$s."), emulator_info::get_configname(), emulator_info::get_appname()), text_layout::text_justify::CENTER, diff --git a/src/frontend/mame/ui/sliders.cpp b/src/frontend/mame/ui/sliders.cpp index 404e174f803..f4b5017397a 100644 --- a/src/frontend/mame/ui/sliders.cpp +++ b/src/frontend/mame/ui/sliders.cpp @@ -27,6 +27,7 @@ menu_sliders::menu_sliders(mame_ui_manager &mui, render_container &container, bo set_one_shot(menuless_mode); set_needs_prev_menu_item(!menuless_mode); set_process_flags(PROCESS_LR_REPEAT | (m_hidden ? PROCESS_CUSTOM_ONLY : 0)); + set_heading(_("Slider Controls")); } menu_sliders::~menu_sliders() diff --git a/src/frontend/mame/ui/slotopt.cpp b/src/frontend/mame/ui/slotopt.cpp index e27e6261c63..985b0fe5eb4 100644 --- a/src/frontend/mame/ui/slotopt.cpp +++ b/src/frontend/mame/ui/slotopt.cpp @@ -45,6 +45,7 @@ namespace ui { menu_slot_devices::menu_slot_devices(mame_ui_manager &mui, render_container &container) : menu(mui, container) { + set_heading(_("Slot Devices")); } //------------------------------------------------- @@ -200,7 +201,7 @@ void menu_slot_devices::populate(float &customtop, float &custombottom) item_append(slot.slot_name(), opt_name, item_flags, (void *)&slot); } item_append(menu_item_type::SEPARATOR); - item_append(_("Reset Machine"), 0, ITEMREF_RESET); + item_append(_("Reset System"), 0, ITEMREF_RESET); // leave space for the name of the current option at the bottom custombottom = ui().get_line_height() + 3.0f * ui().box_tb_border(); diff --git a/src/frontend/mame/ui/sndmenu.cpp b/src/frontend/mame/ui/sndmenu.cpp index 1ee1e82e25c..136cbcf98f4 100644 --- a/src/frontend/mame/ui/sndmenu.cpp +++ b/src/frontend/mame/ui/sndmenu.cpp @@ -27,6 +27,8 @@ const int menu_sound_options::m_sound_rate[] = { 11025, 22050, 44100, 48000 }; menu_sound_options::menu_sound_options(mame_ui_manager &mui, render_container &container) : menu(mui, container) { + set_heading(_("Sound Options")); + osd_options &options = downcast(mui.machine().options()); m_sample_rate = mui.machine().options().sample_rate(); @@ -109,7 +111,7 @@ void menu_sound_options::handle(event const *ev) s_sel[index] = std::to_string(m_sound_rate[index]); menu::stack_push( - ui(), container(), std::move(s_sel), m_cur_rates, + ui(), container(), _("Sample Rate"), std::move(s_sel), m_cur_rates, [this] (int selection) { m_cur_rates = selection; @@ -148,22 +150,6 @@ void menu_sound_options::populate(float &customtop, float &custombottom) item_append(_("Sample Rate"), string_format("%d", m_sample_rate), arrow_flags, (void *)(uintptr_t)SAMPLE_RATE); item_append_on_off(_("Use External Samples"), m_samples, 0, (void *)(uintptr_t)ENABLE_SAMPLES); item_append(menu_item_type::SEPARATOR); - - customtop = ui().get_line_height() + (3.0f * ui().box_tb_border()); -} - -//------------------------------------------------- -// perform our special rendering -//------------------------------------------------- - -void menu_sound_options::custom_render(void *selectedref, float top, float bottom, float origx1, float origy1, float origx2, float origy2) -{ - char const *const toptext[] = { _("Sound Options") }; - draw_text_box( - std::begin(toptext), std::end(toptext), - origx1, origx2, origy1 - top, origy1 - ui().box_tb_border(), - text_layout::text_justify::CENTER, text_layout::word_wrapping::TRUNCATE, false, - ui().colors().text_color(), UI_GREEN_COLOR, 1.0f); } } // namespace ui diff --git a/src/frontend/mame/ui/sndmenu.h b/src/frontend/mame/ui/sndmenu.h index 03f68202748..48d85b7d1a5 100644 --- a/src/frontend/mame/ui/sndmenu.h +++ b/src/frontend/mame/ui/sndmenu.h @@ -27,7 +27,6 @@ public: menu_sound_options(mame_ui_manager &mui, render_container &container); protected: - virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override; virtual void menu_dismissed() override; private: diff --git a/src/frontend/mame/ui/state.cpp b/src/frontend/mame/ui/state.cpp index 4bda4d473ba..9f4e6a40ab2 100644 --- a/src/frontend/mame/ui/state.cpp +++ b/src/frontend/mame/ui/state.cpp @@ -91,7 +91,6 @@ menu_load_save_state_base::menu_load_save_state_base( bool one_shot) : autopause_menu<>(mui, container) , m_switch_poller(machine().input()) - , m_header(header) , m_footer(footer) , m_confirm_delete(nullptr) , m_must_exist(must_exist) @@ -99,6 +98,7 @@ menu_load_save_state_base::menu_load_save_state_base( { set_one_shot(one_shot); set_needs_prev_menu_item(!one_shot); + set_heading(header); } @@ -222,7 +222,6 @@ void menu_load_save_state_base::populate(float &customtop, float &custombottom) item_append(_("Cancel"), 0, nullptr); // set up custom render proc - customtop = ui().get_line_height() + (3.0f * ui().box_tb_border()); custombottom = (2.0f * ui().get_line_height()) + (3.0f * ui().box_tb_border()); // get ready to poll inputs @@ -405,13 +404,6 @@ void menu_load_save_state_base::handle_keys(uint32_t flags, int &iptkey) void menu_load_save_state_base::custom_render(void *selectedref, float top, float bottom, float origx1, float origy1, float origx2, float origy2) { - // draw menu title - draw_text_box( - &m_header, &m_header + 1, - origx1, origx2, origy1 - top, origy1 - ui().box_tb_border(), - text_layout::text_justify::CENTER, text_layout::word_wrapping::TRUNCATE, false, - ui().colors().text_color(), UI_GREEN_COLOR, 1.0f); - std::string_view text[2]; unsigned count(0U); diff --git a/src/frontend/mame/ui/state.h b/src/frontend/mame/ui/state.h index af44b47ba5b..a4dc107b1fc 100644 --- a/src/frontend/mame/ui/state.h +++ b/src/frontend/mame/ui/state.h @@ -67,7 +67,6 @@ private: switch_code_poller m_switch_poller; std::unordered_map m_file_entries; std::unordered_map m_filename_to_code_map; - std::string_view const m_header; std::string_view const m_footer; std::string m_delete_prompt; std::string m_confirm_prompt; diff --git a/src/frontend/mame/ui/submenu.cpp b/src/frontend/mame/ui/submenu.cpp index 895e643bf11..4e470251b7a 100644 --- a/src/frontend/mame/ui/submenu.cpp +++ b/src/frontend/mame/ui/submenu.cpp @@ -32,7 +32,7 @@ std::vector submenu::misc_options() return std::vector