diff options
-rw-r--r-- | scripts/src/emu.lua | 2 | ||||
-rw-r--r-- | src/emu/emuopts.cpp | 4 | ||||
-rw-r--r-- | src/emu/ui/menu.cpp | 37 | ||||
-rw-r--r-- | src/emu/ui/miscmenu.cpp | 121 | ||||
-rw-r--r-- | src/emu/ui/optsmenu.cpp | 10 | ||||
-rw-r--r-- | src/emu/ui/optsmenu.h | 3 | ||||
-rw-r--r-- | src/emu/ui/submenu.cpp | 304 | ||||
-rw-r--r-- | src/emu/ui/submenu.h | 129 | ||||
-rw-r--r-- | src/emu/ui/utils.cpp | 9 | ||||
-rw-r--r-- | src/emu/ui/utils.h | 1 | ||||
-rw-r--r-- | src/lib/util/options.h | 1 |
11 files changed, 484 insertions, 137 deletions
diff --git a/scripts/src/emu.lua b/scripts/src/emu.lua index b00be3e600d..44e98d0fafb 100644 --- a/scripts/src/emu.lua +++ b/scripts/src/emu.lua @@ -206,6 +206,8 @@ files { MAME_DIR .. "src/emu/ui/devctrl.h", MAME_DIR .. "src/emu/ui/menu.cpp", MAME_DIR .. "src/emu/ui/menu.h", + MAME_DIR .. "src/emu/ui/submenu.cpp", + MAME_DIR .. "src/emu/ui/submenu.h", MAME_DIR .. "src/emu/ui/mainmenu.cpp", MAME_DIR .. "src/emu/ui/mainmenu.h", MAME_DIR .. "src/emu/ui/miscmenu.cpp", diff --git a/src/emu/emuopts.cpp b/src/emu/emuopts.cpp index e05a16a5dd5..dfca2bde492 100644 --- a/src/emu/emuopts.cpp +++ b/src/emu/emuopts.cpp @@ -150,8 +150,8 @@ const options_entry emu_options::s_option_entries[] = { OPTION_UI_ACTIVE, "0", OPTION_BOOLEAN, "enable user interface on top of emulated keyboard (if present)" }, { OPTION_OFFSCREEN_RELOAD ";reload", "0", OPTION_BOOLEAN, "convert lightgun button 2 into offscreen reload" }, { OPTION_JOYSTICK_MAP ";joymap", "auto", OPTION_STRING, "explicit joystick map, or auto to auto-select" }, - { OPTION_JOYSTICK_DEADZONE ";joy_deadzone;jdz", "0.3", OPTION_FLOAT, "center deadzone range for joystick where change is ignored (0.0 center, 1.0 end)" }, - { OPTION_JOYSTICK_SATURATION ";joy_saturation;jsat", "0.85", OPTION_FLOAT, "end of axis saturation range for joystick where change is ignored (0.0 center, 1.0 end)" }, + { OPTION_JOYSTICK_DEADZONE ";joy_deadzone;jdz(0.00-1)", "0.3", OPTION_FLOAT, "center deadzone range for joystick where change is ignored (0.0 center, 1.0 end)" }, + { OPTION_JOYSTICK_SATURATION ";joy_saturation;jsat(0.00-1)", "0.85", OPTION_FLOAT, "end of axis saturation range for joystick where change is ignored (0.0 center, 1.0 end)" }, { OPTION_NATURAL_KEYBOARD ";nat", "0", OPTION_BOOLEAN, "specifies whether to use a natural keyboard or not" }, { OPTION_JOYSTICK_CONTRADICTORY ";joy_contradictory","0", OPTION_BOOLEAN, "enable contradictory direction digital joystick input at the same time" }, { OPTION_COIN_IMPULSE, "0", OPTION_INTEGER, "set coin impulse time (n<0 disable impulse, n==0 obey driver, 0<n set time n)" }, diff --git a/src/emu/ui/menu.cpp b/src/emu/ui/menu.cpp index 2af806fa586..3655ac76bc7 100644 --- a/src/emu/ui/menu.cpp +++ b/src/emu/ui/menu.cpp @@ -544,14 +544,25 @@ void ui_menu::draw(bool customonly, bool noimage, bool noinput) if (!customonly) machine().ui().draw_outlined_box(container, x1, y1, x2, y2, UI_BACKGROUND_COLOR); - // determine the first visible line based on the current selection - if (selected > top_line + visible_lines || selected < top_line - visible_lines) - top_line = selected - (visible_lines / 2); if (top_line < 0 || selected == 0) top_line = 0; - if (top_line + visible_lines >= item.size()) + if (top_line > item.size() - visible_lines || selected == (item.size() - 1)) top_line = item.size() - visible_lines; + bool show_top_arrow = false; + bool show_bottom_arrow = false; + + // if scrolling, show arrows + if (item.size() > visible_lines) { + if (top_line > 0) + show_top_arrow = true; + if (top_line != item.size() - visible_lines) + show_bottom_arrow = true; + } + + // set the number of visible lines, minus 1 for top arrow and 1 for bottom arrow + visitems = visible_lines - show_top_arrow - show_bottom_arrow; + // determine effective positions taking into account the hilighting arrows float effective_width = visible_width - 2.0f * gutter_width; float effective_left = visible_left + gutter_width; @@ -573,6 +584,7 @@ void ui_menu::draw(bool customonly, bool noimage, bool noinput) float line_x0 = x1 + 0.5f * UI_LINE_WIDTH; float line_x1 = x2 - 0.5f * UI_LINE_WIDTH; if (!customonly) + { for (linenum = 0; linenum < visible_lines; linenum++) { float line_y = visible_top + (float)linenum * line_height; @@ -613,7 +625,7 @@ void ui_menu::draw(bool customonly, bool noimage, bool noinput) highlight(container, line_x0, line_y0, line_x1, line_y1, bgcolor); // if we're on the top line, display the up arrow - if (linenum == 0 && top_line != 0) + if (linenum == 0 && show_top_arrow) { draw_arrow(container, 0.5f * (x1 + x2) - 0.5f * ud_arrow_width, @@ -627,7 +639,7 @@ void ui_menu::draw(bool customonly, bool noimage, bool noinput) } // if we're on the bottom line, display the down arrow - else if (linenum == visible_lines - 1 && itemnum != item.size() - 1) + else if (linenum == visible_lines - 1 && show_bottom_arrow) { draw_arrow(container, 0.5f * (x1 + x2) - 0.5f * ud_arrow_width, @@ -708,6 +720,7 @@ void ui_menu::draw(bool customonly, bool noimage, bool noinput) } } } + } // if the selected subitem is too big, display it in a separate offset box if (selected_subitem_too_big) @@ -741,9 +754,6 @@ void ui_menu::draw(bool customonly, bool noimage, bool noinput) // if there is something special to add, do it by calling the virtual method custom_render((selected >= 0 && selected < item.size()) ? item[selected].ref : nullptr, customtop, custombottom, x1, y1, x2, y2); - - // return the number of visible lines, minus 1 for top arrow and 1 for bottom arrow - visitems = visible_lines - (top_line != 0) - (top_line + visible_lines != item.size()); } void ui_menu::custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) @@ -989,7 +999,9 @@ void ui_menu::handle_keys(UINT32 flags) } (selected == 0) ? selected = top_line = item.size() - 1 : --selected; validate_selection(-1); - top_line -= (selected == top_line && top_line != 0); + top_line -= (selected <= top_line && top_line != 0); + if (selected <= top_line && visitems != visible_lines) + top_line--; } // down advances by one item @@ -1001,7 +1013,10 @@ void ui_menu::handle_keys(UINT32 flags) return; } (selected == item.size() - 1) ? selected = top_line = 0 : ++selected; - top_line += (selected == top_line + visitems + (top_line != 0)); + validate_selection(1); + top_line += (selected >= top_line + visitems + (top_line != 0)); + if (selected >= (top_line + visitems + (top_line != 0))) + top_line++; } // page up backs up by visitems diff --git a/src/emu/ui/miscmenu.cpp b/src/emu/ui/miscmenu.cpp index edca54ebd20..69f36b6cfda 100644 --- a/src/emu/ui/miscmenu.cpp +++ b/src/emu/ui/miscmenu.cpp @@ -552,127 +552,6 @@ void ui_menu_quit_game::handle() ui_menu::stack_reset(machine()); } -ui_menu_misc_options::misc_option ui_menu_misc_options::m_options[] = { - { 0, nullptr, nullptr }, - { 0, __("Re-select last machine played"), OPTION_REMEMBER_LAST }, - { 0, __("Enlarge images in the right panel"), OPTION_ENLARGE_SNAPS }, - { 0, __("DATs info"), OPTION_DATS_ENABLED }, - { 0, __("Cheats"), OPTION_CHEAT }, - { 0, __("Show mouse pointer"), OPTION_UI_MOUSE }, - { 0, __("Confirm quit from machines"), OPTION_CONFIRM_QUIT }, - { 0, __("Skip displaying information's screen at startup"), OPTION_SKIP_GAMEINFO }, - { 0, __("Force 4:3 appearance for software snapshot"), OPTION_FORCED4X3 }, - { 0, __("Use image as background"), OPTION_USE_BACKGROUND }, - { 0, __("Skip bios selection menu"), OPTION_SKIP_BIOS_MENU }, - { 0, __("Skip software parts selection menu"), OPTION_SKIP_PARTS_MENU } -}; - -//------------------------------------------------- -// ctor / dtor -//------------------------------------------------- - -ui_menu_misc_options::ui_menu_misc_options(running_machine &machine, render_container *container) : ui_menu(machine, container) -{ - for (int d = 1; d < ARRAY_LENGTH(m_options); ++d) - if (machine.ui().options().exists(m_options[d].option)) - m_options[d].status = machine.ui().options().bool_value(m_options[d].option); - else - m_options[d].status = machine.options().bool_value(m_options[d].option); -} - -ui_menu_misc_options::~ui_menu_misc_options() -{ - std::string error_string; - for (int d = 1; d < ARRAY_LENGTH(m_options); ++d) { - if (machine().ui().options().exists(m_options[d].option)) - { - machine().ui().options().set_value(m_options[d].option, m_options[d].status, OPTION_PRIORITY_CMDLINE, error_string); - } - else - { - if (machine().options().bool_value(m_options[d].option) != m_options[d].status) - { - machine().options().set_value(m_options[d].option, m_options[d].status, OPTION_PRIORITY_CMDLINE, error_string); - machine().options().mark_changed(m_options[d].option); - } - } - } - ui_globals::reset = true; -} - -//------------------------------------------------- -// handlethe options menu -//------------------------------------------------- - -void ui_menu_misc_options::handle() -{ - bool changed = false; - - // process the menu - const ui_menu_event *m_event = process(0); - if (m_event != nullptr && m_event->itemref != nullptr) - { - if (m_event->iptkey == IPT_UI_LEFT || m_event->iptkey == IPT_UI_RIGHT || m_event->iptkey == IPT_UI_SELECT) - { - changed = true; - int value = (FPTR)m_event->itemref; - if (!strcmp(m_options[value].option, OPTION_ENLARGE_SNAPS)) - ui_globals::switch_image = true; - m_options[value].status = !m_options[value].status; - } - } - - if (changed) - reset(UI_MENU_RESET_REMEMBER_REF); -} - -//------------------------------------------------- -// populate -//------------------------------------------------- - -void ui_menu_misc_options::populate() -{ - // add options items - for (int opt = 1; opt < ARRAY_LENGTH(m_options); ++opt) - item_append(_(m_options[opt].description), m_options[opt].status ? _("On") : _("Off"), m_options[opt].status ? MENU_FLAG_RIGHT_ARROW : MENU_FLAG_LEFT_ARROW, (void *)(FPTR)opt); - - item_append(MENU_SEPARATOR_ITEM, nullptr, 0, nullptr); - customtop = machine().ui().get_line_height() + (3.0f * UI_BOX_TB_BORDER); -} - -//------------------------------------------------- -// perform our special rendering -//------------------------------------------------- - -void ui_menu_misc_options::custom_render(void *selectedref, float top, float bottom, float origx1, float origy1, float origx2, float origy2) -{ - float width; - ui_manager &mui = machine().ui(); - - mui.draw_text_full(container, _("Miscellaneous Options"), 0.0f, 0.0f, 1.0f, JUSTIFY_CENTER, WRAP_TRUNCATE, - DRAW_NONE, ARGB_WHITE, ARGB_BLACK, &width, nullptr); - width += 2 * UI_BOX_LR_BORDER; - float maxwidth = MAX(origx2 - origx1, 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 - mui.draw_outlined_box(container, x1, y1, x2, y2, UI_GREEN_COLOR); - - // take off the borders - x1 += UI_BOX_LR_BORDER; - x2 -= UI_BOX_LR_BORDER; - y1 += UI_BOX_TB_BORDER; - - // draw the text within it - mui.draw_text_full(container, _("Miscellaneous Options"), x1, y1, x2 - x1, JUSTIFY_CENTER, WRAP_TRUNCATE, - DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr); -} - //------------------------------------------------- // ctor / dtor //------------------------------------------------- diff --git a/src/emu/ui/optsmenu.cpp b/src/emu/ui/optsmenu.cpp index fef44b8e542..296427b42ac 100644 --- a/src/emu/ui/optsmenu.cpp +++ b/src/emu/ui/optsmenu.cpp @@ -11,6 +11,7 @@ #include "emu.h" #include "ui/ui.h" #include "ui/menu.h" +#include "ui/submenu.h" #include "ui/datfile.h" #include "ui/inifile.h" #include "ui/selector.h" @@ -162,7 +163,7 @@ void ui_menu_game_options::handle() break; case MISC_MENU: if (m_event->iptkey == IPT_UI_SELECT) - ui_menu::stack_push(global_alloc_clear<ui_menu_misc_options>(machine(), container)); + ui_menu::stack_push(global_alloc_clear<ui_submenu>(machine(), container, misc_submenu_options)); break; case SOUND_MENU: if (m_event->iptkey == IPT_UI_SELECT) @@ -188,6 +189,10 @@ void ui_menu_game_options::handle() if (m_event->iptkey == IPT_UI_SELECT) ui_menu::stack_push(global_alloc_clear<ui_menu_custom_filter>(machine(), container)); break; + case ADVANCED_MENU: + if (m_event->iptkey == IPT_UI_SELECT) + ui_menu::stack_push(global_alloc_clear<ui_submenu>(machine(), container, advanced_submenu_options)); + break; case SAVE_CONFIG: if (m_event->iptkey == IPT_UI_SELECT) save_main_option(machine()); @@ -260,9 +265,10 @@ void ui_menu_game_options::populate() } item_append(_("Display Options"), nullptr, 0, (void *)(FPTR)DISPLAY_MENU); item_append(_("Sound Options"), nullptr, 0, (void *)(FPTR)SOUND_MENU); - item_append(_("Miscellaneous Options"), nullptr, 0, (void *)(FPTR)MISC_MENU); + item_append(misc_submenu_options[0].description, nullptr, 0, (void *)(FPTR)MISC_MENU); item_append(_("Device Mapping"), nullptr, 0, (void *)(FPTR)CONTROLLER_MENU); item_append(_("General Inputs"), nullptr, 0, (void *)(FPTR)CGI_MENU); + item_append(advanced_submenu_options[0].description, nullptr, 0, (void *)(FPTR)ADVANCED_MENU); item_append(MENU_SEPARATOR_ITEM, nullptr, 0, nullptr); item_append(_("Save Configuration"), nullptr, 0, (void *)(FPTR)SAVE_CONFIG); diff --git a/src/emu/ui/optsmenu.h b/src/emu/ui/optsmenu.h index 4dd2d0f53be..f6b4243afa0 100644 --- a/src/emu/ui/optsmenu.h +++ b/src/emu/ui/optsmenu.h @@ -33,11 +33,12 @@ private: YEAR_CAT_FILTER, CATEGORY_FILTER, CONF_DIR, - MISC_MENU, DISPLAY_MENU, CUSTOM_MENU, SOUND_MENU, CONTROLLER_MENU, + MISC_MENU, + ADVANCED_MENU, SAVE_OPTIONS, CGI_MENU, CUSTOM_FILTER, diff --git a/src/emu/ui/submenu.cpp b/src/emu/ui/submenu.cpp new file mode 100644 index 00000000000..d1db35ad500 --- /dev/null +++ b/src/emu/ui/submenu.cpp @@ -0,0 +1,304 @@ +// license:BSD-3-Clause +// copyright-holders:Maurizio Petrarota,Jeffrey Clark +/*************************************************************************** + + ui/submenu.cpp + + UI options menu + +***************************************************************************/ + +#include "emu.h" +#include "ui/ui.h" +#include "ui/submenu.h" +#include "ui/utils.h" +#include <limits> + +//------------------------------------------------- +// ctor / dtor +//------------------------------------------------- + +ui_submenu::ui_submenu(running_machine &machine, render_container *container, std::vector<ui_submenu::option> &suboptions) + : ui_menu(machine, container), + m_options(suboptions) +{ + for (auto & sm_option : m_options) + { + if (sm_option.type < ui_submenu::EMU) + continue; + + // fixme use switch + sm_option.entry = machine.options().get_entry(sm_option.name); + if (sm_option.entry == nullptr) + { + sm_option.entry = machine.ui().options().get_entry(sm_option.name); + sm_option.options = dynamic_cast<core_options*>(&machine.ui().options()); + } + else + { + sm_option.options = dynamic_cast<core_options*>(&machine.options()); + } + } +} + +ui_submenu::~ui_submenu() +{ +} + +//------------------------------------------------- +// handlethe options menu +//------------------------------------------------- + +void ui_submenu::handle() +{ + bool changed = false; + std::string error_string, tmptxt; + int i_cur; + float f_cur, f_step; + + // process the menu + const ui_menu_event *m_event = process(UI_MENU_PROCESS_LR_REPEAT); + + if (m_event != nullptr && m_event->itemref != nullptr && + (m_event->iptkey == IPT_UI_LEFT || m_event->iptkey == IPT_UI_RIGHT || m_event->iptkey == IPT_UI_SELECT)) + { + ui_submenu::option *sm_option = (ui_submenu::option *)m_event->itemref; + + switch (sm_option->type) + { + case ui_submenu::EMU: + case ui_submenu::UI: + case ui_submenu::OSD: + switch (sm_option->entry->type()) + { + case OPTION_BOOLEAN: + changed = true; + sm_option->options->set_value(sm_option->name, !strcmp(sm_option->entry->value(),"1") ? "0" : "1", OPTION_PRIORITY_CMDLINE, error_string); + sm_option->entry->mark_changed(); + break; + case OPTION_INTEGER: + if (m_event->iptkey == IPT_UI_LEFT || m_event->iptkey == IPT_UI_RIGHT) + { + changed = true; + i_cur = atof(sm_option->entry->value()); + (m_event->iptkey == IPT_UI_LEFT) ? i_cur-- : i_cur++; + sm_option->options->set_value(sm_option->name, i_cur, OPTION_PRIORITY_CMDLINE, error_string); + sm_option->entry->mark_changed(); + } + break; + case OPTION_FLOAT: + if (m_event->iptkey == IPT_UI_LEFT || m_event->iptkey == IPT_UI_RIGHT) + { + changed = true; + f_cur = atof(sm_option->entry->value()); + if (sm_option->entry->has_range()) + { + f_step = atof(sm_option->entry->minimum()); + if (f_step <= 0.0f) { + int pmin = getprecisionchr(sm_option->entry->minimum()); + int pmax = getprecisionchr(sm_option->entry->maximum()); + tmptxt = '1' + std::string((pmin > pmax) ? pmin : pmax, '0'); + f_step = 1 / atof(tmptxt.c_str()); + } + } + else + { + int precision = getprecisionchr(sm_option->entry->default_value()); + tmptxt = '1' + std::string(precision, '0'); + f_step = 1 / atof(tmptxt.c_str()); + } + if (m_event->iptkey == IPT_UI_LEFT) + f_cur -= f_step; + else + f_cur += f_step; + tmptxt = string_format("%g", f_cur); + sm_option->options->set_value(sm_option->name, tmptxt.c_str(), OPTION_PRIORITY_CMDLINE, error_string); + sm_option->entry->mark_changed(); + } + break; + } + break; + default: + osd_printf_error("Unhandled option: %s", sm_option->description); + break; + } + } + + if (changed) + reset(UI_MENU_RESET_REMEMBER_REF); +} + +//------------------------------------------------- +// populate +//------------------------------------------------- + +void ui_submenu::populate() +{ + UINT32 arrow_flags; + std::string tmptxt; + float f_min, f_max, f_cur; + int i_min, i_max, i_cur; + + // add options + for (auto sm_option = m_options.begin(); sm_option < m_options.end(); sm_option++) + { + // skip first heading (is menu title) + if (sm_option == m_options.begin() && sm_option->type == ui_submenu::HEAD) continue; + + switch (sm_option->type) + { + case ui_submenu::HEAD: + item_append(sm_option->description, nullptr, MENU_FLAG_INVERT | MENU_FLAG_DISABLE, nullptr); + break; + case ui_submenu::SEP: + item_append(MENU_SEPARATOR_ITEM, nullptr, 0, nullptr); + break; + case ui_submenu::CMD: + item_append(sm_option->description, nullptr, 0, static_cast<void*>(&(*sm_option))); + break; + case ui_submenu::EMU: + case ui_submenu::UI: + case ui_submenu::OSD: + switch (sm_option->entry->type()) + { + case OPTION_BOOLEAN: + arrow_flags = sm_option->options->bool_value(sm_option->name) ? MENU_FLAG_RIGHT_ARROW : MENU_FLAG_LEFT_ARROW; + item_append(sm_option->description, + (arrow_flags == MENU_FLAG_RIGHT_ARROW) ? "On" : "Off", + arrow_flags, + static_cast<void*>(&(*sm_option))); + break; + case OPTION_INTEGER: + i_cur = atof(sm_option->entry->value()); + if (sm_option->entry->has_range()) + { + i_min = atof(sm_option->entry->minimum()); + i_max = atof(sm_option->entry->maximum()); + } + else + { + i_min = std::numeric_limits<int>::min(); + i_max = std::numeric_limits<int>::max(); + } + arrow_flags = get_arrow_flags(i_min, i_max, i_cur); + item_append(sm_option->description, + sm_option->entry->value(), + arrow_flags, + static_cast<void*>(&(*sm_option))); + break; + case OPTION_FLOAT: + f_cur = atof(sm_option->entry->value()); + if (sm_option->entry->has_range()) + { + f_min = atof(sm_option->entry->minimum()); + f_max = atof(sm_option->entry->maximum()); + } + else + { + f_min = 0.0f; + f_max = std::numeric_limits<float>::max(); + } + arrow_flags = get_arrow_flags(f_min, f_max, f_cur); + tmptxt = string_format("%g", f_cur); + item_append(sm_option->description, + tmptxt.c_str(), + arrow_flags, + static_cast<void*>(&(*sm_option))); + break; + default: + arrow_flags = MENU_FLAG_RIGHT_ARROW; + item_append(sm_option->description, + sm_option->options->value(sm_option->name), + arrow_flags, static_cast<void*>(&(*sm_option))); + break; + } + break; + default: + osd_printf_error("Unknown option type: %s", sm_option->description); + break; + } + } + + item_append(MENU_SEPARATOR_ITEM, nullptr, 0, nullptr); + custombottom = customtop = machine().ui().get_line_height() + (3.0f * UI_BOX_TB_BORDER); +} + +//------------------------------------------------- +// perform our special rendering +//------------------------------------------------- + +void ui_submenu::custom_render(void *selectedref, float top, float bottom, float origx1, float origy1, float origx2, float origy2) +{ + static int interval = 0; + static ui_submenu::option *last_sm_option = nullptr; + + float width; + ui_manager &mui = machine().ui(); + + mui.draw_text_full(container, m_options[0].description, 0.0f, 0.0f, 1.0f, JUSTIFY_CENTER, WRAP_TRUNCATE, + DRAW_NONE, ARGB_WHITE, ARGB_BLACK, &width, nullptr); + width += 2 * UI_BOX_LR_BORDER; + float maxwidth = MAX(origx2 - origx1, 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 + mui.draw_outlined_box(container, x1, y1, x2, y2, UI_GREEN_COLOR); + + // take off the borders + x1 += UI_BOX_LR_BORDER; + x2 -= UI_BOX_LR_BORDER; + y1 += UI_BOX_TB_BORDER; + + // draw the text within it + mui.draw_text_full(container, m_options[0].description, x1, y1, x2 - x1, JUSTIFY_CENTER, WRAP_TRUNCATE, + DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr); + + if (selectedref != nullptr) + { + ui_submenu::option *selected_sm_option = (ui_submenu::option *)selectedref; + + if (last_sm_option == selected_sm_option) { + if (interval <= 30) interval++; + } else { + last_sm_option = selected_sm_option; + interval = 0; + } + + if (interval > 30 && last_sm_option->entry != nullptr) + { + mui.draw_text_full(container, last_sm_option->entry->description(), 0.0f, 0.0f, 1.0f, JUSTIFY_CENTER, WRAP_TRUNCATE, + DRAW_NONE, ARGB_WHITE, ARGB_BLACK, &width, nullptr); + + width += 2 * UI_BOX_LR_BORDER; + maxwidth = 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; + + // draw a box + mui.draw_outlined_box(container, x1, y1, x2, y2, UI_RED_COLOR); + + // take off the borders + x1 += UI_BOX_LR_BORDER; + x2 -= UI_BOX_LR_BORDER; + y1 += UI_BOX_TB_BORDER; + + // draw the text within it + mui.draw_text_full(container, last_sm_option->entry->description(), x1, y1, x2 - x1, JUSTIFY_CENTER, WRAP_NEVER, + DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr); + } + } + else + { + last_sm_option = nullptr; + interval = 0; + } +} diff --git a/src/emu/ui/submenu.h b/src/emu/ui/submenu.h new file mode 100644 index 00000000000..cf658b50d4c --- /dev/null +++ b/src/emu/ui/submenu.h @@ -0,0 +1,129 @@ +// license:BSD-3-Clause +// copyright-holders:Maurizio Petrarota,Jeffrey Clark +/*************************************************************************** + + ui/submenu.h + + UI options menu. + +***************************************************************************/ +#pragma once + +#ifndef __UI_SUBMENU_H__ +#define __UI_SUBMENU_H__ + +#include "ui/menu.h" + +//------------------------------------------------- +// class ui menu +//------------------------------------------------- +class ui_submenu : public ui_menu +{ +public: + enum option_type { + HEAD, + SEP, + MENU, + CMD, + EMU, + UI, + OSD, + }; + + struct option { + option_type type; + const char *description; + const char *name; + core_options::entry *entry; + core_options (*options); + }; + + ui_submenu(running_machine &machine, render_container *container, std::vector<ui_submenu::option> &suboptions); + virtual ~ui_submenu(); + virtual void populate() override; + virtual void handle() override; + virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override; + +private: + std::vector<option> &m_options; +}; + +static std::vector<ui_submenu::option> misc_submenu_options = { + { ui_submenu::HEAD, _("Miscellaneous Options") }, + { ui_submenu::UI, _("Re-select last machine played"), OPTION_REMEMBER_LAST }, + { ui_submenu::UI, _("Enlarge images in the right panel"), OPTION_ENLARGE_SNAPS }, + { ui_submenu::UI, _("DATs info"), OPTION_DATS_ENABLED }, + { ui_submenu::EMU, _("Cheats"), OPTION_CHEAT }, + { ui_submenu::EMU, _("Show mouse pointer"), OPTION_UI_MOUSE }, + { ui_submenu::EMU, _("Confirm quit from machines"), OPTION_CONFIRM_QUIT }, + { ui_submenu::EMU, _("Skip information screen at startup"), OPTION_SKIP_GAMEINFO }, + { ui_submenu::UI, _("Force 4:3 aspect for snapshot display"), OPTION_FORCED4X3 }, + { ui_submenu::UI, _("Use image as background"), OPTION_USE_BACKGROUND }, + { ui_submenu::UI, _("Skip bios selection menu"), OPTION_SKIP_BIOS_MENU }, + { ui_submenu::UI, _("Skip software parts selection menu"), OPTION_SKIP_PARTS_MENU }, + { ui_submenu::UI, _("Info auto audit"), OPTION_INFO_AUTO_AUDIT }, +}; + +static std::vector<ui_submenu::option> advanced_submenu_options = { + { ui_submenu::HEAD, _("Advanced Options") }, + { ui_submenu::HEAD, _("Performance Options") }, + { ui_submenu::EMU, _("Auto frame skip"), OPTION_AUTOFRAMESKIP }, + { ui_submenu::EMU, _("Frame skip"), OPTION_FRAMESKIP }, + { ui_submenu::EMU, _("Throttle"), OPTION_THROTTLE }, + { ui_submenu::EMU, _("Sleep"), OPTION_SLEEP }, + { ui_submenu::EMU, _("Speed"), OPTION_SPEED }, + { ui_submenu::EMU, _("Refresh speed"), OPTION_REFRESHSPEED }, +//}; + +//static std::vector<ui_submenu::option> rotate_submenu_options = { + { ui_submenu::HEAD, _("Rotation Options") }, + { ui_submenu::EMU, _("Rotate"), OPTION_ROTATE }, + { ui_submenu::EMU, _("Rotate right"), OPTION_ROR }, + { ui_submenu::EMU, _("Rotate left"), OPTION_ROL }, + { ui_submenu::EMU, _("Auto rotate right"), OPTION_AUTOROR }, + { ui_submenu::EMU, _("Auto rotate left"), OPTION_AUTOROL }, + { ui_submenu::EMU, _("Flip X"), OPTION_FLIPX }, + { ui_submenu::EMU, _("Flip Y"), OPTION_FLIPY }, +//}; + +//static std::vector<ui_submenu::option> artwork_submenu_options = { + { ui_submenu::HEAD, _("Artwork Options") }, + { ui_submenu::EMU, _("Artwork Crop"), OPTION_ARTWORK_CROP }, + { ui_submenu::EMU, _("Use Backdrops"), OPTION_USE_BACKDROPS }, + { ui_submenu::EMU, _("Use Overlays"), OPTION_USE_OVERLAYS }, + { ui_submenu::EMU, _("Use Bezels"), OPTION_USE_BEZELS }, + { ui_submenu::EMU, _("Use Control Panels"), OPTION_USE_CPANELS }, + { ui_submenu::EMU, _("Use Marquees"), OPTION_USE_MARQUEES }, +//}; + +//static std::vector<ui_submenu::option> state_submenu_options = { + { ui_submenu::HEAD, _("State/Playback Options") }, + { ui_submenu::EMU, _("Automatic save/restore"), OPTION_AUTOSAVE }, + { ui_submenu::EMU, _("Bilinear snapshot"), OPTION_SNAPBILINEAR }, + { ui_submenu::EMU, _("Burn-in"), OPTION_BURNIN }, +//}; + +//static std::vector<ui_submenu::option> input_submenu_options = { + { ui_submenu::HEAD, _("Input Options") }, + { ui_submenu::EMU, _("Coin lockout"), OPTION_COIN_LOCKOUT }, + { ui_submenu::EMU, _("Mouse"), OPTION_MOUSE }, + { ui_submenu::EMU, _("Joystick"), OPTION_JOYSTICK }, + { ui_submenu::EMU, _("Lightgun"), OPTION_LIGHTGUN }, + { ui_submenu::EMU, _("Multi-keyboard"), OPTION_MULTIKEYBOARD }, + { ui_submenu::EMU, _("Multi-mouse"), OPTION_MULTIMOUSE }, + { ui_submenu::EMU, _("Steadykey"), OPTION_STEADYKEY }, + { ui_submenu::EMU, _("UI active"), OPTION_UI_ACTIVE }, + { ui_submenu::EMU, _("Offscreen reload"), OPTION_OFFSCREEN_RELOAD }, + { ui_submenu::EMU, _("Joystick deadzone"), OPTION_JOYSTICK_DEADZONE }, + { ui_submenu::EMU, _("Joystick saturation"), OPTION_JOYSTICK_SATURATION }, + { ui_submenu::EMU, _("Natural keyboard"), OPTION_NATURAL_KEYBOARD }, + { ui_submenu::EMU, _("Simultaneous contradictory"), OPTION_JOYSTICK_CONTRADICTORY }, + { ui_submenu::EMU, _("Coin impulse"), OPTION_COIN_IMPULSE }, +}; + +//static std::vector<ui_submenu::option> export_submenu_options = { +// { ui_submenu::COMMAND, _("Export XML format (like -listxml)"), "exportxml" }, +// { ui_submenu::COMMAND, _("Export TXT format (like -listfull)"), "exporttxt" }, +//}; + +#endif /* __UI_SUBMENU_H__ */ diff --git a/src/emu/ui/utils.cpp b/src/emu/ui/utils.cpp index 1e998d04c9d..6a59208cd30 100644 --- a/src/emu/ui/utils.cpp +++ b/src/emu/ui/utils.cpp @@ -84,6 +84,15 @@ const char* strensure(const char* s) return s == nullptr ? "" : s; } +int getprecisionchr(const char* s) +{ + int precision = 1; + char *dp = const_cast<char *>(strchr(s, '.')); + if (dp != nullptr) + precision = strlen(s) - (dp - s) - 1; + return precision; +} + //------------------------------------------------- // search a substring with even partial matching //------------------------------------------------- diff --git a/src/emu/ui/utils.h b/src/emu/ui/utils.h index 81107c0911c..519f74e667b 100644 --- a/src/emu/ui/utils.h +++ b/src/emu/ui/utils.h @@ -254,5 +254,6 @@ char* chartrimcarriage(char str[]); const char* strensure(const char* s); +int getprecisionchr(const char* s); #endif /* __UI_UTILS_H__ */ diff --git a/src/lib/util/options.h b/src/lib/util/options.h index 9af9c61233e..a6c003162fd 100644 --- a/src/lib/util/options.h +++ b/src/lib/util/options.h @@ -131,6 +131,7 @@ public: // getters entry *first() const { return m_entrylist.first(); } const char *command() const { return m_command.c_str(); } + entry *get_entry(const char *option) { return (m_entrymap.find(option) != m_entrymap.end()) ? m_entrymap.find(option)->second : nullptr; } // range iterators using auto_iterator = simple_list<entry>::auto_iterator; |