mirror of
https://github.com/holub/mame
synced 2025-04-23 00:39:36 +03:00
Merge pull request #782 from h0tw1r3/feature-extmenu
refactor miscmenu and add adv menu (nw)
This commit is contained in:
commit
9c61e636f1
@ -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",
|
||||
|
@ -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)" },
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
//-------------------------------------------------
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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,
|
||||
|
304
src/emu/ui/submenu.cpp
Normal file
304
src/emu/ui/submenu.cpp
Normal file
@ -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;
|
||||
}
|
||||
}
|
129
src/emu/ui/submenu.h
Normal file
129
src/emu/ui/submenu.h
Normal file
@ -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__ */
|
@ -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
|
||||
//-------------------------------------------------
|
||||
|
@ -254,5 +254,6 @@ char* chartrimcarriage(char str[]);
|
||||
|
||||
const char* strensure(const char* s);
|
||||
|
||||
int getprecisionchr(const char* s);
|
||||
|
||||
#endif /* __UI_UTILS_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;
|
||||
|
Loading…
Reference in New Issue
Block a user