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 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(machine(), container)); + ui_menu::stack_push(global_alloc_clear(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(machine(), container)); break; + case ADVANCED_MENU: + if (m_event->iptkey == IPT_UI_SELECT) + ui_menu::stack_push(global_alloc_clear(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 + +//------------------------------------------------- +// ctor / dtor +//------------------------------------------------- + +ui_submenu::ui_submenu(running_machine &machine, render_container *container, std::vector &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(&machine.ui().options()); + } + else + { + sm_option.options = dynamic_cast(&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(&(*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(&(*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::min(); + i_max = std::numeric_limits::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(&(*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::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(&(*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(&(*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 &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