summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
author Vas Crabb <vas@vastheman.com>2016-07-10 02:42:38 +1000
committer Vas Crabb <vas@vastheman.com>2016-07-10 03:01:13 +1000
commit1abf53ca6a7a01ae2d4491825a97b0a4baef634a (patch)
tree2a061c81dab912dbf52f8cdd54f97507820029dd /src
parent2364b48f0dd496de3908fa4d3bcd24693a5f6231 (diff)
UI code refactoring: [Vas Crabb]
* Split out main menu and dat box drawing from base class * Make a bunch of class statics proper per-machine persistent objects * Object lifecycle fixes
Diffstat (limited to 'src')
-rw-r--r--src/frontend/mame/ui/auditmenu.cpp2
-rw-r--r--src/frontend/mame/ui/custui.cpp2
-rw-r--r--src/frontend/mame/ui/datmenu.cpp145
-rw-r--r--src/frontend/mame/ui/datmenu.h4
-rw-r--r--src/frontend/mame/ui/dirmenu.cpp4
-rw-r--r--src/frontend/mame/ui/filecreate.cpp6
-rw-r--r--src/frontend/mame/ui/filesel.cpp10
-rw-r--r--src/frontend/mame/ui/floppycntrl.cpp12
-rw-r--r--src/frontend/mame/ui/imgcntrl.cpp14
-rw-r--r--src/frontend/mame/ui/mainmenu.cpp2
-rw-r--r--src/frontend/mame/ui/menu.cpp1700
-rw-r--r--src/frontend/mame/ui/menu.h182
-rw-r--r--src/frontend/mame/ui/miscmenu.cpp2
-rw-r--r--src/frontend/mame/ui/selector.cpp2
-rw-r--r--src/frontend/mame/ui/selgame.cpp91
-rw-r--r--src/frontend/mame/ui/selgame.h4
-rw-r--r--src/frontend/mame/ui/selmenu.cpp1287
-rw-r--r--src/frontend/mame/ui/selmenu.h134
-rw-r--r--src/frontend/mame/ui/selsoft.cpp53
-rw-r--r--src/frontend/mame/ui/selsoft.h3
-rw-r--r--src/frontend/mame/ui/simpleselgame.cpp4
-rw-r--r--src/frontend/mame/ui/sliders.cpp6
-rw-r--r--src/frontend/mame/ui/swlist.cpp8
-rw-r--r--src/frontend/mame/ui/ui.cpp8
24 files changed, 1963 insertions, 1722 deletions
diff --git a/src/frontend/mame/ui/auditmenu.cpp b/src/frontend/mame/ui/auditmenu.cpp
index 26c667401c0..ea3058914ab 100644
--- a/src/frontend/mame/ui/auditmenu.cpp
+++ b/src/frontend/mame/ui/auditmenu.cpp
@@ -159,7 +159,7 @@ void menu_audit::handle()
std::stable_sort(m_unavailablesorted.begin(), m_unavailablesorted.end(), sorted_game_list);
save_available_machines();
reset_parent(reset_options::SELECT_FIRST);
- menu::stack_pop(machine());
+ stack_pop();
}
//-------------------------------------------------
diff --git a/src/frontend/mame/ui/custui.cpp b/src/frontend/mame/ui/custui.cpp
index 6eb4352e0c5..6a7d7635e92 100644
--- a/src/frontend/mame/ui/custui.cpp
+++ b/src/frontend/mame/ui/custui.cpp
@@ -1045,7 +1045,7 @@ void menu_palette_sel::handle()
{
m_original = rgb_t((UINT32)strtoul(item[selected].subtext.c_str(), nullptr, 16));
reset_parent(reset_options::SELECT_FIRST);
- menu::stack_pop(machine());
+ stack_pop();
}
}
}
diff --git a/src/frontend/mame/ui/datmenu.cpp b/src/frontend/mame/ui/datmenu.cpp
index 9445f30c10f..7ac8095c725 100644
--- a/src/frontend/mame/ui/datmenu.cpp
+++ b/src/frontend/mame/ui/datmenu.cpp
@@ -18,6 +18,10 @@
#include "mame.h"
#include "rendfont.h"
#include "softlist.h"
+#include "uiinput.h"
+
+#include <cmath>
+
namespace ui {
//-------------------------------------------------
@@ -119,6 +123,147 @@ void menu_dats_view::populate()
}
//-------------------------------------------------
+// draw - draw dats menu
+//-------------------------------------------------
+
+void menu_dats_view::draw(UINT32 flags)
+{
+ auto line_height = ui().get_line_height();
+ auto ud_arrow_width = line_height * machine().render().ui_aspect();
+ auto gutter_width = 0.52f * line_height * machine().render().ui_aspect();
+ mouse_x = -1, mouse_y = -1;
+ float visible_width = 1.0f - 2.0f * UI_BOX_LR_BORDER;
+ float visible_left = (1.0f - visible_width) * 0.5f;
+
+ draw_background();
+
+ hover = item.size() + 1;
+ visible_items = item.size() - 2;
+ float extra_height = 2.0f * line_height;
+ float visible_extra_menu_height = customtop + custombottom + extra_height;
+
+ // locate mouse
+ mouse_hit = false;
+ mouse_button = false;
+ mouse_target = machine().ui_input().find_mouse(&mouse_target_x, &mouse_target_y, &mouse_button);
+ if (mouse_target != nullptr)
+ if (mouse_target->map_point_container(mouse_target_x, mouse_target_y, *container, mouse_x, mouse_y))
+ mouse_hit = true;
+
+ // account for extra space at the top and bottom
+ float visible_main_menu_height = 1.0f - 2.0f * UI_BOX_TB_BORDER - visible_extra_menu_height;
+ m_visible_lines = int(std::trunc(visible_main_menu_height / line_height));
+ visible_main_menu_height = float(m_visible_lines) * line_height;
+
+ // compute top/left of inner menu area by centering
+ float visible_top = (1.0f - (visible_main_menu_height + visible_extra_menu_height)) * 0.5f;
+
+ // if the menu is at the bottom of the extra, adjust
+ visible_top += customtop;
+
+ // compute left box size
+ float x1 = visible_left;
+ float y1 = visible_top - UI_BOX_TB_BORDER;
+ float x2 = x1 + visible_width;
+ float y2 = visible_top + visible_main_menu_height + UI_BOX_TB_BORDER + extra_height;
+ float line = visible_top + float(m_visible_lines) * line_height;
+
+ ui().draw_outlined_box(container, x1, y1, x2, y2, UI_BACKGROUND_COLOR);
+
+ m_visible_lines = (std::min)(visible_items, m_visible_lines);
+ top_line = (std::max)(0, top_line);
+ if (top_line + m_visible_lines >= visible_items)
+ top_line = visible_items - m_visible_lines;
+
+ // 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;
+
+ int const n_loop = (std::min)(visible_items, m_visible_lines);
+ for (int linenum = 0; linenum < n_loop; linenum++)
+ {
+ float line_y = visible_top + (float)linenum * line_height;
+ int itemnum = top_line + linenum;
+ const menu_item &pitem = item[itemnum];
+ const char *itemtext = pitem.text.c_str();
+ rgb_t fgcolor = UI_TEXT_COLOR;
+ rgb_t bgcolor = UI_TEXT_BG_COLOR;
+ float line_x0 = x1 + 0.5f * UI_LINE_WIDTH;
+ float line_y0 = line_y;
+ float line_x1 = x2 - 0.5f * UI_LINE_WIDTH;
+ float line_y1 = line_y + line_height;
+
+ // if we're on the top line, display the up arrow
+ if (linenum == 0 && top_line != 0)
+ {
+ draw_arrow(container, 0.5f * (x1 + x2) - 0.5f * ud_arrow_width, line_y + 0.25f * line_height,
+ 0.5f * (x1 + x2) + 0.5f * ud_arrow_width, line_y + 0.75f * line_height, fgcolor, ROT0);
+
+ if (mouse_hit && line_x0 <= mouse_x && line_x1 > mouse_x && line_y0 <= mouse_y && line_y1 > mouse_y)
+ {
+ fgcolor = UI_MOUSEOVER_COLOR;
+ bgcolor = UI_MOUSEOVER_BG_COLOR;
+ highlight(container, line_x0, line_y0, line_x1, line_y1, bgcolor);
+ hover = HOVER_ARROW_UP;
+ }
+ }
+ // if we're on the bottom line, display the down arrow
+ else if (linenum == m_visible_lines - 1 && itemnum != visible_items - 1)
+ {
+ draw_arrow(container, 0.5f * (x1 + x2) - 0.5f * ud_arrow_width, line_y + 0.25f * line_height,
+ 0.5f * (x1 + x2) + 0.5f * ud_arrow_width, line_y + 0.75f * line_height, fgcolor, ROT0 ^ ORIENTATION_FLIP_Y);
+
+ if (mouse_hit && line_x0 <= mouse_x && line_x1 > mouse_x && line_y0 <= mouse_y && line_y1 > mouse_y)
+ {
+ fgcolor = UI_MOUSEOVER_COLOR;
+ bgcolor = UI_MOUSEOVER_BG_COLOR;
+ highlight(container, line_x0, line_y0, line_x1, line_y1, bgcolor);
+ hover = HOVER_ARROW_DOWN;
+ }
+ }
+
+ // draw dats text
+ else if (pitem.subtext.empty())
+ {
+ ui().draw_text_full(container, itemtext, effective_left, line_y, effective_width, ui::text_layout::LEFT, ui::text_layout::NEVER,
+ mame_ui_manager::NORMAL, fgcolor, bgcolor, nullptr, nullptr);
+ }
+ }
+
+ for (size_t count = visible_items; count < item.size(); count++)
+ {
+ const menu_item &pitem = item[count];
+ const char *itemtext = pitem.text.c_str();
+ float line_x0 = x1 + 0.5f * UI_LINE_WIDTH;
+ float line_y0 = line;
+ float line_x1 = x2 - 0.5f * UI_LINE_WIDTH;
+ float line_y1 = line + line_height;
+ rgb_t fgcolor = UI_SELECTED_COLOR;
+ rgb_t bgcolor = UI_SELECTED_BG_COLOR;
+
+ if (mouse_hit && line_x0 <= mouse_x && line_x1 > mouse_x && line_y0 <= mouse_y && line_y1 > mouse_y && is_selectable(pitem))
+ hover = count;
+
+ if (pitem.type == menu_item_type::SEPARATOR)
+ container->add_line(visible_left, line + 0.5f * line_height, visible_left + visible_width, line + 0.5f * line_height,
+ UI_LINE_WIDTH, UI_TEXT_COLOR, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+ else
+ {
+ highlight(container, line_x0, line_y0, line_x1, line_y1, bgcolor);
+ ui().draw_text_full(container, itemtext, effective_left, line, effective_width, ui::text_layout::CENTER, ui::text_layout::TRUNCATE,
+ mame_ui_manager::NORMAL, fgcolor, bgcolor, nullptr, nullptr);
+ }
+ line += line_height;
+ }
+
+ // if there is something special to add, do it by calling the virtual method
+ custom_render(get_selection_ref(), customtop, custombottom, x1, y1, x2, y2);
+
+ // return the number of visible lines, minus 1 for top arrow and 1 for bottom arrow
+ m_visible_items = m_visible_lines - (top_line != 0) - (top_line + m_visible_lines != visible_items);
+}
+
+//-------------------------------------------------
// perform our special rendering
//-------------------------------------------------
diff --git a/src/frontend/mame/ui/datmenu.h b/src/frontend/mame/ui/datmenu.h
index fb896781ef9..300a0f60eeb 100644
--- a/src/frontend/mame/ui/datmenu.h
+++ b/src/frontend/mame/ui/datmenu.h
@@ -38,6 +38,10 @@ public:
virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override;
private:
+ // draw dats menu
+ virtual void draw(UINT32 flags) override;
+
+ int visible_items;
int m_actual;
const game_driver *m_driver;
ui_software_info *m_swinfo;
diff --git a/src/frontend/mame/ui/dirmenu.cpp b/src/frontend/mame/ui/dirmenu.cpp
index 13875c328f5..5e377d4e474 100644
--- a/src/frontend/mame/ui/dirmenu.cpp
+++ b/src/frontend/mame/ui/dirmenu.cpp
@@ -392,7 +392,7 @@ void menu_add_change_folder::handle()
}
reset_parent(reset_options::SELECT_FIRST);
- menu::stack_pop(machine());
+ stack_pop();
}
else if (menu_event->is_char_printable())
{
@@ -614,7 +614,7 @@ void menu_remove_folder::handle()
}
reset_parent(reset_options::REMEMBER_REF);
- menu::stack_pop(machine());
+ stack_pop();
}
}
diff --git a/src/frontend/mame/ui/filecreate.cpp b/src/frontend/mame/ui/filecreate.cpp
index 80513c27318..9cd260684a3 100644
--- a/src/frontend/mame/ui/filecreate.cpp
+++ b/src/frontend/mame/ui/filecreate.cpp
@@ -125,7 +125,7 @@ void menu_confirm_save_as::handle()
*m_yes = true;
// no matter what, pop out
- menu::stack_pop(machine());
+ stack_pop();
}
}
@@ -238,7 +238,7 @@ void menu_file_create::handle()
if (tmp_file.find(".") != -1 && tmp_file.find(".") < tmp_file.length() - 1)
{
m_current_file = m_filename;
- menu::stack_pop(machine());
+ stack_pop();
}
else
ui().popup_time(1, "%s", _("Please enter a file extension too"));
@@ -316,7 +316,7 @@ void menu_select_format::handle()
if (event != nullptr && event->iptkey == IPT_UI_SELECT)
{
*m_result = int(FPTR(event->itemref));
- menu::stack_pop(machine());
+ stack_pop();
}
}
diff --git a/src/frontend/mame/ui/filesel.cpp b/src/frontend/mame/ui/filesel.cpp
index 34e86c99fe8..673f6a96161 100644
--- a/src/frontend/mame/ui/filesel.cpp
+++ b/src/frontend/mame/ui/filesel.cpp
@@ -392,18 +392,18 @@ void menu_file_selector::handle()
case SELECTOR_ENTRY_TYPE_EMPTY:
// empty slot - unload
m_result = result::EMPTY;
- menu::stack_pop(machine());
+ stack_pop();
break;
case SELECTOR_ENTRY_TYPE_CREATE:
// create
m_result = result::CREATE;
- menu::stack_pop(machine());
+ stack_pop();
break;
case SELECTOR_ENTRY_TYPE_SOFTWARE_LIST:
m_result = result::SOFTLIST;
- menu::stack_pop(machine());
+ stack_pop();
break;
case SELECTOR_ENTRY_TYPE_DRIVE:
@@ -424,7 +424,7 @@ void menu_file_selector::handle()
// file
m_current_file.assign(entry->fullpath);
m_result = result::FILE;
- menu::stack_pop(machine());
+ stack_pop();
break;
}
@@ -551,7 +551,7 @@ void menu_select_rw::handle()
if (event != nullptr && event->iptkey == IPT_UI_SELECT)
{
m_result = result_from_itemref(event->itemref);
- menu::stack_pop(machine());
+ stack_pop();
}
}
diff --git a/src/frontend/mame/ui/floppycntrl.cpp b/src/frontend/mame/ui/floppycntrl.cpp
index 0fc1408f603..f47b4d580bf 100644
--- a/src/frontend/mame/ui/floppycntrl.cpp
+++ b/src/frontend/mame/ui/floppycntrl.cpp
@@ -67,7 +67,7 @@ void menu_control_floppy_image::hook_load(std::string filename, bool softlist)
{
machine().popmessage("When loaded from software list, the disk is Read-only.\n");
image->load(filename.c_str());
- menu::stack_pop(machine());
+ stack_pop();
return;
}
@@ -77,7 +77,7 @@ void menu_control_floppy_image::hook_load(std::string filename, bool softlist)
if (!input_format)
{
machine().popmessage("Error: %s\n", image->error());
- menu::stack_pop(machine());
+ stack_pop();
return;
}
@@ -134,7 +134,7 @@ void menu_control_floppy_image::handle()
output_filename = util::zippath_combine(m_current_directory.c_str(), m_current_file.c_str());
output_format = format_array[submenu_result.i];
do_load_create();
- menu::stack_pop(machine());
+ stack_pop();
}
break;
@@ -142,18 +142,18 @@ void menu_control_floppy_image::handle()
switch(submenu_result.rw) {
case menu_select_rw::result::READONLY:
do_load_create();
- menu::stack_pop(machine());
+ stack_pop();
break;
case menu_select_rw::result::READWRITE:
output_format = input_format;
do_load_create();
- menu::stack_pop(machine());
+ stack_pop();
break;
case menu_select_rw::result::WRITE_DIFF:
machine().popmessage("Sorry, diffs are not supported yet\n");
- menu::stack_pop(machine());
+ stack_pop();
break;
case menu_select_rw::result::WRITE_OTHER:
diff --git a/src/frontend/mame/ui/imgcntrl.cpp b/src/frontend/mame/ui/imgcntrl.cpp
index e6521f931c0..62082930f3b 100644
--- a/src/frontend/mame/ui/imgcntrl.cpp
+++ b/src/frontend/mame/ui/imgcntrl.cpp
@@ -156,7 +156,7 @@ void menu_control_device_image::hook_load(std::string name, bool softlist)
{
if (image->is_reset_on_load()) image->set_init_phase();
image->load(name.c_str());
- menu::stack_pop(machine());
+ stack_pop();
}
@@ -198,7 +198,7 @@ void menu_control_device_image::handle()
case SELECT_SOFTLIST:
if(!sld) {
- menu::stack_pop(machine());
+ stack_pop();
break;
}
software_info_name = "";
@@ -251,7 +251,7 @@ void menu_control_device_image::handle()
case menu_software_parts::result::EMPTY:
image->unload();
- menu::stack_pop(machine());
+ stack_pop();
break;
case menu_software_parts::result::SWLIST:
@@ -260,7 +260,7 @@ void menu_control_device_image::handle()
break;
case menu_software_parts::result::INVALID: // return to system
- menu::stack_pop(machine());
+ stack_pop();
break;
}
@@ -270,7 +270,7 @@ void menu_control_device_image::handle()
switch(submenu_result.filesel) {
case menu_file_selector::result::EMPTY:
image->unload();
- menu::stack_pop(machine());
+ stack_pop();
break;
case menu_file_selector::result::FILE:
@@ -288,7 +288,7 @@ void menu_control_device_image::handle()
break;
default: // return to system
- menu::stack_pop(machine());
+ stack_pop();
break;
}
break;
@@ -326,7 +326,7 @@ void menu_control_device_image::handle()
int err = image->create(path.c_str(), nullptr, nullptr);
if (err != 0)
machine().popmessage("Error: %s", image->error());
- menu::stack_pop(machine());
+ stack_pop();
break;
}
}
diff --git a/src/frontend/mame/ui/mainmenu.cpp b/src/frontend/mame/ui/mainmenu.cpp
index 7fa50f9f8ea..0342559d47e 100644
--- a/src/frontend/mame/ui/mainmenu.cpp
+++ b/src/frontend/mame/ui/mainmenu.cpp
@@ -272,7 +272,7 @@ void menu_main::handle()
break;
case QUIT_GAME:
- menu::stack_pop(machine());
+ stack_pop();
ui().request_quit();
break;
diff --git a/src/frontend/mame/ui/menu.cpp b/src/frontend/mame/ui/menu.cpp
index 095cae4acf1..6cfc3c464db 100644
--- a/src/frontend/mame/ui/menu.cpp
+++ b/src/frontend/mame/ui/menu.cpp
@@ -15,20 +15,18 @@
#include "ui/ui.h"
#include "ui/mainmenu.h"
#include "ui/utils.h"
-#include "ui/defimg.h"
-#include "ui/starimg.h"
-#include "ui/icorender.h"
-#include "ui/toolbar.h"
#include "ui/miscmenu.h"
#include "cheat.h"
-#include "drivenum.h"
#include "mame.h"
+
+#include "drivenum.h"
#include "rendutil.h"
#include "uiinput.h"
#include <algorithm>
#include <cmath>
+#include <utility>
namespace ui {
@@ -37,75 +35,31 @@ namespace ui {
***************************************************************************/
#define UI_MENU_POOL_SIZE 65536
-#define MAX_ICONS_RENDER 40
-
-static std::vector<std::pair<const char *, const char *>> arts_info =
-{
- { __("Snapshots"), OPTION_SNAPSHOT_DIRECTORY },
- { __("Cabinets"), OPTION_CABINETS_PATH },
- { __("Control Panels"), OPTION_CPANELS_PATH },
- { __("PCBs"), OPTION_PCBS_PATH },
- { __("Flyers"), OPTION_FLYERS_PATH },
- { __("Titles"), OPTION_TITLES_PATH },
- { __("Ends"), OPTION_ENDS_PATH },
- { __("Artwork Preview"), OPTION_ARTPREV_PATH },
- { __("Bosses"), OPTION_BOSSES_PATH },
- { __("Logos"), OPTION_LOGOS_PATH },
- { __("Versus"), OPTION_VERSUS_PATH },
- { __("Game Over"), OPTION_GAMEOVER_PATH },
- { __("HowTo"), OPTION_HOWTO_PATH },
- { __("Scores"), OPTION_SCORES_PATH },
- { __("Select"), OPTION_SELECT_PATH },
- { __("Marquees"), OPTION_MARQUEES_PATH },
- { __("Covers"), OPTION_COVER_PATH },
-};
-
-static const char *hover_msg[] = {
- __("Add or remove favorites"),
- __("Export displayed list to file"),
- __("Show DATs view"),
-};
/***************************************************************************
GLOBAL VARIABLES
***************************************************************************/
-std::unique_ptr<menu> menu::menu_stack;
-std::unique_ptr<menu> menu::menu_free;
+std::mutex menu::s_global_state_guard;
+menu::global_state_map menu::s_global_states;
std::unique_ptr<bitmap_rgb32> menu::hilight_bitmap;
render_texture *menu::hilight_texture;
-render_texture *menu::arrow_texture;
render_texture *menu::snapx_texture;
render_texture *menu::hilight_main_texture;
-render_texture *menu::bgrnd_texture;
-render_texture *menu::star_texture;
-render_texture *menu::toolbar_texture[UI_TOOLBAR_BUTTONS];
-render_texture *menu::sw_toolbar_texture[UI_TOOLBAR_BUTTONS];
-render_texture *menu::icons_texture[MAX_ICONS_RENDER];
std::unique_ptr<bitmap_argb32> menu::snapx_bitmap;
-std::unique_ptr<bitmap_argb32> menu::no_avail_bitmap;
-std::unique_ptr<bitmap_argb32> menu::star_bitmap;
-std::unique_ptr<bitmap_argb32> menu::bgrnd_bitmap;
-std::vector<std::unique_ptr<bitmap_argb32>> menu::icons_bitmap;
std::unique_ptr<bitmap_rgb32> menu::hilight_main_bitmap;
-std::vector<std::shared_ptr<bitmap_argb32>> menu::toolbar_bitmap;
-std::vector<std::shared_ptr<bitmap_argb32>> menu::sw_toolbar_bitmap;
-std::vector<const game_driver *> menu::m_old_icons;
/***************************************************************************
INLINE FUNCTIONS
***************************************************************************/
-//-------------------------------------------------
-// is_selectable - return TRUE if the given
-// item is selectable
-//-------------------------------------------------
-
-inline bool is_selectable(menu_item const &item)
+inline menu::global_state_ptr menu::get_global_state(running_machine &machine)
{
- return ((item.flags & (menu::FLAG_MULTILINE | menu::FLAG_DISABLE)) == 0 && item.type != menu_item_type::SEPARATOR);
-}
+ std::lock_guard<std::mutex> guard(s_global_state_guard);
+ auto const it(s_global_states.find(&machine));
+ return (it != s_global_states.end()) ? it->second : global_state_ptr();
+}
//-------------------------------------------------
// exclusive_input_pressed - return TRUE if the
@@ -113,14 +67,17 @@ inline bool is_selectable(menu_item const &item)
// reported a key
//-------------------------------------------------
-inline bool menu::exclusive_input_pressed(int key, int repeat)
+bool menu::exclusive_input_pressed(int &iptkey, int key, int repeat)
{
- if (m_event.iptkey == IPT_INVALID && machine().ui_input().pressed_repeat(key, repeat))
+ if ((iptkey == IPT_INVALID) && machine().ui_input().pressed_repeat(key, repeat))
{
- m_event.iptkey = key;
+ iptkey = key;
return true;
}
- return false;
+ else
+ {
+ return false;
+ }
}
@@ -129,6 +86,104 @@ inline bool menu::exclusive_input_pressed(int key, int repeat)
CORE SYSTEM MANAGEMENT
***************************************************************************/
+menu::global_state::global_state(running_machine &machine, ui_options const &options)
+ : m_machine(machine)
+ , m_cleanup_callbacks()
+ , m_bgrnd_bitmap()
+ , m_bgrnd_texture()
+ , m_stack()
+ , m_free()
+{
+ render_manager &render(machine.render());
+ auto const texture_free([&render](render_texture *texture) { render.texture_free(texture); });
+
+ // create a texture for arrow icons
+ m_arrow_texture = texture_ptr(render.texture_alloc(render_triangle), texture_free);
+
+ // create a texture for main menu background
+ m_bgrnd_texture = texture_ptr(render.texture_alloc(render_texture::hq_scale), texture_free);
+ if (options.use_background_image() && (&machine.system() == &GAME_NAME(___empty)))
+ {
+ m_bgrnd_bitmap = std::make_unique<bitmap_argb32>(0, 0);
+ emu_file backgroundfile(".", OPEN_FLAG_READ);
+ render_load_jpeg(*m_bgrnd_bitmap, backgroundfile, nullptr, "background.jpg");
+
+ if (!m_bgrnd_bitmap->valid())
+ render_load_png(*m_bgrnd_bitmap, backgroundfile, nullptr, "background.png");
+
+ if (m_bgrnd_bitmap->valid())
+ m_bgrnd_texture->set_bitmap(*m_bgrnd_bitmap, m_bgrnd_bitmap->cliprect(), TEXFORMAT_ARGB32);
+ else
+ m_bgrnd_bitmap->reset();
+ }
+}
+
+
+menu::global_state::~global_state()
+{
+ stack_reset();
+ clear_free_list();
+
+ for (auto const &callback : m_cleanup_callbacks)
+ callback(m_machine);
+}
+
+
+void menu::global_state::add_cleanup_callback(cleanup_callback &&callback)
+{
+ m_cleanup_callbacks.emplace_back(std::move(callback));
+}
+
+
+void menu::global_state::stack_push(std::unique_ptr<menu> &&menu)
+{
+ menu->m_parent = std::move(m_stack);
+ m_stack = std::move(menu);
+ m_stack->reset(reset_options::SELECT_FIRST);
+ m_stack->machine().ui_input().reset();
+}
+
+
+void menu::global_state::stack_pop()
+{
+ if (m_stack)
+ {
+ std::unique_ptr<menu> menu(std::move(m_stack));
+ m_stack = std::move(menu->m_parent);
+ menu->m_parent = std::move(m_free);
+ m_free = std::move(menu);
+ m_machine.ui_input().reset();
+ }
+}
+
+
+void menu::global_state::stack_reset()
+{
+ while (m_stack)
+ stack_pop();
+}
+
+
+void menu::global_state::clear_free_list()
+{
+ while (m_free)
+ m_free = std::move(m_free->m_parent);
+}
+
+
+bool menu::global_state::stack_has_special_main_menu() const
+{
+ for (auto menu = m_stack.get(); menu != nullptr; menu = menu->m_parent.get())
+ {
+ if (menu->is_special_main_menu())
+ return true;
+ }
+ return false;
+}
+
+
+
+
//-------------------------------------------------
// init - initialize the menu system
//-------------------------------------------------
@@ -136,7 +191,14 @@ inline bool menu::exclusive_input_pressed(int key, int repeat)
void menu::init(running_machine &machine, ui_options &mopt)
{
// initialize the menu stack
- menu::stack_reset(machine);
+ {
+ std::lock_guard<std::mutex> guard(s_global_state_guard);
+ auto const ins(s_global_states.emplace(&machine, std::make_shared<global_state>(machine, mopt)));
+ if (ins.second)
+ machine.add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(FUNC(menu::exit), &machine)); // add an exit callback to free memory
+ else
+ ins.first->second->stack_reset();
+ }
// create a texture for hilighting items
hilight_bitmap = std::make_unique<bitmap_rgb32>(256, 1);
@@ -150,14 +212,8 @@ void menu::init(running_machine &machine, ui_options &mopt)
hilight_texture = machine.render().texture_alloc();
hilight_texture->set_bitmap(*hilight_bitmap, hilight_bitmap->cliprect(), TEXFORMAT_ARGB32);
- // create a texture for arrow icons
- arrow_texture = machine.render().texture_alloc(render_triangle);
-
// initialize ui
init_ui(machine, mopt);
-
- // add an exit callback to free memory
- machine.add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(FUNC(menu::exit), &machine));
}
@@ -168,31 +224,16 @@ void menu::init(running_machine &machine, ui_options &mopt)
void menu::exit(running_machine &machine)
{
// free menus
- menu::stack_reset(machine);
- menu::clear_free_list(machine);
+ {
+ std::lock_guard<std::mutex> guard(s_global_state_guard);
+ s_global_states.erase(&machine);
+ }
// free textures
render_manager &mre = machine.render();
mre.texture_free(hilight_texture);
- mre.texture_free(arrow_texture);
mre.texture_free(snapx_texture);
mre.texture_free(hilight_main_texture);
- mre.texture_free(bgrnd_texture);
- mre.texture_free(star_texture);
-
- for (auto & elem : icons_texture)
- mre.texture_free(elem);
-
- for (int i = 0; i < UI_TOOLBAR_BUTTONS; ++i)
- {
- mre.texture_free(sw_toolbar_texture[i]);
- mre.texture_free(toolbar_texture[i]);
- }
-
- icons_bitmap.clear();
- sw_toolbar_bitmap.clear();
- toolbar_bitmap.clear();
- m_old_icons.clear();
}
@@ -206,16 +247,14 @@ void menu::exit(running_machine &machine)
//-------------------------------------------------
menu::menu(mame_ui_manager &mui, render_container *_container)
- : m_special_main_menu(false)
+ : m_visible_lines(0)
+ , m_visible_items(0)
+ , m_global_state(get_global_state(mui.machine()))
+ , m_special_main_menu(false)
, m_ui(mui)
, m_parent()
- , m_pressed(false)
- , m_repeat(0)
, m_event()
, m_pool(nullptr)
- , m_focus(focused_menu::main)
- , m_visible_lines(0)
- , m_visible_items(0)
, m_resetpos(0)
, m_resetref(nullptr)
{
@@ -275,12 +314,12 @@ void menu::reset(reset_options options)
if (machine().options().ui() == emu_options::UI_SIMPLE)
item_append(_("Exit"), "", 0, nullptr);
else
- item_append(_("Exit"), "", FLAG_UI | FLAG_LEFT_ARROW | FLAG_RIGHT_ARROW, nullptr);
+ item_append(_("Exit"), "", FLAG_LEFT_ARROW | FLAG_RIGHT_ARROW, nullptr);
}
else
{
- if (machine().options().ui() != emu_options::UI_SIMPLE && menu::stack_has_special_main_menu())
- item_append(_("Return to Previous Menu"), "", FLAG_UI | FLAG_LEFT_ARROW | FLAG_RIGHT_ARROW, nullptr);
+ if (machine().options().ui() != emu_options::UI_SIMPLE && stack_has_special_main_menu())
+ item_append(_("Return to Previous Menu"), "", FLAG_LEFT_ARROW | FLAG_RIGHT_ARROW, nullptr);
else
item_append(_("Return to Previous Menu"), "", 0, nullptr);
}
@@ -398,32 +437,20 @@ const menu::event *menu::process(UINT32 flags, float x0, float y0)
// draw the menu
if (item.size() > 1 && (item[0].flags & FLAG_MULTILINE) != 0)
draw_text_box();
- else if ((item[0].flags & FLAG_UI) != 0 || (item[0].flags & FLAG_UI_SWLIST) != 0)
- draw_select_game((flags & PROCESS_NOINPUT));
else if ((item[0].flags & FLAG_UI_PALETTE) != 0)
draw_palette_menu();
- else if ((item[0].flags & FLAG_UI_DATS) != 0)
- draw_dats_menu();
else
- draw(flags, x0, y0);
+ draw(flags);
// process input
if (!(flags & PROCESS_NOKEYS) && !(flags & PROCESS_NOINPUT))
{
// read events
- if ((item[0].flags & FLAG_UI ) != 0 || (item[0].flags & FLAG_UI_SWLIST ) != 0)
- handle_main_events();
- else
- handle_events(flags);
+ handle_events(flags, m_event);
// handle the keys if we don't already have an event
if (m_event.iptkey == IPT_INVALID)
- {
- if ((item[0].flags & FLAG_UI) != 0 || (item[0].flags & FLAG_UI_SWLIST) != 0)
- handle_main_keys(flags);
- else
- handle_keys(flags);
- }
+ handle_keys(flags, m_event.iptkey);
}
// update the selected item in the event
@@ -497,7 +524,7 @@ void menu::set_selection(void *selected_itemref)
// draw - draw a menu
//-------------------------------------------------
-void menu::draw(UINT32 flags, float origx0, float origy0)
+void menu::draw(UINT32 flags)
{
// first draw the FPS counter
if (ui().show_fps_counter())
@@ -514,8 +541,8 @@ void menu::draw(UINT32 flags, float origx0, float origy0)
float const ud_arrow_width = line_height * machine().render().ui_aspect();
float const gutter_width = lr_arrow_width * 1.3f;
- if (ui().options().use_background_image() && &machine().system() == &GAME_NAME(___empty) && bgrnd_bitmap->valid() && !noimage)
- container->add_quad(0.0f, 0.0f, 1.0f, 1.0f, rgb_t::white, bgrnd_texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+ if (&machine().system() == &GAME_NAME(___empty) && !noimage)
+ draw_background();
// compute the width and height of the full menu
float visible_width = 0;
@@ -850,7 +877,7 @@ void menu::draw_text_box()
// input events for a menu
//-------------------------------------------------
-void menu::handle_events(UINT32 flags)
+void menu::handle_events(UINT32 flags, event &ev)
{
bool stop = false;
ui_event local_menu_event;
@@ -901,11 +928,11 @@ void menu::handle_events(UINT32 flags)
if (!(flags & PROCESS_ONLYCHAR) && hover >= 0 && hover < item.size())
{
selected = hover;
- m_event.iptkey = IPT_UI_SELECT;
+ ev.iptkey = IPT_UI_SELECT;
if (is_last_selected())
{
- m_event.iptkey = IPT_UI_CANCEL;
- menu::stack_pop(machine());
+ ev.iptkey = IPT_UI_CANCEL;
+ stack_pop();
}
stop = true;
}
@@ -946,8 +973,8 @@ void menu::handle_events(UINT32 flags)
// translate CHAR events into specials
case UI_EVENT_CHAR:
- m_event.iptkey = IPT_SPECIAL;
- m_event.unichar = local_menu_event.ch;
+ ev.iptkey = IPT_SPECIAL;
+ ev.unichar = local_menu_event.ch;
stop = true;
break;
@@ -964,9 +991,9 @@ void menu::handle_events(UINT32 flags)
// keys for a menu
//-------------------------------------------------
-void menu::handle_keys(UINT32 flags)
+void menu::handle_keys(UINT32 flags, int &iptkey)
{
- bool ignorepause = menu::stack_has_special_main_menu();
+ bool ignorepause = stack_has_special_main_menu();
int code;
// bail if no items
@@ -974,12 +1001,12 @@ void menu::handle_keys(UINT32 flags)
return;
// if we hit select, return TRUE or pop the stack, depending on the item
- if (exclusive_input_pressed(IPT_UI_SELECT, 0))
+ if (exclusive_input_pressed(iptkey, IPT_UI_SELECT, 0))
{
if (is_last_selected())
{
- m_event.iptkey = IPT_UI_CANCEL;
- menu::stack_pop(machine());
+ iptkey = IPT_UI_CANCEL;
+ stack_pop();
}
return;
}
@@ -989,10 +1016,10 @@ void menu::handle_keys(UINT32 flags)
return;
// hitting cancel also pops the stack
- if (exclusive_input_pressed(IPT_UI_CANCEL, 0))
+ if (exclusive_input_pressed(iptkey, IPT_UI_CANCEL, 0))
{
if (!menu_has_search_active())
- menu::stack_pop(machine());
+ stack_pop();
return;
}
@@ -1007,13 +1034,13 @@ void menu::handle_keys(UINT32 flags)
ignoreleft = ignoreright = false;
// accept left/right keys as-is with repeat
- if (!ignoreleft && exclusive_input_pressed(IPT_UI_LEFT, (flags & PROCESS_LR_REPEAT) ? 6 : 0))
+ if (!ignoreleft && exclusive_input_pressed(iptkey, IPT_UI_LEFT, (flags & PROCESS_LR_REPEAT) ? 6 : 0))
return;
- if (!ignoreright && exclusive_input_pressed(IPT_UI_RIGHT, (flags & PROCESS_LR_REPEAT) ? 6 : 0))
+ if (!ignoreright && exclusive_input_pressed(iptkey, IPT_UI_RIGHT, (flags & PROCESS_LR_REPEAT) ? 6 : 0))
return;
// up backs up by one item
- if (exclusive_input_pressed(IPT_UI_UP, 6))
+ if (exclusive_input_pressed(iptkey, IPT_UI_UP, 6))
{
if ((item[0].flags & FLAG_UI_DATS))
{
@@ -1028,7 +1055,7 @@ void menu::handle_keys(UINT32 flags)
}
// down advances by one item
- if (exclusive_input_pressed(IPT_UI_DOWN, 6))
+ if (exclusive_input_pressed(iptkey, IPT_UI_DOWN, 6))
{
if ((item[0].flags & FLAG_UI_DATS))
{
@@ -1043,7 +1070,7 @@ void menu::handle_keys(UINT32 flags)
}
// page up backs up by m_visible_items
- if (exclusive_input_pressed(IPT_UI_PAGE_UP, 6))
+ if (exclusive_input_pressed(iptkey, IPT_UI_PAGE_UP, 6))
{
selected -= m_visible_items;
top_line -= m_visible_items - (last_item_visible() ? 1 : 0);
@@ -1053,7 +1080,7 @@ void menu::handle_keys(UINT32 flags)
}
// page down advances by m_visible_items
- if (exclusive_input_pressed(IPT_UI_PAGE_DOWN, 6))
+ if (exclusive_input_pressed(iptkey, IPT_UI_PAGE_DOWN, 6))
{
selected += m_visible_lines - 2 + (selected == 0);
top_line += m_visible_lines - 2;
@@ -1064,21 +1091,21 @@ void menu::handle_keys(UINT32 flags)
}
// home goes to the start
- if (exclusive_input_pressed(IPT_UI_HOME, 0))
+ if (exclusive_input_pressed(iptkey, IPT_UI_HOME, 0))
{
selected = top_line = 0;
validate_selection(1);
}
// end goes to the last
- if (exclusive_input_pressed(IPT_UI_END, 0))
+ if (exclusive_input_pressed(iptkey, IPT_UI_END, 0))
{
selected = top_line = item.size() - 1;
validate_selection(-1);
}
// pause enables/disables pause
- if (!ignorepause && exclusive_input_pressed(IPT_UI_PAUSE, 0))
+ if (!ignorepause && exclusive_input_pressed(iptkey, IPT_UI_PAUSE, 0))
{
if (machine().paused())
machine().resume();
@@ -1091,14 +1118,16 @@ void menu::handle_keys(UINT32 flags)
mame_machine_manager::instance()->cheat().set_enable(!mame_machine_manager::instance()->cheat().enabled());
// see if any other UI keys are pressed
- if (m_event.iptkey == IPT_INVALID)
+ if (iptkey == IPT_INVALID)
+ {
for (code = IPT_UI_FIRST + 1; code < IPT_UI_LAST; code++)
{
if (code == IPT_UI_CONFIGURE || (code == IPT_UI_LEFT && ignoreleft) || (code == IPT_UI_RIGHT && ignoreright) || (code == IPT_UI_PAUSE && ignorepause))
continue;
- if (exclusive_input_pressed(code, 0))
+ if (exclusive_input_pressed(iptkey, code, 0))
break;
}
+ }
}
@@ -1123,82 +1152,13 @@ void menu::validate_selection(int scandir)
-//-------------------------------------------------
-// clear_free_list - clear out anything
-// accumulated in the free list
-//-------------------------------------------------
-
-void menu::clear_free_list(running_machine &machine)
-{
- while (menu_free)
- menu_free = std::move(menu_free->m_parent);
-}
-
-
-
/***************************************************************************
MENU STACK MANAGEMENT
***************************************************************************/
-//-------------------------------------------------
-// menu::stack_reset - reset the menu stack
-//-------------------------------------------------
-
-void menu::stack_reset(running_machine &machine)
-{
- while (menu_stack)
- menu::stack_pop(machine);
-}
-
-
-//-------------------------------------------------
-// stack_push - push a new menu onto the
-// stack
-//-------------------------------------------------
-
-void menu::stack_push(std::unique_ptr<menu> &&menu)
-{
- menu->m_parent = std::move(menu_stack);
- menu_stack = std::move(menu);
- menu_stack->reset(reset_options::SELECT_FIRST);
- menu_stack->machine().ui_input().reset();
-}
-
-
-//-------------------------------------------------
-// stack_pop - pop a menu from the stack
-//-------------------------------------------------
-
-void menu::stack_pop(running_machine &machine)
-{
- if (menu_stack)
- {
- std::unique_ptr<menu> menu(std::move(menu_stack));
- menu_stack = std::move(menu->m_parent);
- menu->m_parent = std::move(menu_free);
- menu_free = std::move(menu);
- machine.ui_input().reset();
- }
-}
-
-
-//-------------------------------------------------
-// menu::stack_has_special_main_menu -
-// check in the special main menu is in the stack
-//-------------------------------------------------
-
-bool menu::stack_has_special_main_menu()
-{
- for (auto menu = menu_stack.get(); menu != nullptr; menu = menu->m_parent.get())
- if (menu->is_special_main_menu())
- return true;
-
- return false;
-}
-
void menu::do_handle()
{
- if(item.size() < 2)
+ if (item.size() < 2)
populate();
handle();
}
@@ -1215,19 +1175,21 @@ void menu::do_handle()
UINT32 menu::ui_handler(render_container *container, mame_ui_manager &mui)
{
+ global_state_ptr const state(get_global_state(mui.machine()));
+
// if we have no menus stacked up, start with the main menu
- if (!menu_stack)
- stack_push(std::unique_ptr<menu>(global_alloc_clear<menu_main>(mui, container)));
+ if (!state->topmost_menu<menu>())
+ state->stack_push(std::unique_ptr<menu>(global_alloc_clear<menu_main>(mui, container)));
// update the menu state
- if (menu_stack)
- menu_stack->do_handle();
+ if (state->topmost_menu<menu>())
+ state->topmost_menu<menu>()->do_handle();
// clear up anything pending to be released
- clear_free_list(mui.machine());
+ state->clear_free_list();
// if the menus are to be hidden, return a cancel here
- if (mui.is_menu_active() && ((mui.machine().ui_input().pressed(IPT_UI_CONFIGURE) && !stack_has_special_main_menu()) || menu_stack == nullptr))
+ if (mui.is_menu_active() && ((mui.machine().ui_input().pressed(IPT_UI_CONFIGURE) && !state->stack_has_special_main_menu()) || !state->topmost_menu<menu>()))
return UI_HANDLER_CANCEL;
return 0;
@@ -1308,7 +1270,7 @@ void menu::highlight(render_container *container, float x0, float y0, float x1,
void menu::draw_arrow(render_container *container, float x0, float y0, float x1, float y1, rgb_t fgcolor, UINT32 orientation)
{
- container->add_quad(x0, y0, x1, y1, fgcolor, arrow_texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXORIENT(orientation) | PRIMFLAG_PACKABLE);
+ container->add_quad(x0, y0, x1, y1, fgcolor, m_global_state->arrow_texture(), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXORIENT(orientation) | PRIMFLAG_PACKABLE);
}
//-------------------------------------------------
@@ -1336,1037 +1298,8 @@ void menu::init_ui(running_machine &machine, ui_options &mopt)
// create a texture for snapshot
snapx_bitmap = std::make_unique<bitmap_argb32>(0, 0);
snapx_texture = mrender.texture_alloc(render_texture::hq_scale);
-
- // allocates and sets the default "no available" image
- no_avail_bitmap = std::make_unique<bitmap_argb32>(256, 256);
- UINT32 *dst = &no_avail_bitmap->pix32(0);
- memcpy(dst, no_avail_bmp, 256 * 256 * sizeof(UINT32));
-
- // allocates and sets the favorites star image
- star_bitmap = std::make_unique<bitmap_argb32>(32, 32);
- dst = &star_bitmap->pix32(0);
- memcpy(dst, favorite_star_bmp, 32 * 32 * sizeof(UINT32));
- star_texture = mrender.texture_alloc();
- star_texture->set_bitmap(*star_bitmap, star_bitmap->cliprect(), TEXFORMAT_ARGB32);
-
- // allocate icons
- for (auto & icons : icons_texture)
- {
- m_old_icons.emplace_back(nullptr);
- icons_bitmap.emplace_back(std::make_unique<bitmap_argb32>());
- icons = mrender.texture_alloc();
- }
-
- // create a texture for main menu background
- bgrnd_bitmap = std::make_unique<bitmap_argb32>(0, 0);
- bgrnd_texture = mrender.texture_alloc(render_texture::hq_scale);
-
- if (mopt.use_background_image() && &machine.system() == &GAME_NAME(___empty))
- {
- emu_file backgroundfile(".", OPEN_FLAG_READ);
- render_load_jpeg(*bgrnd_bitmap, backgroundfile, nullptr, "background.jpg");
-
- if (!bgrnd_bitmap->valid())
- render_load_png(*bgrnd_bitmap, backgroundfile, nullptr, "background.png");
-
- if (bgrnd_bitmap->valid())
- bgrnd_texture->set_bitmap(*bgrnd_bitmap, bgrnd_bitmap->cliprect(), TEXFORMAT_ARGB32);
- else
- bgrnd_bitmap->reset();
- }
- else
- bgrnd_bitmap->reset();
-
- // create a texture for toolbar
- for (int x = 0; x < UI_TOOLBAR_BUTTONS; ++x)
- {
- toolbar_bitmap.emplace_back(std::make_shared<bitmap_argb32>(32, 32));
- sw_toolbar_bitmap.emplace_back(std::make_shared<bitmap_argb32>(32, 32));
- toolbar_texture[x] = mrender.texture_alloc();
- sw_toolbar_texture[x] = mrender.texture_alloc();
- UINT32 *texture_dst = &toolbar_bitmap.back()->pix32(0);
- memcpy(texture_dst, toolbar_bitmap_bmp[x], 32 * 32 * sizeof(UINT32));
- if (toolbar_bitmap.back()->valid())
- toolbar_texture[x]->set_bitmap(*toolbar_bitmap.back(), toolbar_bitmap.back()->cliprect(), TEXFORMAT_ARGB32);
- else
- toolbar_bitmap.back()->reset();
-
- if (x == 0 || x == 2)
- {
- texture_dst = &sw_toolbar_bitmap[x]->pix32(0);
- memcpy(texture_dst, toolbar_bitmap_bmp[x], 32 * 32 * sizeof(UINT32));
- if (sw_toolbar_bitmap.back()->valid())
- sw_toolbar_texture[x]->set_bitmap(*sw_toolbar_bitmap.back(), sw_toolbar_bitmap.back()->cliprect(), TEXFORMAT_ARGB32);
- else
- sw_toolbar_bitmap.back()->reset();
- }
- else
- sw_toolbar_bitmap.back()->reset();
-
- }
-}
-
-
-//-------------------------------------------------
-// draw main menu
-//-------------------------------------------------
-
-void menu::draw_select_game(UINT32 flags)
-{
- bool noinput = (flags & PROCESS_NOINPUT);
- float line_height = ui().get_line_height();
- float ud_arrow_width = line_height * machine().render().ui_aspect();
- float gutter_width = 0.52f * ud_arrow_width;
- mouse_x = -1, mouse_y = -1;
- float right_panel_size = (ui_globals::panels_status == HIDE_BOTH || ui_globals::panels_status == HIDE_RIGHT_PANEL) ? 2.0f * UI_BOX_LR_BORDER : 0.3f;
- float visible_width = 1.0f - 4.0f * UI_BOX_LR_BORDER;
- float primary_left = (1.0f - visible_width) * 0.5f;
- float primary_width = visible_width;
- bool is_swlist = (item[0].flags & FLAG_UI_SWLIST);
-
- // draw background image if available
- if (ui().options().use_background_image() && bgrnd_bitmap->valid())
- container->add_quad(0.0f, 0.0f, 1.0f, 1.0f, rgb_t::white, bgrnd_texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
-
- hover = item.size() + 1;
- visible_items = (is_swlist) ? item.size() - 2 : item.size() - 2 - skip_main_items;
- float extra_height = (is_swlist) ? 2.0f * line_height : (2.0f + skip_main_items) * line_height;
- float visible_extra_menu_height = customtop + custombottom + extra_height;
-
- // locate mouse
- mouse_hit = false;
- mouse_button = false;
- if (!noinput)
- {
- mouse_target = machine().ui_input().find_mouse(&mouse_target_x, &mouse_target_y, &mouse_button);
- if (mouse_target)
- if (mouse_target->map_point_container(mouse_target_x, mouse_target_y, *container, mouse_x, mouse_y))
- mouse_hit = true;
- }
-
- // account for extra space at the top and bottom
- float visible_main_menu_height = 1.0f - 2.0f * UI_BOX_TB_BORDER - visible_extra_menu_height;
- m_visible_lines = int(std::trunc(visible_main_menu_height / line_height));
- visible_main_menu_height = float(m_visible_lines) * line_height;
-
- if (!is_swlist)
- ui_globals::visible_main_lines = m_visible_lines;
- else
- ui_globals::visible_sw_lines = m_visible_lines;
-
- // compute top/left of inner menu area by centering
- float visible_left = primary_left;
- float visible_top = (1.0f - (visible_main_menu_height + visible_extra_menu_height)) * 0.5f;
-
- // if the menu is at the bottom of the extra, adjust
- visible_top += customtop;
-
- // compute left box size
- float x1 = visible_left - UI_BOX_LR_BORDER;
- float y1 = visible_top - UI_BOX_TB_BORDER;
- float x2 = x1 + 2.0f * UI_BOX_LR_BORDER;
- float y2 = visible_top + visible_main_menu_height + UI_BOX_TB_BORDER + extra_height;
-
- // add left box
- visible_left = draw_left_panel(x1, y1, x2, y2);
- visible_width -= right_panel_size + visible_left - 2.0f * UI_BOX_LR_BORDER;
-
- // compute and add main box
- x1 = visible_left - UI_BOX_LR_BORDER;
- x2 = visible_left + visible_width + UI_BOX_LR_BORDER;
- float line = visible_top + (float(m_visible_lines) * line_height);
- ui().draw_outlined_box(container, x1, y1, x2, y2, UI_BACKGROUND_COLOR);
-
- if (visible_items < m_visible_lines)
- m_visible_lines = visible_items;
- if (top_line < 0 || is_first_selected())
- top_line = 0;
- if (selected < visible_items && top_line + m_visible_lines >= visible_items)
- top_line = visible_items - m_visible_lines;
-
- // 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;
-
- if (m_prev_selected != nullptr && m_focus == focused_menu::main && selected < visible_items)
- m_prev_selected = nullptr;
-
- int const n_loop = (std::min)(m_visible_lines, visible_items);
- for (int linenum = 0; linenum < n_loop; linenum++)
- {
- float line_y = visible_top + (float)linenum * line_height;
- int itemnum = top_line + linenum;
- const menu_item &pitem = item[itemnum];
- const char *itemtext = pitem.text.c_str();
- rgb_t fgcolor = UI_TEXT_COLOR;
- rgb_t bgcolor = UI_TEXT_BG_COLOR;
- rgb_t fgcolor3 = UI_CLONE_COLOR;
- float line_x0 = x1 + 0.5f * UI_LINE_WIDTH;
- float line_y0 = line_y;
- float line_x1 = x2 - 0.5f * UI_LINE_WIDTH;
- float line_y1 = line_y + line_height;
-
- // set the hover if this is our item
- if (mouse_hit && line_x0 <= mouse_x && line_x1 > mouse_x && line_y0 <= mouse_y && line_y1 > mouse_y && is_selectable(pitem))
- hover = itemnum;
-
- // if we're selected, draw with a different background
- if (itemnum == selected && m_focus == focused_menu::main)
- {
- fgcolor = rgb_t(0xff, 0xff, 0x00);
- bgcolor = rgb_t(0xff, 0xff, 0xff);
- fgcolor3 = rgb_t(0xcc, 0xcc, 0x00);
- ui().draw_textured_box(container, line_x0 + 0.01f, line_y0, line_x1 - 0.01f, line_y1, bgcolor, rgb_t(43, 43, 43),
- hilight_main_texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXWRAP(TRUE));
- }
- // else if the mouse is over this item, draw with a different background
- else if (itemnum == hover)
- {
- fgcolor = fgcolor3 = UI_MOUSEOVER_COLOR;
- bgcolor = UI_MOUSEOVER_BG_COLOR;
- highlight(container, line_x0, line_y0, line_x1, line_y1, bgcolor);
- }
- else if (pitem.ref == m_prev_selected)
- {
- fgcolor = fgcolor3 = UI_MOUSEOVER_COLOR;
- bgcolor = UI_MOUSEOVER_BG_COLOR;
- ui().draw_textured_box(container, line_x0 + 0.01f, line_y0, line_x1 - 0.01f, line_y1, bgcolor, rgb_t(43, 43, 43),
- hilight_main_texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXWRAP(TRUE));
- }
-
- if (linenum == 0 && top_line != 0)
- {
- // if we're on the top line, display the up arrow
- draw_arrow(container, 0.5f * (x1 + x2) - 0.5f * ud_arrow_width, line_y + 0.25f * line_height,
- 0.5f * (x1 + x2) + 0.5f * ud_arrow_width, line_y + 0.75f * line_height, fgcolor, ROT0);
-
- if (hover == itemnum)
- hover = HOVER_ARROW_UP;
- }
- else if (linenum == m_visible_lines - 1 && itemnum != visible_items - 1)
- {
- // if we're on the bottom line, display the down arrow
- draw_arrow(container, 0.5f * (x1 + x2) - 0.5f * ud_arrow_width, line_y + 0.25f * line_height,
- 0.5f * (x1 + x2) + 0.5f * ud_arrow_width, line_y + 0.75f * line_height, fgcolor, ROT0 ^ ORIENTATION_FLIP_Y);
-
- if (hover == itemnum)
- hover = HOVER_ARROW_DOWN;
- }
- else if (pitem.type == menu_item_type::SEPARATOR)
- {
- // if we're just a divider, draw a line
- container->add_line(visible_left, line_y + 0.5f * line_height, visible_left + visible_width, line_y + 0.5f * line_height,
- UI_LINE_WIDTH, UI_TEXT_COLOR, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
- }
- else if (pitem.subtext.empty())
- {
- // draw the item centered
- int item_invert = pitem.flags & FLAG_INVERT;
- auto icon = draw_icon(linenum, item[itemnum].ref, effective_left, line_y);
- ui().draw_text_full(container, itemtext, effective_left + icon, line_y, effective_width - icon, ui::text_layout::LEFT, ui::text_layout::TRUNCATE,
- mame_ui_manager::NORMAL, item_invert ? fgcolor3 : fgcolor, bgcolor, nullptr, nullptr);
- }
- else
- {
- auto item_invert = pitem.flags & FLAG_INVERT;
- const char *subitem_text = pitem.subtext.c_str();
- float item_width, subitem_width;
-
- // compute right space for subitem
- ui().draw_text_full(container, subitem_text, effective_left, line_y, ui().get_string_width(pitem.subtext.c_str()),
- ui::text_layout::RIGHT, ui::text_layout::NEVER, mame_ui_manager::NONE, item_invert ? fgcolor3 : fgcolor, bgcolor, &subitem_width, nullptr);
- subitem_width += gutter_width;
-
- // draw the item left-justified
- ui().draw_text_full(container, itemtext, effective_left, line_y, effective_width - subitem_width,
- ui::text_layout::LEFT, ui::text_layout::TRUNCATE, mame_ui_manager::NORMAL, item_invert ? fgcolor3 : fgcolor, bgcolor, &item_width, nullptr);
-
- // draw the subitem right-justified
- ui().draw_text_full(container, subitem_text, effective_left + item_width, line_y, effective_width - item_width,
- ui::text_layout::RIGHT, ui::text_layout::NEVER, mame_ui_manager::NORMAL, item_invert ? fgcolor3 : fgcolor, bgcolor, nullptr, nullptr);
- }
- }
-
- for (size_t count = visible_items; count < item.size(); count++)
- {
- const menu_item &pitem = item[count];
- const char *itemtext = pitem.text.c_str();
- float line_x0 = x1 + 0.5f * UI_LINE_WIDTH;
- float line_y0 = line;
- float line_x1 = x2 - 0.5f * UI_LINE_WIDTH;
- float line_y1 = line + line_height;
- rgb_t fgcolor = UI_TEXT_COLOR;
- rgb_t bgcolor = UI_TEXT_BG_COLOR;
-
- if (mouse_hit && line_x0 <= mouse_x && line_x1 > mouse_x && line_y0 <= mouse_y && line_y1 > mouse_y && is_selectable(pitem))
- hover = count;
-
- // if we're selected, draw with a different background
- if (count == selected && m_focus == focused_menu::main)
- {
- fgcolor = rgb_t(0xff, 0xff, 0x00);
- bgcolor = rgb_t(0xff, 0xff, 0xff);
- ui().draw_textured_box(container, line_x0 + 0.01f, line_y0, line_x1 - 0.01f, line_y1, bgcolor, rgb_t(43, 43, 43),
- hilight_main_texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXWRAP(TRUE));
- }
- // else if the mouse is over this item, draw with a different background
- else if (count == hover)
- {
- fgcolor = UI_MOUSEOVER_COLOR;
- bgcolor = UI_MOUSEOVER_BG_COLOR;
- highlight(container, line_x0, line_y0, line_x1, line_y1, bgcolor);
- }
-
- if (pitem.type == menu_item_type::SEPARATOR)
- container->add_line(visible_left, line + 0.5f * line_height, visible_left + visible_width, line + 0.5f * line_height,
- UI_LINE_WIDTH, UI_TEXT_COLOR, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
- else
- ui().draw_text_full(container, itemtext, effective_left, line, effective_width, ui::text_layout::CENTER, ui::text_layout::TRUNCATE,
- mame_ui_manager::NORMAL, fgcolor, bgcolor, nullptr, nullptr);
- line += line_height;
- }
-
- x1 = x2;
- x2 += right_panel_size;
-
- draw_right_panel(get_selection_ref(), x1, y1, x2, y2);
-
- x1 = primary_left - UI_BOX_LR_BORDER;
- x2 = primary_left + primary_width + UI_BOX_LR_BORDER;
-
- // if there is something special to add, do it by calling the virtual method
- custom_render(get_selection_ref(), customtop, custombottom, x1, y1, x2, y2);
-
- // return the number of visible lines, minus 1 for top arrow and 1 for bottom arrow
- m_visible_items = m_visible_lines - (top_line != 0) - (top_line + m_visible_lines != visible_items);
-
- // reset redraw icon stage
- if (!is_swlist) ui_globals::redraw_icon = false;
-
- // noinput
- if (noinput)
- {
- int alpha = (1.0f - machine().options().pause_brightness()) * 255.0f;
- if (alpha > 255)
- alpha = 255;
- if (alpha >= 0)
- container->add_rect(0.0f, 0.0f, 1.0f, 1.0f, rgb_t(alpha, 0x00, 0x00, 0x00), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
- }
-}
-
-//-------------------------------------------------
-// get title and search path for right panel
-//-------------------------------------------------
-
-void menu::get_title_search(std::string &snaptext, std::string &searchstr)
-{
- // get arts title text
- snaptext.assign(_(arts_info[ui_globals::curimage_view].first));
-
- // get search path
- std::string addpath;
- if (ui_globals::curimage_view == SNAPSHOT_VIEW)
- {
- emu_options moptions;
- searchstr = machine().options().value(arts_info[ui_globals::curimage_view].second);
- addpath = moptions.value(arts_info[ui_globals::curimage_view].second);
- }
- else
- {
- ui_options moptions;
- searchstr = ui().options().value(arts_info[ui_globals::curimage_view].second);
- addpath = moptions.value(arts_info[ui_globals::curimage_view].second);
- }
-
- std::string tmp(searchstr);
- path_iterator path(tmp.c_str());
- path_iterator path_iter(addpath.c_str());
- std::string c_path, curpath;
-
- // iterate over path and add path for zipped formats
- while (path.next(curpath))
- {
- path_iter.reset();
- while (path_iter.next(c_path))
- searchstr.append(";").append(curpath).append(PATH_SEPARATOR).append(c_path);
- }
-}
-
-//-------------------------------------------------
-// handle keys for main menu
-//-------------------------------------------------
-
-void menu::handle_main_keys(UINT32 flags)
-{
- auto ignorepause = menu::stack_has_special_main_menu();
-
- // bail if no items
- if (item.size() == 0)
- return;
-
- // if we hit select, return TRUE or pop the stack, depending on the item
- if (exclusive_input_pressed(IPT_UI_SELECT, 0))
- {
- if (is_last_selected() && m_focus == focused_menu::main)
- {
- m_event.iptkey = IPT_UI_CANCEL;
- menu::stack_pop(machine());
- }
- return;
- }
-
- // hitting cancel also pops the stack
- if (exclusive_input_pressed(IPT_UI_CANCEL, 0))
- {
- if (!ui_error && !menu_has_search_active())
- menu::stack_pop(machine());
- return;
- }
-
- // validate the current selection
- validate_selection(1);
-
- // swallow left/right keys if they are not appropriate
- bool ignoreleft = ((item[selected].flags & FLAG_LEFT_ARROW) == 0);
- bool ignoreright = ((item[selected].flags & FLAG_RIGHT_ARROW) == 0);
- bool leftclose = (ui_globals::panels_status == HIDE_BOTH || ui_globals::panels_status == HIDE_LEFT_PANEL);
- bool rightclose = (ui_globals::panels_status == HIDE_BOTH || ui_globals::panels_status == HIDE_RIGHT_PANEL);
-
- // accept left/right keys as-is with repeat
- if (!ignoreleft && exclusive_input_pressed(IPT_UI_LEFT, (flags & PROCESS_LR_REPEAT) ? 6 : 0))
- {
- // Swap the right panel
- if (m_focus == focused_menu::righttop)
- m_event.iptkey = IPT_UI_LEFT_PANEL;
- return;
- }
-
- if (!ignoreright && exclusive_input_pressed(IPT_UI_RIGHT, (flags & PROCESS_LR_REPEAT) ? 6 : 0))
- {
- // Swap the right panel
- if (m_focus == focused_menu::righttop)
- m_event.iptkey = IPT_UI_RIGHT_PANEL;
- return;
- }
-
- // up backs up by one item
- if (exclusive_input_pressed(IPT_UI_UP, 6))
- {
- // Filter
- if (!leftclose && m_focus == focused_menu::left)
- {
- m_event.iptkey = IPT_UI_UP_FILTER;
- return;
- }
-
- // Infos
- if (!rightclose && m_focus == focused_menu::rightbottom)
- {
- m_event.iptkey = IPT_UI_UP_PANEL;
- topline_datsview--;
- return;
- }
-
- if (selected == visible_items + 1 || is_first_selected() || ui_error)
- return;
-
- selected--;
-
- if (selected == top_line && top_line != 0)
- top_line--;
- }
-
- // down advances by one item
- if (exclusive_input_pressed(IPT_UI_DOWN, 6))
- {
- // Filter
- if (!leftclose && m_focus == focused_menu::left)
- {
- m_event.iptkey = IPT_UI_DOWN_FILTER;
- return;
- }
-
- // Infos
- if (!rightclose && m_focus == focused_menu::rightbottom)
- {
- m_event.iptkey = IPT_UI_DOWN_PANEL;
- topline_datsview++;
- return;
- }
-
- if (is_last_selected() || selected == visible_items - 1 || ui_error)
- return;
-
- selected++;
-
- if (selected == top_line + m_visible_items + (top_line != 0))
- top_line++;
- }
-
- // page up backs up by m_visible_items
- if (exclusive_input_pressed(IPT_UI_PAGE_UP, 6))
- {
- // Infos
- if (!rightclose && m_focus == focused_menu::rightbottom)
- {
- m_event.iptkey = IPT_UI_DOWN_PANEL;
- topline_datsview -= right_visible_lines - 1;
- return;
- }
-
- if (selected < visible_items && !ui_error)
- {
- selected -= m_visible_items;
-
- if (selected < 0)
- selected = 0;
-
- top_line -= m_visible_items - (top_line + m_visible_lines == visible_items);
- }
- }
-
- // page down advances by m_visible_items
- if (exclusive_input_pressed(IPT_UI_PAGE_DOWN, 6))
- {
- // Infos
- if (!rightclose && m_focus == focused_menu::rightbottom)
- {
- m_event.iptkey = IPT_UI_DOWN_PANEL;
- topline_datsview += right_visible_lines - 1;
- return;
- }
-
- if (selected < visible_items && !ui_error)
- {
- selected += m_visible_lines - 2 + (selected == 0);
-
- if (selected >= visible_items)
- selected = visible_items - 1;
-
- top_line += m_visible_lines - 2;
- }
- }
-
- // home goes to the start
- if (exclusive_input_pressed(IPT_UI_HOME, 0))
- {
- // Infos
- if (!rightclose && m_focus == focused_menu::rightbottom)
- {
- m_event.iptkey = IPT_UI_DOWN_PANEL;
- topline_datsview = 0;
- return;
- }
-
- if (selected < visible_items && !ui_error)
- {
- selected = 0;
- top_line = 0;
- }
- }
-
- // end goes to the last
- if (exclusive_input_pressed(IPT_UI_END, 0))
- {
- // Infos
- if (!rightclose && m_focus == focused_menu::rightbottom)
- {
- m_event.iptkey = IPT_UI_DOWN_PANEL;
- topline_datsview = totallines;
- return;
- }
-
- if (selected < visible_items && !ui_error)
- selected = top_line = visible_items - 1;
- }
-
- // pause enables/disables pause
- if (!ui_error && !ignorepause && exclusive_input_pressed(IPT_UI_PAUSE, 0))
- {
- if (machine().paused())
- machine().resume();
- else
- machine().pause();
- }
-
- // handle a toggle cheats request
- if (!ui_error && machine().ui_input().pressed_repeat(IPT_UI_TOGGLE_CHEAT, 0))
- mame_machine_manager::instance()->cheat().set_enable(!mame_machine_manager::instance()->cheat().enabled());
-
- // see if any other UI keys are pressed
- if (m_event.iptkey == IPT_INVALID)
- for (int code = IPT_UI_FIRST + 1; code < IPT_UI_LAST; code++)
- {
- if (ui_error || code == IPT_UI_CONFIGURE || (code == IPT_UI_LEFT && ignoreleft) || (code == IPT_UI_RIGHT && ignoreright) || (code == IPT_UI_PAUSE && ignorepause))
- continue;
-
- if (exclusive_input_pressed(code, 0))
- break;
- }
-}
-
-//-------------------------------------------------
-// handle input events for main menu
-//-------------------------------------------------
-
-void menu::handle_main_events()
-{
- auto stop = false;
- ui_event local_menu_event;
-
- if (m_pressed)
- {
- bool pressed = mouse_pressed();
- INT32 m_target_x, m_target_y;
- bool m_button;
- auto mouse_target = machine().ui_input().find_mouse(&m_target_x, &m_target_y, &m_button);
- if (mouse_target && m_button && (hover == HOVER_ARROW_DOWN || hover == HOVER_ARROW_UP))
- {
- if (pressed)
- machine().ui_input().push_mouse_down_event(mouse_target, m_target_x, m_target_y);
- }
- else
- reset_pressed();
- }
-
- // loop while we have interesting events
- while (!stop && machine().ui_input().pop_event(&local_menu_event))
- {
- switch (local_menu_event.event_type)
- {
- // if we are hovering over a valid item, select it with a single click
- case UI_EVENT_MOUSE_DOWN:
- {
- if (ui_error)
- {
- m_event.iptkey = IPT_OTHER;
- stop = true;
- }
- else
- {
- if (hover >= 0 && hover < item.size())
- {
- if (hover >= visible_items - 1 && selected < visible_items)
- m_prev_selected = item[selected].ref;
- selected = hover;
- m_focus = focused_menu::main;
- }
- else if (hover == HOVER_ARROW_UP)
- {
- selected -= m_visible_items;
- if (selected < 0)
- selected = 0;
- top_line -= m_visible_items - (top_line + m_visible_lines == visible_items);
- set_pressed();
- }
- else if (hover == HOVER_ARROW_DOWN)
- {
- selected += m_visible_lines - 2 + (selected == 0);
- if (selected >= visible_items)
- selected = visible_items - 1;
- top_line += m_visible_lines - 2;
- set_pressed();
- }
- else if (hover == HOVER_UI_RIGHT)
- m_event.iptkey = IPT_UI_RIGHT;
- else if (hover == HOVER_UI_LEFT)
- m_event.iptkey = IPT_UI_LEFT;
- else if (hover == HOVER_DAT_DOWN)
- topline_datsview += right_visible_lines - 1;
- else if (hover == HOVER_DAT_UP)
- topline_datsview -= right_visible_lines - 1;
- else if (hover == HOVER_LPANEL_ARROW)
- {
- if (ui_globals::panels_status == HIDE_LEFT_PANEL)
- ui_globals::panels_status = SHOW_PANELS;
- else if (ui_globals::panels_status == HIDE_BOTH)
- ui_globals::panels_status = HIDE_RIGHT_PANEL;
- else if (ui_globals::panels_status == SHOW_PANELS)
- ui_globals::panels_status = HIDE_LEFT_PANEL;
- else if (ui_globals::panels_status == HIDE_RIGHT_PANEL)
- ui_globals::panels_status = HIDE_BOTH;
- }
- else if (hover == HOVER_RPANEL_ARROW)
- {
- if (ui_globals::panels_status == HIDE_RIGHT_PANEL)
- ui_globals::panels_status = SHOW_PANELS;
- else if (ui_globals::panels_status == HIDE_BOTH)
- ui_globals::panels_status = HIDE_LEFT_PANEL;
- else if (ui_globals::panels_status == SHOW_PANELS)
- ui_globals::panels_status = HIDE_RIGHT_PANEL;
- else if (ui_globals::panels_status == HIDE_LEFT_PANEL)
- ui_globals::panels_status = HIDE_BOTH;
- }
- else if (hover == HOVER_B_FAV)
- {
- m_event.iptkey = IPT_UI_FAVORITES;
- stop = true;
- }
- else if (hover == HOVER_B_EXPORT)
- {
- m_event.iptkey = IPT_UI_EXPORT;
- stop = true;
- }
- else if (hover == HOVER_B_DATS)
- {
- m_event.iptkey = IPT_UI_DATS;
- stop = true;
- }
- else if (hover >= HOVER_RP_FIRST && hover <= HOVER_RP_LAST)
- {
- ui_globals::rpanel = (HOVER_RP_FIRST - hover) * (-1);
- stop = true;
- }
- else if (hover >= HOVER_SW_FILTER_FIRST && hover <= HOVER_SW_FILTER_LAST)
- {
- l_sw_hover = (HOVER_SW_FILTER_FIRST - hover) * (-1);
- m_event.iptkey = IPT_OTHER;
- stop = true;
- }
- else if (hover >= HOVER_FILTER_FIRST && hover <= HOVER_FILTER_LAST)
- {
- l_hover = (HOVER_FILTER_FIRST - hover) * (-1);
- m_event.iptkey = IPT_OTHER;
- stop = true;
- }
- }
- break;
- }
-
- // if we are hovering over a valid item, fake a UI_SELECT with a double-click
- case UI_EVENT_MOUSE_DOUBLE_CLICK:
- if (hover >= 0 && hover < item.size())
- {
- selected = hover;
- m_event.iptkey = IPT_UI_SELECT;
- }
-
- if (selected == item.size() - 1)
- {
- m_event.iptkey = IPT_UI_CANCEL;
- menu::stack_pop(machine());
- }
- stop = true;
- break;
-
- // caught scroll event
- case UI_EVENT_MOUSE_WHEEL:
- if (hover >= 0 && hover < item.size() - skip_main_items - 1)
- {
- if (local_menu_event.zdelta > 0)
- {
- if (selected >= visible_items || selected == 0 || ui_error)
- break;
- selected -= local_menu_event.num_lines;
- if (selected < top_line + (top_line != 0))
- top_line -= local_menu_event.num_lines;
- }
- else
- {
- if (selected >= visible_items - 1 || ui_error)
- break;
- selected += local_menu_event.num_lines;
- if (selected > visible_items - 1)
- selected = visible_items - 1;
- if (selected >= top_line + m_visible_items + (top_line != 0))
- top_line += local_menu_event.num_lines;
- }
- }
- break;
-
- // translate CHAR events into specials
- case UI_EVENT_CHAR:
- if (exclusive_input_pressed(IPT_UI_CONFIGURE, 0))
- {
- m_event.iptkey = IPT_UI_CONFIGURE;
- stop = true;
- }
- else
- {
- m_event.iptkey = IPT_SPECIAL;
- m_event.unichar = local_menu_event.ch;
- stop = true;
- }
- break;
-
- case UI_EVENT_MOUSE_RDOWN:
- if (hover >= 0 && hover < item.size() - skip_main_items - 1)
- {
- selected = hover;
- m_prev_selected = item[selected].ref;
- m_focus = focused_menu::main;
- m_event.iptkey = IPT_CUSTOM;
- m_event.mouse.x0 = local_menu_event.mouse_x;
- m_event.mouse.y0 = local_menu_event.mouse_y;
- stop = true;
- }
- break;
-
- // ignore everything else
- default:
- break;
- }
- }
-}
-
-//-------------------------------------------------
-// draw right box title
-//-------------------------------------------------
-
-float menu::draw_right_box_title(float x1, float y1, float x2, float y2)
-{
- auto line_height = ui().get_line_height();
- float midl = (x2 - x1) * 0.5f;
-
- // add outlined box for options
- ui().draw_outlined_box(container, x1, y1, x2, y2, UI_BACKGROUND_COLOR);
-
- // add separator line
- container->add_line(x1 + midl, y1, x1 + midl, y1 + line_height, UI_LINE_WIDTH, UI_BORDER_COLOR, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
-
- std::string buffer[RP_LAST + 1];
- buffer[RP_IMAGES] = _("Images");
- buffer[RP_INFOS] = _("Infos");
-
- // check size
- float text_size = 1.0f;
- for (auto & elem : buffer)
- {
- auto textlen = ui().get_string_width(elem.c_str()) + 0.01f;
- float tmp_size = (textlen > midl) ? (midl / textlen) : 1.0f;
- text_size = MIN(text_size, tmp_size);
- }
-
- for (int cells = RP_FIRST; cells <= RP_LAST; ++cells)
- {
- rgb_t bgcolor = UI_TEXT_BG_COLOR;
- rgb_t fgcolor = UI_TEXT_COLOR;
-
- if (mouse_hit && x1 <= mouse_x && x1 + midl > mouse_x && y1 <= mouse_y && y1 + line_height > mouse_y)
- {
- if (ui_globals::rpanel != cells)
- {
- bgcolor = UI_MOUSEOVER_BG_COLOR;
- fgcolor = UI_MOUSEOVER_COLOR;
- hover = HOVER_RP_FIRST + cells;
- }
- }
-
- if (ui_globals::rpanel != cells)
- {
- container->add_line(x1, y1 + line_height, x1 + midl, y1 + line_height, UI_LINE_WIDTH,
- UI_BORDER_COLOR, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
- if (fgcolor != UI_MOUSEOVER_COLOR)
- fgcolor = UI_CLONE_COLOR;
- }
-
- if (m_focus == focused_menu::righttop && ui_globals::rpanel == cells)
- {
- fgcolor = rgb_t(0xff, 0xff, 0x00);
- bgcolor = rgb_t(0xff, 0xff, 0xff);
- ui().draw_textured_box(container, x1 + UI_LINE_WIDTH, y1 + UI_LINE_WIDTH, x1 + midl - UI_LINE_WIDTH, y1 + line_height,
- bgcolor, rgb_t(43, 43, 43), hilight_main_texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXWRAP(TRUE));
- }
- else if (bgcolor == UI_MOUSEOVER_BG_COLOR)
- container->add_rect(x1 + UI_LINE_WIDTH, y1 + UI_LINE_WIDTH, x1 + midl - UI_LINE_WIDTH, y1 + line_height,
- bgcolor, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXWRAP(TRUE));
-
- ui().draw_text_full(container, buffer[cells].c_str(), x1 + UI_LINE_WIDTH, y1, midl - UI_LINE_WIDTH,
- ui::text_layout::CENTER, ui::text_layout::NEVER, mame_ui_manager::NORMAL, fgcolor, bgcolor, nullptr, nullptr, text_size);
- x1 += midl;
- }
-
- return (y1 + line_height + UI_LINE_WIDTH);
}
-//-------------------------------------------------
-// common function for images render
-//-------------------------------------------------
-
-std::string menu::arts_render_common(float origx1, float origy1, float origx2, float origy2)
-{
- auto line_height = ui().get_line_height();
- std::string snaptext, searchstr;
- auto title_size = 0.0f;
- auto txt_lenght = 0.0f;
- auto gutter_width = 0.4f * line_height * machine().render().ui_aspect() * 1.3f;
-
- get_title_search(snaptext, searchstr);
-
- // apply title to right panel
- for (int x = FIRST_VIEW; x < LAST_VIEW; x++)
- {
- ui().draw_text_full(container, _(arts_info[x].first), origx1, origy1, origx2 - origx1, ui::text_layout::CENTER,
- ui::text_layout::TRUNCATE, mame_ui_manager::NONE, rgb_t::white, rgb_t::black, &txt_lenght, nullptr);
- txt_lenght += 0.01f;
- title_size = MAX(txt_lenght, title_size);
- }
-
- rgb_t fgcolor = (m_focus == focused_menu::rightbottom) ? rgb_t(0xff, 0xff, 0x00) : UI_TEXT_COLOR;
- rgb_t bgcolor = (m_focus == focused_menu::rightbottom) ? rgb_t(0xff, 0xff, 0xff) : UI_TEXT_BG_COLOR;
- float middle = origx2 - origx1;
-
- // check size
- float sc = title_size + 2.0f * gutter_width;
- float tmp_size = (sc > middle) ? ((middle - 2.0f * gutter_width) / sc) : 1.0f;
- title_size *= tmp_size;
-
- if (bgcolor != UI_TEXT_BG_COLOR)
- ui().draw_textured_box(container, origx1 + ((middle - title_size) * 0.5f), origy1, origx1 + ((middle + title_size) * 0.5f),
- origy1 + line_height, bgcolor, rgb_t(43, 43, 43), hilight_main_texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXWRAP(TRUE));
-
- ui().draw_text_full(container, snaptext.c_str(), origx1, origy1, origx2 - origx1, ui::text_layout::CENTER, ui::text_layout::TRUNCATE,
- mame_ui_manager::NORMAL, fgcolor, bgcolor, nullptr, nullptr, tmp_size);
-
- draw_common_arrow(origx1, origy1, origx2, origy2, ui_globals::curimage_view, FIRST_VIEW, LAST_VIEW, title_size);
-
- return searchstr;
-}
-
-//-------------------------------------------------
-// draw favorites star
-//-------------------------------------------------
-
-void menu::draw_star(float x0, float y0)
-{
- float y1 = y0 + ui().get_line_height();
- float x1 = x0 + ui().get_line_height() * container->manager().ui_aspect();
- container->add_quad(x0, y0, x1, y1, rgb_t::white, star_texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_PACKABLE);
-}
-
-//-------------------------------------------------
-// draw toolbar
-//-------------------------------------------------
-
-void menu::draw_toolbar(float x1, float y1, float x2, float y2, bool software)
-{
- // draw a box
- ui().draw_outlined_box(container, x1, y1, x2, y2, rgb_t(0xEF, 0x12, 0x47, 0x7B));
-
- // take off the borders
- x1 += UI_BOX_LR_BORDER;
- x2 -= UI_BOX_LR_BORDER;
- y1 += UI_BOX_TB_BORDER;
- y2 -= UI_BOX_TB_BORDER;
-
- render_texture **t_texture = (software) ? sw_toolbar_texture : toolbar_texture;
- auto t_bitmap = (software) ? sw_toolbar_bitmap : toolbar_bitmap;
-
- int m_valid = 0;
- for (auto & e : t_bitmap)
- if (e->valid()) m_valid++;
-
- float space_x = (y2 - y1) * container->manager().ui_aspect(container);
- auto total = (float)(m_valid * space_x) + ((float)(m_valid - 1) * 0.001f);
- x1 += (x2 - x1) * 0.5f - total * 0.5f;
- x2 = x1 + space_x;
-
- for (int z = 0; z < UI_TOOLBAR_BUTTONS; ++z)
- if (t_bitmap[z]->valid())
- {
- rgb_t color(0xEFEFEFEF);
- if (mouse_hit && x1 <= mouse_x && x2 > mouse_x && y1 <= mouse_y && y2 > mouse_y)
- {
- hover = HOVER_B_FAV + z;
- color = rgb_t::white;
- float ypos = y2 + ui().get_line_height() + 2.0f * UI_BOX_TB_BORDER;
- ui().draw_text_box(container, _(hover_msg[z]), ui::text_layout::CENTER, 0.5f, ypos, UI_BACKGROUND_COLOR);
- }
-
- container->add_quad(x1, y1, x2, y2, color, t_texture[z], PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
- x1 += space_x + ((z < UI_TOOLBAR_BUTTONS - 1) ? 0.001f : 0.0f);
- x2 = x1 + space_x;
- }
-}
-
-
-//-------------------------------------------------
-// perform rendering of image
-//-------------------------------------------------
-
-void menu::arts_render_images(bitmap_argb32 *tmp_bitmap, float origx1, float origy1, float origx2, float origy2)
-{
- bool no_available = false;
- float line_height = ui().get_line_height();
-
- // if it fails, use the default image
- if (!tmp_bitmap->valid())
- {
- tmp_bitmap->allocate(256, 256);
- for (int x = 0; x < 256; x++)
- for (int y = 0; y < 256; y++)
- tmp_bitmap->pix32(y, x) = no_avail_bitmap->pix32(y, x);
- no_available = true;
- }
-
- if (tmp_bitmap->valid())
- {
- float panel_width = origx2 - origx1 - 0.02f;
- float panel_height = origy2 - origy1 - 0.02f - (2.0f * UI_BOX_TB_BORDER) - (2.0f * line_height);
- int screen_width = machine().render().ui_target().width();
- int screen_height = machine().render().ui_target().height();
-
- if (machine().render().ui_target().orientation() & ORIENTATION_SWAP_XY)
- std::swap(screen_height, screen_width);
-
- int panel_width_pixel = panel_width * screen_width;
- int panel_height_pixel = panel_height * screen_height;
-
- // Calculate resize ratios for resizing
- auto ratioW = (float)panel_width_pixel / tmp_bitmap->width();
- auto ratioH = (float)panel_height_pixel / tmp_bitmap->height();
- auto ratioI = (float)tmp_bitmap->height() / tmp_bitmap->width();
- auto dest_xPixel = tmp_bitmap->width();
- auto dest_yPixel = tmp_bitmap->height();
-
- // force 4:3 ratio min
- if (ui().options().forced_4x3_snapshot() && ratioI < 0.75f && ui_globals::curimage_view == SNAPSHOT_VIEW)
- {
- // smaller ratio will ensure that the image fits in the view
- dest_yPixel = tmp_bitmap->width() * 0.75f;
- ratioH = (float)panel_height_pixel / dest_yPixel;
- float ratio = MIN(ratioW, ratioH);
- dest_xPixel = tmp_bitmap->width() * ratio;
- dest_yPixel *= ratio;
- }
- // resize the bitmap if necessary
- else if (ratioW < 1 || ratioH < 1 || (ui().options().enlarge_snaps() && !no_available))
- {
- // smaller ratio will ensure that the image fits in the view
- float ratio = MIN(ratioW, ratioH);
- dest_xPixel = tmp_bitmap->width() * ratio;
- dest_yPixel = tmp_bitmap->height() * ratio;
- }
-
- bitmap_argb32 *dest_bitmap;
-
- // resample if necessary
- if (dest_xPixel != tmp_bitmap->width() || dest_yPixel != tmp_bitmap->height())
- {
- dest_bitmap = auto_alloc(machine(), bitmap_argb32);
- dest_bitmap->allocate(dest_xPixel, dest_yPixel);
- render_color color = { 1.0f, 1.0f, 1.0f, 1.0f };
- render_resample_argb_bitmap_hq(*dest_bitmap, *tmp_bitmap, color, true);
- }
- else
- dest_bitmap = tmp_bitmap;
-
- snapx_bitmap->allocate(panel_width_pixel, panel_height_pixel);
- int x1 = (0.5f * panel_width_pixel) - (0.5f * dest_xPixel);
- int y1 = (0.5f * panel_height_pixel) - (0.5f * dest_yPixel);
-
- for (int x = 0; x < dest_xPixel; x++)
- for (int y = 0; y < dest_yPixel; y++)
- snapx_bitmap->pix32(y + y1, x + x1) = dest_bitmap->pix32(y, x);
-
- auto_free(machine(), dest_bitmap);
-
- // apply bitmap
- snapx_texture->set_bitmap(*snapx_bitmap, snapx_bitmap->cliprect(), TEXFORMAT_ARGB32);
- }
- else
- snapx_bitmap->reset();
-}
//-------------------------------------------------
// draw common arrows
@@ -2421,125 +1354,6 @@ void menu::draw_common_arrow(float origx1, float origy1, float origx2, float ori
}
//-------------------------------------------------
-// draw icons
-//-------------------------------------------------
-
-float menu::draw_icon(int linenum, void *selectedref, float x0, float y0)
-{
- if (!ui_globals::has_icons || (item[0].flags & FLAG_UI_SWLIST))
- return 0.0f;
-
- float ud_arrow_width = ui().get_line_height() * container->manager().ui_aspect(container);
- const game_driver *driver = nullptr;
-
- if (item[0].flags & FLAG_UI_FAVORITE)
- {
- ui_software_info *soft = (ui_software_info *)selectedref;
- if (soft->startempty == 1)
- driver = soft->driver;
- }
- else
- driver = (const game_driver *)selectedref;
-
- auto x1 = x0 + ud_arrow_width;
- auto y1 = y0 + ui().get_line_height();
-
- if (m_old_icons[linenum] != driver || ui_globals::redraw_icon)
- {
- m_old_icons[linenum] = driver;
-
- // set clone status
- bool cloneof = strcmp(driver->parent, "0");
- if (cloneof)
- {
- auto cx = driver_list::find(driver->parent);
- if (cx != -1 && ((driver_list::driver(cx).flags & MACHINE_IS_BIOS_ROOT) != 0))
- cloneof = false;
- }
-
- // get search path
- path_iterator path(ui().options().icons_directory());
- std::string curpath;
- std::string searchstr(ui().options().icons_directory());
-
- // iterate over path and add path for zipped formats
- while (path.next(curpath))
- searchstr.append(";").append(curpath.c_str()).append(PATH_SEPARATOR).append("icons");
-
- bitmap_argb32 *tmp = auto_alloc(machine(), bitmap_argb32);
- emu_file snapfile(searchstr.c_str(), OPEN_FLAG_READ);
- std::string fullname = std::string(driver->name).append(".ico");
- render_load_ico(*tmp, snapfile, nullptr, fullname.c_str());
-
- if (!tmp->valid() && cloneof)
- {
- fullname.assign(driver->parent).append(".ico");
- render_load_ico(*tmp, snapfile, nullptr, fullname.c_str());
- }
-
- if (tmp->valid())
- {
- float panel_width = x1 - x0;
- float panel_height = y1 - y0;
- auto screen_width = machine().render().ui_target().width();
- auto screen_height = machine().render().ui_target().height();
-
- if (machine().render().ui_target().orientation() & ORIENTATION_SWAP_XY)
- std::swap(screen_height, screen_width);
-
- int panel_width_pixel = panel_width * screen_width;
- int panel_height_pixel = panel_height * screen_height;
-
- // Calculate resize ratios for resizing
- auto ratioW = (float)panel_width_pixel / tmp->width();
- auto ratioH = (float)panel_height_pixel / tmp->height();
- auto dest_xPixel = tmp->width();
- auto dest_yPixel = tmp->height();
-
- if (ratioW < 1 || ratioH < 1)
- {
- // smaller ratio will ensure that the image fits in the view
- float ratio = MIN(ratioW, ratioH);
- dest_xPixel = tmp->width() * ratio;
- dest_yPixel = tmp->height() * ratio;
- }
-
- bitmap_argb32 *dest_bitmap;
- dest_bitmap = auto_alloc(machine(), bitmap_argb32);
-
- // resample if necessary
- if (dest_xPixel != tmp->width() || dest_yPixel != tmp->height())
- {
- dest_bitmap->allocate(dest_xPixel, dest_yPixel);
- render_color color = { 1.0f, 1.0f, 1.0f, 1.0f };
- render_resample_argb_bitmap_hq(*dest_bitmap, *tmp, color, true);
- }
- else
- dest_bitmap = tmp;
-
- icons_bitmap[linenum]->allocate(panel_width_pixel, panel_height_pixel);
-
- for (int x = 0; x < dest_xPixel; x++)
- for (int y = 0; y < dest_yPixel; y++)
- icons_bitmap[linenum]->pix32(y, x) = dest_bitmap->pix32(y, x);
-
- auto_free(machine(), dest_bitmap);
-
- icons_texture[linenum]->set_bitmap(*icons_bitmap[linenum], icons_bitmap[linenum]->cliprect(), TEXFORMAT_ARGB32);
- }
- else if (icons_bitmap[linenum] != nullptr)
- icons_bitmap[linenum]->reset();
-
- auto_free(machine(), tmp);
- }
-
- if (icons_bitmap[linenum] != nullptr && icons_bitmap[linenum]->valid())
- container->add_quad(x0, y0, x1, y1, rgb_t::white, icons_texture[linenum], PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
-
- return ud_arrow_width * 1.5f;
-}
-
-//-------------------------------------------------
// draw info arrow
//-------------------------------------------------
@@ -2572,8 +1386,8 @@ void menu::draw_palette_menu()
auto gutter_width = lr_arrow_width * 1.3f;
int itemnum, linenum;
- if (ui().options().use_background_image() && &machine().system() == &GAME_NAME(___empty) && bgrnd_bitmap->valid())
- container->add_quad(0.0f, 0.0f, 1.0f, 1.0f, rgb_t::white, bgrnd_texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+ if (&machine().system() == &GAME_NAME(___empty))
+ draw_background();
// compute the width and height of the full menu
auto visible_width = 0.0f;
@@ -2747,156 +1561,6 @@ void menu::draw_palette_menu()
}
//-------------------------------------------------
-// draw - draw dats menu
-//-------------------------------------------------
-
-void menu::draw_dats_menu()
-{
- auto line_height = ui().get_line_height();
- auto ud_arrow_width = line_height * machine().render().ui_aspect();
- auto gutter_width = 0.52f * line_height * machine().render().ui_aspect();
- mouse_x = -1, mouse_y = -1;
- float visible_width = 1.0f - 2.0f * UI_BOX_LR_BORDER;
- float visible_left = (1.0f - visible_width) * 0.5f;
-
- // draw background image if available
- if (ui().options().use_background_image() && bgrnd_bitmap->valid())
- container->add_quad(0.0f, 0.0f, 1.0f, 1.0f, rgb_t::white, bgrnd_texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
-
- hover = item.size() + 1;
- visible_items = item.size() - 2;
- float extra_height = 2.0f * line_height;
- float visible_extra_menu_height = customtop + custombottom + extra_height;
-
- // locate mouse
- mouse_hit = false;
- mouse_button = false;
- mouse_target = machine().ui_input().find_mouse(&mouse_target_x, &mouse_target_y, &mouse_button);
- if (mouse_target != nullptr)
- if (mouse_target->map_point_container(mouse_target_x, mouse_target_y, *container, mouse_x, mouse_y))
- mouse_hit = true;
-
- // account for extra space at the top and bottom
- float visible_main_menu_height = 1.0f - 2.0f * UI_BOX_TB_BORDER - visible_extra_menu_height;
- m_visible_lines = int(std::trunc(visible_main_menu_height / line_height));
- visible_main_menu_height = float(m_visible_lines) * line_height;
-
- // compute top/left of inner menu area by centering
- float visible_top = (1.0f - (visible_main_menu_height + visible_extra_menu_height)) * 0.5f;
-
- // if the menu is at the bottom of the extra, adjust
- visible_top += customtop;
-
- // compute left box size
- float x1 = visible_left;
- float y1 = visible_top - UI_BOX_TB_BORDER;
- float x2 = x1 + visible_width;
- float y2 = visible_top + visible_main_menu_height + UI_BOX_TB_BORDER + extra_height;
- float line = visible_top + float(m_visible_lines) * line_height;
-
- ui().draw_outlined_box(container, x1, y1, x2, y2, UI_BACKGROUND_COLOR);
-
- m_visible_lines = (std::min)(visible_items, m_visible_lines);
- top_line = (std::max)(0, top_line);
- if (top_line + m_visible_lines >= visible_items)
- top_line = visible_items - m_visible_lines;
-
- // 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;
-
- int const n_loop = (std::min)(visible_items, m_visible_lines);
- for (int linenum = 0; linenum < n_loop; linenum++)
- {
- float line_y = visible_top + (float)linenum * line_height;
- int itemnum = top_line + linenum;
- const menu_item &pitem = item[itemnum];
- const char *itemtext = pitem.text.c_str();
- rgb_t fgcolor = UI_TEXT_COLOR;
- rgb_t bgcolor = UI_TEXT_BG_COLOR;
- float line_x0 = x1 + 0.5f * UI_LINE_WIDTH;
- float line_y0 = line_y;
- float line_x1 = x2 - 0.5f * UI_LINE_WIDTH;
- float line_y1 = line_y + line_height;
-
- // if we're on the top line, display the up arrow
- if (linenum == 0 && top_line != 0)
- {
- draw_arrow(container, 0.5f * (x1 + x2) - 0.5f * ud_arrow_width, line_y + 0.25f * line_height,
- 0.5f * (x1 + x2) + 0.5f * ud_arrow_width, line_y + 0.75f * line_height, fgcolor, ROT0);
-
- if (mouse_hit && line_x0 <= mouse_x && line_x1 > mouse_x && line_y0 <= mouse_y && line_y1 > mouse_y)
- {
- fgcolor = UI_MOUSEOVER_COLOR;
- bgcolor = UI_MOUSEOVER_BG_COLOR;
- highlight(container, line_x0, line_y0, line_x1, line_y1, bgcolor);
- hover = HOVER_ARROW_UP;
- }
- }
- // if we're on the bottom line, display the down arrow
- else if (linenum == m_visible_lines - 1 && itemnum != visible_items - 1)
- {
- draw_arrow(container, 0.5f * (x1 + x2) - 0.5f * ud_arrow_width, line_y + 0.25f * line_height,
- 0.5f * (x1 + x2) + 0.5f * ud_arrow_width, line_y + 0.75f * line_height, fgcolor, ROT0 ^ ORIENTATION_FLIP_Y);
-
- if (mouse_hit && line_x0 <= mouse_x && line_x1 > mouse_x && line_y0 <= mouse_y && line_y1 > mouse_y)
- {
- fgcolor = UI_MOUSEOVER_COLOR;
- bgcolor = UI_MOUSEOVER_BG_COLOR;
- highlight(container, line_x0, line_y0, line_x1, line_y1, bgcolor);
- hover = HOVER_ARROW_DOWN;
- }
- }
-
- // draw dats text
- else if (pitem.subtext.empty())
- {
- ui().draw_text_full(container, itemtext, effective_left, line_y, effective_width, ui::text_layout::LEFT, ui::text_layout::NEVER,
- mame_ui_manager::NORMAL, fgcolor, bgcolor, nullptr, nullptr);
- }
- }
-
- for (size_t count = visible_items; count < item.size(); count++)
- {
- const menu_item &pitem = item[count];
- const char *itemtext = pitem.text.c_str();
- float line_x0 = x1 + 0.5f * UI_LINE_WIDTH;
- float line_y0 = line;
- float line_x1 = x2 - 0.5f * UI_LINE_WIDTH;
- float line_y1 = line + line_height;
- rgb_t fgcolor = UI_SELECTED_COLOR;
- rgb_t bgcolor = UI_SELECTED_BG_COLOR;
-
- if (mouse_hit && line_x0 <= mouse_x && line_x1 > mouse_x && line_y0 <= mouse_y && line_y1 > mouse_y && is_selectable(pitem))
- hover = count;
-
- if (pitem.type == menu_item_type::SEPARATOR)
- container->add_line(visible_left, line + 0.5f * line_height, visible_left + visible_width, line + 0.5f * line_height,
- UI_LINE_WIDTH, UI_TEXT_COLOR, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
- else
- {
- highlight(container, line_x0, line_y0, line_x1, line_y1, bgcolor);
- ui().draw_text_full(container, itemtext, effective_left, line, effective_width, ui::text_layout::CENTER, ui::text_layout::TRUNCATE,
- mame_ui_manager::NORMAL, fgcolor, bgcolor, nullptr, nullptr);
- }
- line += line_height;
- }
-
- // if there is something special to add, do it by calling the virtual method
- custom_render(get_selection_ref(), customtop, custombottom, x1, y1, x2, y2);
-
- // return the number of visible lines, minus 1 for top arrow and 1 for bottom arrow
- m_visible_items = m_visible_lines - (top_line != 0) - (top_line + m_visible_lines != visible_items);
-}
-
-void menu::set_pressed()
-{
- (m_repeat == 0) ? m_repeat = osd_ticks() + osd_ticks_per_second() / 2 : m_repeat = osd_ticks() + osd_ticks_per_second() / 4;
- m_pressed = true;
-}
-
-
-//-------------------------------------------------
// extra_text_draw_box - generically adds header
// or footer text
//-------------------------------------------------
@@ -2923,6 +1587,14 @@ void menu::extra_text_draw_box(float origx1, float origx2, float origy, float ys
}
+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));
+}
+
+
//-------------------------------------------------
// extra_text_position - given extra text that has
// been put into a layout, position it
diff --git a/src/frontend/mame/ui/menu.h b/src/frontend/mame/ui/menu.h
index 7c292a22753..d0df364d3fe 100644
--- a/src/frontend/mame/ui/menu.h
+++ b/src/frontend/mame/ui/menu.h
@@ -8,18 +8,21 @@
***************************************************************************/
-#pragma once
-
#ifndef MAME_FRONTEND_UI_MENU_H
#define MAME_FRONTEND_UI_MENU_H
+#pragma once
+
#include "ui/ui.h"
#include "ui/menuitem.h"
#include "language.h"
#include "render.h"
+#include <functional>
+#include <map>
#include <memory>
+#include <mutex>
namespace ui {
@@ -39,9 +42,7 @@ public:
FLAG_MULTILINE = (1 << 3),
FLAG_REDTEXT = (1 << 4),
FLAG_DISABLE = (1 << 5),
- FLAG_UI = (1 << 6),
FLAG_UI_DATS = (1 << 7),
- FLAG_UI_SWLIST = (1 << 8),
FLAG_UI_FAVORITE = (1 << 9),
FLAG_UI_PALETTE = (1 << 10),
FLAG_UI_HEADING = (1 << 11)
@@ -72,10 +73,9 @@ public:
// Global initialization
static void init(running_machine &machine, ui_options &mopt);
- static void exit(running_machine &machine);
// reset the menus, clearing everything
- static void stack_reset(running_machine &machine);
+ static void stack_reset(running_machine &machine) { get_global_state(machine)->stack_reset(); }
// push a new menu onto the stack
template <typename T, typename... Params>
@@ -92,17 +92,14 @@ public:
}
// pop a menu from the stack
- static void stack_pop(running_machine &machine);
+ static void stack_pop(running_machine &machine) { get_global_state(machine)->stack_pop(); }
// test if one of the menus in the stack requires hide disable
- static bool stack_has_special_main_menu();
+ static bool stack_has_special_main_menu(running_machine &machine) { return get_global_state(machine)->stack_has_special_main_menu(); }
// highlight
static void highlight(render_container *container, float x0, float y0, float x1, float y1, rgb_t bgcolor);
- // draw arrow
- static void draw_arrow(render_container *container, float x0, float y0, float x1, float y1, rgb_t fgcolor, UINT32 orientation);
-
// master handler
static UINT32 ui_handler(render_container *container, mame_ui_manager &mui);
@@ -122,41 +119,28 @@ public:
private:
static std::unique_ptr<bitmap_rgb32> hilight_bitmap;
- static render_texture *hilight_texture, *arrow_texture;
+ static render_texture *hilight_texture;
- void draw(UINT32 flags, float x0 = 0.0f, float y0 = 0.0f);
+ virtual void draw(UINT32 flags);
void draw_text_box();
- void handle_events(UINT32 flags);
- void handle_keys(UINT32 flags);
- inline bool exclusive_input_pressed(int key, int repeat);
- static void clear_free_list(running_machine &machine);
static void render_triangle(bitmap_argb32 &dest, bitmap_argb32 &source, const rectangle &sbounds, void *param);
public:
void *m_prev_selected;
- int visible_items;
- bool ui_error;
-
// mouse handling
bool mouse_hit, mouse_button;
render_target *mouse_target;
INT32 mouse_target_x, mouse_target_y;
float mouse_x, mouse_y;
- // draw toolbar
- void draw_toolbar(float x1, float y1, float x2, float y2, bool software = false);
-
// draw left panel
virtual float draw_left_panel(float x1, float y1, float x2, float y2) { return 0; }
// draw right panel
virtual void draw_right_panel(void *selectedref, float origx1, float origy1, float origx2, float origy2) { };
- // draw star
- void draw_star(float x0, float y0);
-
// Global initialization
static void init_ui(running_machine &machine, ui_options &mopt);
@@ -171,6 +155,10 @@ public:
}
protected:
+ using cleanup_callback = std::function<void(running_machine &)>;
+ using bitmap_ptr = std::unique_ptr<bitmap_argb32>;
+ using texture_ptr = std::unique_ptr<render_texture, std::function<void(render_texture *)> >;
+
// flags to pass to process
enum
{
@@ -190,15 +178,6 @@ protected:
REMEMBER_REF
};
- // tab navigation
- enum class focused_menu
- {
- main,
- left,
- righttop,
- rightbottom
- };
-
// menu-related events
struct event
{
@@ -234,27 +213,33 @@ protected:
}
};
- int topline_datsview; // right box top line
- int top_line; // main box top line
+ int top_line; // main box top line
int l_sw_hover;
int l_hover;
- int totallines;
int skip_main_items;
- int selected; // which item is selected
+ int selected; // which item is selected
+
+ int m_visible_lines; // main box visible lines
+ int m_visible_items; // number of visible items
menu(mame_ui_manager &mui, render_container *container);
void reset(reset_options options);
void reset_parent(reset_options options) { m_parent->reset(options); }
- static void reset_topmost(reset_options options) { if (menu_stack) menu_stack->reset(options); }
+ void reset_topmost(reset_options options) { m_global_state->reset_topmost(options); }
+
+ template <typename T> T *topmost_menu() const { return m_global_state->topmost_menu<T>(); }
+ template <typename T> static T *topmost_menu(running_machine &machine) { return get_global_state(machine)->topmost_menu<T>(); }
+ void stack_pop() { m_global_state->stack_pop(); }
+ void stack_reset() { m_global_state->stack_reset(); }
+ bool stack_has_special_main_menu() const { return m_global_state->stack_has_special_main_menu(); }
+
+ void add_cleanup_callback(cleanup_callback &&callback) { m_global_state->add_cleanup_callback(std::move(callback)); }
// process a menu, drawing it and returning any interesting events
const event *process(UINT32 flags, float x0 = 0.0f, float y0 = 0.0f);
void process_parent() { m_parent->process(PROCESS_NOINPUT); }
- focused_menu get_focus() const { return m_focus; }
- void set_focus(focused_menu focus) { m_focus = focus; }
-
// retrieves the ref of the currently selected menu item or nullptr
void *get_selection_ref() const { return selection_valid() ? item[selected].ref : nullptr; }
bool selection_valid() const { return (0 <= selected) && (item.size() > selected); }
@@ -267,37 +252,81 @@ protected:
// scroll position control
void centre_selection() { top_line = selected - (m_visible_lines / 2); }
- // draw right box
- float draw_right_box_title(float x1, float y1, float x2, float y2);
+ // test if the given key is pressed and we haven't already reported a key
+ bool exclusive_input_pressed(int &iptkey, int key, int repeat);
// draw arrow
+ void draw_arrow(render_container *container, float x0, float y0, float x1, float y1, rgb_t fgcolor, UINT32 orientation);
void draw_common_arrow(float origx1, float origy1, float origx2, float origy2, int current, int dmin, int dmax, float title);
void info_arrow(int ub, float origx1, float origx2, float oy1, float line_height, float text_size, float ud_arrow_width);
- // images render
- std::string arts_render_common(float origx1, float origy1, float origx2, float origy2);
- void arts_render_images(bitmap_argb32 *bitmap, float origx1, float origy1, float origx2, float origy2);
-
// draw header and footer text
void extra_text_render(float top, float bottom, float origx1, float origy1, float origx2, float origy2, const char *header, const char *footer);
void extra_text_position(float origx1, float origx2, float origy, float yspan, text_layout &layout,
int direction, float &x1, float &y1, float &x2, float &y2);
- // custom events
+ void draw_background();
+
+ // overridable event handling
+ virtual void handle_events(UINT32 flags, event &ev);
+ virtual void handle_keys(UINT32 flags, int &iptkey);
virtual bool custom_mouse_down() { return false; }
- template <typename T>
- static T *topmost_menu() { return dynamic_cast<T *>(menu_stack.get()); }
+ static bool is_selectable(menu_item const &item)
+ {
+ return ((item.flags & (menu::FLAG_MULTILINE | menu::FLAG_DISABLE)) == 0 && item.type != menu_item_type::SEPARATOR);
+ }
int right_visible_lines; // right box lines
- static std::unique_ptr<bitmap_argb32> snapx_bitmap;
+ static bitmap_ptr snapx_bitmap;
static render_texture *snapx_texture;
static std::unique_ptr<bitmap_rgb32> hilight_main_bitmap;
static render_texture *hilight_main_texture;
private:
+ class global_state
+ {
+ public:
+ global_state(running_machine &machine, ui_options const &options);
+ global_state(global_state const &) = delete;
+ global_state(global_state &&) = delete;
+ ~global_state();
+
+ void add_cleanup_callback(cleanup_callback &&callback);
+
+ render_texture * arrow_texture() { return m_arrow_texture.get(); }
+ bitmap_argb32 *bgrnd_bitmap() { return m_bgrnd_bitmap.get(); }
+ render_texture * bgrnd_texture() { return m_bgrnd_texture.get(); }
+
+ void reset_topmost(reset_options options) { if (m_stack) m_stack->reset(options); }
+
+ template <typename T>
+ T *topmost_menu() const { return dynamic_cast<T *>(m_stack.get()); }
+
+ void stack_push(std::unique_ptr<menu> &&menu);
+ void stack_pop();
+ void stack_reset();
+ void clear_free_list();
+ bool stack_has_special_main_menu() const;
+
+ private:
+ using cleanup_callback_vector = std::vector<cleanup_callback>;
+
+ running_machine &m_machine;
+ cleanup_callback_vector m_cleanup_callbacks;
+
+ texture_ptr m_arrow_texture;
+ bitmap_ptr m_bgrnd_bitmap;
+ texture_ptr m_bgrnd_texture;
+
+ std::unique_ptr<menu> m_stack;
+ std::unique_ptr<menu> m_free;
+ };
+ using global_state_ptr = std::shared_ptr<global_state>;
+ using global_state_map = std::map<running_machine *, global_state_ptr>;
+
struct pool
{
pool *next; // chain to next one
@@ -305,69 +334,36 @@ private:
UINT8 *end; // end of the pool
};
-
- void reset_pressed() { m_pressed = false; m_repeat = 0; }
- bool mouse_pressed() { return (osd_ticks() >= m_repeat); }
- void set_pressed();
-
- static std::unique_ptr<bitmap_argb32> no_avail_bitmap, bgrnd_bitmap, star_bitmap;
- static render_texture *bgrnd_texture, *star_texture;
- static std::vector<std::unique_ptr<bitmap_argb32>> icons_bitmap;
- static render_texture *icons_texture[];
-
// request the specific handling of the game selection main menu
bool is_special_main_menu() const;
void set_special_main_menu(bool disable);
// push a new menu onto the stack
- static void stack_push(std::unique_ptr<menu> &&menu);
-
- // toolbar
- static std::vector<std::shared_ptr<bitmap_argb32>> toolbar_bitmap, sw_toolbar_bitmap;
- static render_texture *toolbar_texture[], *sw_toolbar_texture[];
-
- // draw game list
- void draw_select_game(UINT32 flags);
+ static void stack_push(std::unique_ptr<menu> &&menu) { get_global_state(menu->machine())->stack_push(std::move(menu)); }
// draw palette menu
void draw_palette_menu();
- // draw dats menu
- void draw_dats_menu();
-
- void get_title_search(std::string &title, std::string &search);
-
- // handle keys
- void handle_main_keys(UINT32 flags);
-
- // handle mouse
- void handle_main_events();
-
- float draw_icon(int linenum, void *selectedref, float x1, float y1);
void extra_text_draw_box(float origx1, float origx2, float origy, float yspan, const char *text, int direction);
bool first_item_visible() const { return top_line <= 0; }
bool last_item_visible() const { return (top_line + m_visible_lines) >= item.size(); }
+ static void exit(running_machine &machine);
+ static global_state_ptr get_global_state(running_machine &machine);
+
+ global_state_ptr const m_global_state;
bool m_special_main_menu;
mame_ui_manager &m_ui; // UI we are attached to
std::unique_ptr<menu> m_parent; // pointer to parent menu
- bool m_pressed; // mouse button held down
- osd_ticks_t m_repeat;
event m_event; // the UI event that occurred
pool *m_pool; // list of memory pools
- focused_menu m_focus;
-
- int m_visible_lines; // main box visible lines
- int m_visible_items; // number of visible items
int m_resetpos; // reset position
void *m_resetref; // reset reference
- static std::vector<const game_driver *> m_old_icons;
-
- static std::unique_ptr<menu> menu_stack;
- static std::unique_ptr<menu> menu_free;
+ static std::mutex s_global_state_guard;
+ static global_state_map s_global_states;
};
} // namespace ui
diff --git a/src/frontend/mame/ui/miscmenu.cpp b/src/frontend/mame/ui/miscmenu.cpp
index 25f18f7aacc..62c04b98cff 100644
--- a/src/frontend/mame/ui/miscmenu.cpp
+++ b/src/frontend/mame/ui/miscmenu.cpp
@@ -548,7 +548,7 @@ void menu_quit_game::handle()
machine().schedule_exit();
/* reset the menu stack */
- menu::stack_reset(machine());
+ stack_reset();
}
//-------------------------------------------------
diff --git a/src/frontend/mame/ui/selector.cpp b/src/frontend/mame/ui/selector.cpp
index f5f07c0c2b3..236ce06f672 100644
--- a/src/frontend/mame/ui/selector.cpp
+++ b/src/frontend/mame/ui/selector.cpp
@@ -95,7 +95,7 @@ void menu_selector::handle()
}
ui_globals::switch_image = true;
- menu::stack_pop(machine());
+ stack_pop();
}
else if (menu_event->iptkey == IPT_SPECIAL)
{
diff --git a/src/frontend/mame/ui/selgame.cpp b/src/frontend/mame/ui/selgame.cpp
index 992cab5c758..6f451a3018e 100644
--- a/src/frontend/mame/ui/selgame.cpp
+++ b/src/frontend/mame/ui/selgame.cpp
@@ -55,7 +55,8 @@ int menu_select_game::m_isabios = 0;
// ctor
//-------------------------------------------------
-menu_select_game::menu_select_game(mame_ui_manager &mui, render_container *container, const char *gamename) : menu(mui, container)
+menu_select_game::menu_select_game(mame_ui_manager &mui, render_container *container, const char *gamename)
+ : menu_select_launch(mui, container, false)
{
set_focus(focused_menu::main);
highlight = 0;
@@ -184,7 +185,7 @@ void menu_select_game::handle()
{
ui_globals::reset = false;
machine().schedule_hard_reset();
- menu::stack_reset(machine());
+ stack_reset();
return;
}
@@ -203,10 +204,10 @@ void menu_select_game::handle()
const event *menu_event = process(PROCESS_LR_REPEAT);
if (menu_event && menu_event->itemref)
{
- if (ui_error)
+ if (m_ui_error)
{
// reset the error on any future menu_event
- ui_error = false;
+ m_ui_error = false;
machine().ui_input().reset();
}
else if (menu_event->iptkey == IPT_UI_SELECT)
@@ -257,7 +258,7 @@ void menu_select_game::handle()
if ((FPTR)drv > skip_main_items && ui_globals::curdats_view > UI_FIRST_LOAD)
{
ui_globals::curdats_view--;
- topline_datsview = 0;
+ m_topline_datsview = 0;
}
}
else
@@ -266,12 +267,12 @@ void menu_select_game::handle()
if (drv->startempty == 1 && ui_globals::curdats_view > UI_FIRST_LOAD)
{
ui_globals::curdats_view--;
- topline_datsview = 0;
+ m_topline_datsview = 0;
}
else if ((FPTR)drv > skip_main_items && ui_globals::cur_sw_dats_view > 0)
{
ui_globals::cur_sw_dats_view--;
- topline_datsview = 0;
+ m_topline_datsview = 0;
}
}
}
@@ -295,7 +296,7 @@ void menu_select_game::handle()
if ((FPTR)drv > skip_main_items && ui_globals::curdats_view < UI_LAST_LOAD)
{
ui_globals::curdats_view++;
- topline_datsview = 0;
+ m_topline_datsview = 0;
}
}
else
@@ -304,12 +305,12 @@ void menu_select_game::handle()
if (drv->startempty == 1 && ui_globals::curdats_view < UI_LAST_LOAD)
{
ui_globals::curdats_view++;
- topline_datsview = 0;
+ m_topline_datsview = 0;
}
else if ((FPTR)drv > skip_main_items && ui_globals::cur_sw_dats_view < 1)
{
ui_globals::cur_sw_dats_view++;
- topline_datsview = 0;
+ m_topline_datsview = 0;
}
}
}
@@ -457,7 +458,7 @@ void menu_select_game::handle()
}
// if we're in an error state, overlay an error message
- if (ui_error)
+ if (m_ui_error)
ui().draw_text_box(container, _("The selected machine is missing one or more required ROM or CHD images. "
"Please select a different machine.\n\nPress any key to continue."), ui::text_layout::CENTER, 0.5f, 0.5f, UI_RED_COLOR);
@@ -497,7 +498,7 @@ void menu_select_game::populate()
ui_globals::redraw_icon = true;
ui_globals::switch_image = true;
int old_item_selected = -1;
- UINT32 flags_ui = FLAG_UI | FLAG_LEFT_ARROW | FLAG_RIGHT_ARROW;
+ UINT32 flags_ui = FLAG_LEFT_ARROW | FLAG_RIGHT_ARROW;
if (!isfavorite())
{
@@ -588,7 +589,7 @@ void menu_select_game::populate()
item_append(menu_item_type::SEPARATOR, flags_ui);
// add special items
- if (menu::stack_has_special_main_menu())
+ if (stack_has_special_main_menu())
{
item_append(_("Configure Options"), "", flags_ui, (void *)(FPTR)CONF_OPTS);
item_append(_("Configure Machine"), "", flags_ui, (void *)(FPTR)CONF_MACHINE);
@@ -1064,14 +1065,14 @@ void menu_select_game::inkey_select(const event *menu_event)
reselect_last::swlist.clear();
mame_machine_manager::instance()->schedule_new_driver(*driver);
machine().schedule_hard_reset();
- menu::stack_reset(machine());
+ stack_reset();
}
}
// otherwise, display an error
else
{
reset(reset_options::REMEMBER_REF);
- ui_error = true;
+ m_ui_error = true;
}
}
}
@@ -1125,7 +1126,7 @@ void menu_select_game::inkey_select_favorite(const event *menu_event)
reselect_last::set(true);
mame_machine_manager::instance()->schedule_new_driver(*ui_swinfo->driver);
machine().schedule_hard_reset();
- menu::stack_reset(machine());
+ stack_reset();
}
}
@@ -1133,7 +1134,7 @@ void menu_select_game::inkey_select_favorite(const event *menu_event)
else
{
reset(reset_options::REMEMBER_REF);
- ui_error = true;
+ m_ui_error = true;
}
}
else
@@ -1182,14 +1183,14 @@ void menu_select_game::inkey_select_favorite(const event *menu_event)
reselect_last::swlist = ui_swinfo->listname;
mame_machine_manager::instance()->schedule_new_driver(drv.driver());
machine().schedule_hard_reset();
- menu::stack_reset(machine());
+ stack_reset();
}
// otherwise, display an error
else
{
reset(reset_options::REMEMBER_POSITION);
- ui_error = true;
+ m_ui_error = true;
}
}
}
@@ -1531,7 +1532,7 @@ void menu_select_game::populate_search()
}
(index < VISIBLE_GAMES_IN_SEARCH) ? m_searchlist[index] = nullptr : m_searchlist[VISIBLE_GAMES_IN_SEARCH] = nullptr;
- UINT32 flags_ui = FLAG_UI | FLAG_LEFT_ARROW | FLAG_RIGHT_ARROW;
+ UINT32 flags_ui = FLAG_LEFT_ARROW | FLAG_RIGHT_ARROW;
for (int curitem = 0; m_searchlist[curitem]; ++curitem)
{
bool cloneof = strcmp(m_searchlist[curitem]->parent, "0");
@@ -2040,8 +2041,8 @@ void menu_select_game::infos_render(void *selectedref, float origx1, float origy
buffer.clear();
olddriver = driver;
oldview = ui_globals::curdats_view;
- topline_datsview = 0;
- totallines = 0;
+ m_topline_datsview = 0;
+ m_total_lines = 0;
std::vector<std::string> m_item;
if (ui_globals::curdats_view == UI_GENERAL_LOAD)
@@ -2072,29 +2073,29 @@ void menu_select_game::infos_render(void *selectedref, float origx1, float origy
return;
}
else if (ui_globals::curdats_view != UI_STORY_LOAD && ui_globals::curdats_view != UI_COMMAND_LOAD)
- totallines = ui().wrap_text(container, buffer.c_str(), origx1, origy1, origx2 - origx1 - (2.0f * gutter_width), xstart, xend, text_size);
+ m_total_lines = ui().wrap_text(container, buffer.c_str(), origx1, origy1, origx2 - origx1 - (2.0f * gutter_width), xstart, xend, text_size);
else
- totallines = ui().wrap_text(container, buffer.c_str(), 0.0f, 0.0f, 1.0f - (2.0f * gutter_width), xstart, xend, text_size);
+ m_total_lines = ui().wrap_text(container, buffer.c_str(), 0.0f, 0.0f, 1.0f - (2.0f * gutter_width), xstart, xend, text_size);
int r_visible_lines = floor((origy2 - oy1) / (line_height * text_size));
- if (totallines < r_visible_lines)
- r_visible_lines = totallines;
- if (topline_datsview < 0)
- topline_datsview = 0;
- if (topline_datsview + r_visible_lines >= totallines)
- topline_datsview = totallines - r_visible_lines;
+ if (m_total_lines < r_visible_lines)
+ r_visible_lines = m_total_lines;
+ if (m_topline_datsview < 0)
+ m_topline_datsview = 0;
+ if (m_topline_datsview + r_visible_lines >= m_total_lines)
+ m_topline_datsview = m_total_lines - r_visible_lines;
sc = origx2 - origx1 - (2.0f * UI_BOX_LR_BORDER);
for (int r = 0; r < r_visible_lines; ++r)
{
- int itemline = r + topline_datsview;
+ int itemline = r + m_topline_datsview;
std::string tempbuf(buffer.substr(xstart[itemline], xend[itemline] - xstart[itemline]));
// up arrow
- if (r == 0 && topline_datsview != 0)
+ if (r == 0 && m_topline_datsview != 0)
info_arrow(0, origx1, origx2, oy1, line_height, text_size, ud_arrow_width);
// bottom arrow
- else if (r == r_visible_lines - 1 && itemline != totallines - 1)
+ else if (r == r_visible_lines - 1 && itemline != m_total_lines - 1)
info_arrow(1, origx1, origx2, oy1, line_height, text_size, ud_arrow_width);
// special case for mamescore
else if (ui_globals::curdats_view == UI_STORY_LOAD)
@@ -2159,7 +2160,7 @@ void menu_select_game::infos_render(void *selectedref, float origx1, float origy
}
// return the number of visible lines, minus 1 for top arrow and 1 for bottom arrow
- right_visible_lines = r_visible_lines - (topline_datsview != 0) - (topline_datsview + r_visible_lines != totallines);
+ right_visible_lines = r_visible_lines - (m_topline_datsview != 0) - (m_topline_datsview + r_visible_lines != m_total_lines);
}
else if (soft)
{
@@ -2233,26 +2234,26 @@ void menu_select_game::infos_render(void *selectedref, float origx1, float origy
return;
}
else
- totallines = ui().wrap_text(container, buffer.c_str(), origx1, origy1, origx2 - origx1 - (2.0f * gutter_width), xstart, xend, text_size);
+ m_total_lines = ui().wrap_text(container, buffer.c_str(), origx1, origy1, origx2 - origx1 - (2.0f * gutter_width), xstart, xend, text_size);
int r_visible_lines = floor((origy2 - oy1) / (line_height * text_size));
- if (totallines < r_visible_lines)
- r_visible_lines = totallines;
- if (topline_datsview < 0)
- topline_datsview = 0;
- if (topline_datsview + r_visible_lines >= totallines)
- topline_datsview = totallines - r_visible_lines;
+ if (m_total_lines < r_visible_lines)
+ r_visible_lines = m_total_lines;
+ if (m_topline_datsview < 0)
+ m_topline_datsview = 0;
+ if (m_topline_datsview + r_visible_lines >= m_total_lines)
+ m_topline_datsview = m_total_lines - r_visible_lines;
for (int r = 0; r < r_visible_lines; ++r)
{
- int itemline = r + topline_datsview;
+ int itemline = r + m_topline_datsview;
std::string tempbuf(buffer.substr(xstart[itemline], xend[itemline] - xstart[itemline]));
// up arrow
- if (r == 0 && topline_datsview != 0)
+ if (r == 0 && m_topline_datsview != 0)
info_arrow(0, origx1, origx2, oy1, line_height, text_size, ud_arrow_width);
// bottom arrow
- else if (r == r_visible_lines - 1 && itemline != totallines - 1)
+ else if (r == r_visible_lines - 1 && itemline != m_total_lines - 1)
info_arrow(1, origx1, origx2, oy1, line_height, text_size, ud_arrow_width);
else
ui().draw_text_full(container, tempbuf.c_str(), origx1 + gutter_width, oy1, origx2 - origx1, ui::text_layout::LEFT,
@@ -2261,7 +2262,7 @@ void menu_select_game::infos_render(void *selectedref, float origx1, float origy
}
// return the number of visible lines, minus 1 for top arrow and 1 for bottom arrow
- right_visible_lines = r_visible_lines - (topline_datsview != 0) - (topline_datsview + r_visible_lines != totallines);
+ right_visible_lines = r_visible_lines - (m_topline_datsview != 0) - (m_topline_datsview + r_visible_lines != m_total_lines);
}
}
diff --git a/src/frontend/mame/ui/selgame.h b/src/frontend/mame/ui/selgame.h
index b826dfaf5fc..153e353c93b 100644
--- a/src/frontend/mame/ui/selgame.h
+++ b/src/frontend/mame/ui/selgame.h
@@ -13,11 +13,11 @@
#ifndef MAME_FRONTEND_UI_SELGAME_H
#define MAME_FRONTEND_UI_SELGAME_H
-#include "ui/menu.h"
+#include "ui/selmenu.h"
namespace ui {
-class menu_select_game : public menu
+class menu_select_game : public menu_select_launch
{
public:
menu_select_game(mame_ui_manager &mui, render_container *container, const char *gamename);
diff --git a/src/frontend/mame/ui/selmenu.cpp b/src/frontend/mame/ui/selmenu.cpp
new file mode 100644
index 00000000000..3f7b70d5def
--- /dev/null
+++ b/src/frontend/mame/ui/selmenu.cpp
@@ -0,0 +1,1287 @@
+// license:BSD-3-Clause
+// copyright-holders:Nicola Salmoria, Aaron Giles, Nathan Woods
+/***************************************************************************
+
+ ui/selmenu.cpp
+
+ MAME system/software selection menu.
+
+***************************************************************************/
+
+#include "emu.h"
+
+#include "ui/selmenu.h"
+
+#include "ui/icorender.h"
+#include "ui/utils.h"
+
+// these hold static bitmap images
+#include "ui/defimg.h"
+#include "ui/starimg.h"
+#include "ui/toolbar.h"
+
+#include "cheat.h"
+#include "mame.h"
+
+#include "drivenum.h"
+#include "emuopts.h"
+#include "rendutil.h"
+#include "uiinput.h"
+
+#include <algorithm>
+#include <cmath>
+#include <cstring>
+#include <utility>
+
+
+namespace ui {
+namespace {
+std::pair<char const *, char const *> const arts_info[] =
+{
+ { __("Snapshots"), OPTION_SNAPSHOT_DIRECTORY },
+ { __("Cabinets"), OPTION_CABINETS_PATH },
+ { __("Control Panels"), OPTION_CPANELS_PATH },
+ { __("PCBs"), OPTION_PCBS_PATH },
+ { __("Flyers"), OPTION_FLYERS_PATH },
+ { __("Titles"), OPTION_TITLES_PATH },
+ { __("Ends"), OPTION_ENDS_PATH },
+ { __("Artwork Preview"), OPTION_ARTPREV_PATH },
+ { __("Bosses"), OPTION_BOSSES_PATH },
+ { __("Logos"), OPTION_LOGOS_PATH },
+ { __("Versus"), OPTION_VERSUS_PATH },
+ { __("Game Over"), OPTION_GAMEOVER_PATH },
+ { __("HowTo"), OPTION_HOWTO_PATH },
+ { __("Scores"), OPTION_SCORES_PATH },
+ { __("Select"), OPTION_SELECT_PATH },
+ { __("Marquees"), OPTION_MARQUEES_PATH },
+ { __("Covers"), OPTION_COVER_PATH },
+};
+
+char const *const hover_msg[] = {
+ __("Add or remove favorites"),
+ __("Export displayed list to file"),
+ __("Show DATs view"),
+};
+
+} // anonymous namespace
+
+
+std::mutex menu_select_launch::s_cache_guard;
+menu_select_launch::cache_ptr_map menu_select_launch::s_caches;
+
+
+menu_select_launch::cache::cache(running_machine &machine)
+ : m_no_avail_bitmap(std::make_unique<bitmap_argb32>(256, 256))
+ , m_star_bitmap(std::make_unique<bitmap_argb32>(32, 32))
+ , m_star_texture()
+ , m_toolbar_bitmap()
+ , m_sw_toolbar_bitmap()
+ , m_toolbar_texture()
+ , m_sw_toolbar_texture()
+{
+ render_manager &render(machine.render());
+ auto const texture_free([&render](render_texture *texture) { render.texture_free(texture); });
+
+ std::memcpy(&m_no_avail_bitmap->pix32(0), no_avail_bmp, 256 * 256 * sizeof(UINT32));
+ std::memcpy(&m_star_bitmap->pix32(0), favorite_star_bmp, 32 * 32 * sizeof(UINT32));
+
+ m_star_texture = texture_ptr(render.texture_alloc(), texture_free);
+ m_star_texture->set_bitmap(*m_star_bitmap, m_star_bitmap->cliprect(), TEXFORMAT_ARGB32);
+
+ m_toolbar_bitmap.reserve(UI_TOOLBAR_BUTTONS);
+ m_sw_toolbar_bitmap.reserve(UI_TOOLBAR_BUTTONS);
+ m_toolbar_texture.reserve(UI_TOOLBAR_BUTTONS);
+ m_sw_toolbar_texture.reserve(UI_TOOLBAR_BUTTONS);
+
+ for (std::size_t i = 0; i < UI_TOOLBAR_BUTTONS; ++i)
+ {
+ m_toolbar_bitmap.emplace_back(std::make_unique<bitmap_argb32>(32, 32));
+ m_sw_toolbar_bitmap.emplace_back(std::make_unique<bitmap_argb32>(32, 32));
+ m_toolbar_texture.emplace_back(texture_ptr(render.texture_alloc(), texture_free));
+ m_sw_toolbar_texture.emplace_back(texture_ptr(render.texture_alloc(), texture_free));
+
+ std::memcpy(&m_toolbar_bitmap.back()->pix32(0), toolbar_bitmap_bmp[i], 32 * 32 * sizeof(UINT32));
+ if (m_toolbar_bitmap.back()->valid())
+ m_toolbar_texture.back()->set_bitmap(*m_toolbar_bitmap.back(), m_toolbar_bitmap.back()->cliprect(), TEXFORMAT_ARGB32);
+ else
+ m_toolbar_bitmap.back()->reset();
+
+ if ((i == 0U) || (i == 2U))
+ {
+ std::memcpy(&m_sw_toolbar_bitmap.back()->pix32(0), toolbar_bitmap_bmp[i], 32 * 32 * sizeof(UINT32));
+ if (m_sw_toolbar_bitmap.back()->valid())
+ m_sw_toolbar_texture.back()->set_bitmap(*m_sw_toolbar_bitmap.back(), m_sw_toolbar_bitmap.back()->cliprect(), TEXFORMAT_ARGB32);
+ else
+ m_sw_toolbar_bitmap.back()->reset();
+ }
+ else
+ {
+ m_sw_toolbar_bitmap.back()->reset();
+ }
+ }
+}
+
+
+menu_select_launch::cache::~cache()
+{
+}
+
+
+menu_select_launch::~menu_select_launch()
+{
+ // need to manually clean up icon textures for now
+ for (auto &texture : m_icons_texture)
+ {
+ if (texture)
+ machine().render().texture_free(texture);
+ }
+}
+
+
+menu_select_launch::menu_select_launch(mame_ui_manager &mui, render_container *container, bool is_swlist)
+ : menu(mui, container)
+ , m_total_lines(0)
+ , m_topline_datsview(0)
+ , m_ui_error(false)
+ , m_cache()
+ , m_is_swlist(is_swlist)
+ , m_focus(focused_menu::main)
+ , m_pressed(false)
+ , m_repeat(0)
+{
+ // set up persistent cache for machine run
+ {
+ std::lock_guard<std::mutex> guard(s_cache_guard);
+ auto const found(s_caches.find(&machine()));
+ if (found != s_caches.end())
+ {
+ assert(found->second);
+ m_cache = found->second;
+ }
+ else
+ {
+ m_cache = std::make_shared<cache>(machine());
+ s_caches.emplace(&machine(), m_cache);
+ add_cleanup_callback(&menu_select_launch::exit);
+ }
+ }
+
+ // initialise icon cache
+ if (is_swlist)
+ {
+ std::fill(std::begin(m_icons_texture), std::end(m_icons_texture), nullptr);
+ }
+ else
+ {
+ std::generate(std::begin(m_icons_texture), std::end(m_icons_texture), [&render = machine().render()]() { return render.texture_alloc(); });
+ std::generate(std::begin(m_icons_bitmap), std::end(m_icons_bitmap), []() { return std::make_unique<bitmap_argb32>(); });
+ }
+ std::fill(std::begin(m_old_icons), std::end(m_old_icons), nullptr);
+}
+
+
+//-------------------------------------------------
+// draw right box title
+//-------------------------------------------------
+
+float menu_select_launch::draw_right_box_title(float x1, float y1, float x2, float y2)
+{
+ auto line_height = ui().get_line_height();
+ float midl = (x2 - x1) * 0.5f;
+
+ // add outlined box for options
+ ui().draw_outlined_box(container, x1, y1, x2, y2, UI_BACKGROUND_COLOR);
+
+ // add separator line
+ container->add_line(x1 + midl, y1, x1 + midl, y1 + line_height, UI_LINE_WIDTH, UI_BORDER_COLOR, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+
+ std::string buffer[RP_LAST + 1];
+ buffer[RP_IMAGES] = _("Images");
+ buffer[RP_INFOS] = _("Infos");
+
+ // check size
+ float text_size = 1.0f;
+ for (auto & elem : buffer)
+ {
+ auto textlen = ui().get_string_width(elem.c_str()) + 0.01f;
+ float tmp_size = (textlen > midl) ? (midl / textlen) : 1.0f;
+ text_size = MIN(text_size, tmp_size);
+ }
+
+ for (int cells = RP_FIRST; cells <= RP_LAST; ++cells)
+ {
+ rgb_t bgcolor = UI_TEXT_BG_COLOR;
+ rgb_t fgcolor = UI_TEXT_COLOR;
+
+ if (mouse_hit && x1 <= mouse_x && x1 + midl > mouse_x && y1 <= mouse_y && y1 + line_height > mouse_y)
+ {
+ if (ui_globals::rpanel != cells)
+ {
+ bgcolor = UI_MOUSEOVER_BG_COLOR;
+ fgcolor = UI_MOUSEOVER_COLOR;
+ hover = HOVER_RP_FIRST + cells;
+ }
+ }
+
+ if (ui_globals::rpanel != cells)
+ {
+ container->add_line(x1, y1 + line_height, x1 + midl, y1 + line_height, UI_LINE_WIDTH,
+ UI_BORDER_COLOR, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+ if (fgcolor != UI_MOUSEOVER_COLOR)
+ fgcolor = UI_CLONE_COLOR;
+ }
+
+ if (m_focus == focused_menu::righttop && ui_globals::rpanel == cells)
+ {
+ fgcolor = rgb_t(0xff, 0xff, 0x00);
+ bgcolor = rgb_t(0xff, 0xff, 0xff);
+ ui().draw_textured_box(container, x1 + UI_LINE_WIDTH, y1 + UI_LINE_WIDTH, x1 + midl - UI_LINE_WIDTH, y1 + line_height,
+ bgcolor, rgb_t(43, 43, 43), hilight_main_texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXWRAP(TRUE));
+ }
+ else if (bgcolor == UI_MOUSEOVER_BG_COLOR)
+ container->add_rect(x1 + UI_LINE_WIDTH, y1 + UI_LINE_WIDTH, x1 + midl - UI_LINE_WIDTH, y1 + line_height,
+ bgcolor, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXWRAP(TRUE));
+
+ ui().draw_text_full(container, buffer[cells].c_str(), x1 + UI_LINE_WIDTH, y1, midl - UI_LINE_WIDTH,
+ ui::text_layout::CENTER, ui::text_layout::NEVER, mame_ui_manager::NORMAL, fgcolor, bgcolor, nullptr, nullptr, text_size);
+ x1 += midl;
+ }
+
+ return (y1 + line_height + UI_LINE_WIDTH);
+}
+
+
+//-------------------------------------------------
+// common function for images render
+//-------------------------------------------------
+
+std::string menu_select_launch::arts_render_common(float origx1, float origy1, float origx2, float origy2)
+{
+ auto line_height = ui().get_line_height();
+ std::string snaptext, searchstr;
+ auto title_size = 0.0f;
+ auto txt_lenght = 0.0f;
+ auto gutter_width = 0.4f * line_height * machine().render().ui_aspect() * 1.3f;
+
+ get_title_search(snaptext, searchstr);
+
+ // apply title to right panel
+ for (int x = FIRST_VIEW; x < LAST_VIEW; x++)
+ {
+ ui().draw_text_full(container, _(arts_info[x].first), origx1, origy1, origx2 - origx1, ui::text_layout::CENTER,
+ ui::text_layout::TRUNCATE, mame_ui_manager::NONE, rgb_t::white, rgb_t::black, &txt_lenght, nullptr);
+ txt_lenght += 0.01f;
+ title_size = MAX(txt_lenght, title_size);
+ }
+
+ rgb_t fgcolor = (m_focus == focused_menu::rightbottom) ? rgb_t(0xff, 0xff, 0x00) : UI_TEXT_COLOR;
+ rgb_t bgcolor = (m_focus == focused_menu::rightbottom) ? rgb_t(0xff, 0xff, 0xff) : UI_TEXT_BG_COLOR;
+ float middle = origx2 - origx1;
+
+ // check size
+ float sc = title_size + 2.0f * gutter_width;
+ float tmp_size = (sc > middle) ? ((middle - 2.0f * gutter_width) / sc) : 1.0f;
+ title_size *= tmp_size;
+
+ if (bgcolor != UI_TEXT_BG_COLOR)
+ ui().draw_textured_box(container, origx1 + ((middle - title_size) * 0.5f), origy1, origx1 + ((middle + title_size) * 0.5f),
+ origy1 + line_height, bgcolor, rgb_t(43, 43, 43), hilight_main_texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXWRAP(TRUE));
+
+ ui().draw_text_full(container, snaptext.c_str(), origx1, origy1, origx2 - origx1, ui::text_layout::CENTER, ui::text_layout::TRUNCATE,
+ mame_ui_manager::NORMAL, fgcolor, bgcolor, nullptr, nullptr, tmp_size);
+
+ draw_common_arrow(origx1, origy1, origx2, origy2, ui_globals::curimage_view, FIRST_VIEW, LAST_VIEW, title_size);
+
+ return searchstr;
+}
+
+
+//-------------------------------------------------
+// perform rendering of image
+//-------------------------------------------------
+
+void menu_select_launch::arts_render_images(bitmap_argb32 *tmp_bitmap, float origx1, float origy1, float origx2, float origy2)
+{
+ bool no_available = false;
+ float line_height = ui().get_line_height();
+
+ // if it fails, use the default image
+ if (!tmp_bitmap->valid())
+ {
+ tmp_bitmap->allocate(256, 256);
+ const bitmap_argb32 &src(m_cache->no_avail_bitmap());
+ for (int x = 0; x < 256; x++)
+ {
+ for (int y = 0; y < 256; y++)
+ tmp_bitmap->pix32(y, x) = src.pix32(y, x);
+ }
+ no_available = true;
+ }
+
+ if (tmp_bitmap->valid())
+ {
+ float panel_width = origx2 - origx1 - 0.02f;
+ float panel_height = origy2 - origy1 - 0.02f - (2.0f * UI_BOX_TB_BORDER) - (2.0f * line_height);
+ int screen_width = machine().render().ui_target().width();
+ int screen_height = machine().render().ui_target().height();
+
+ if (machine().render().ui_target().orientation() & ORIENTATION_SWAP_XY)
+ std::swap(screen_height, screen_width);
+
+ int panel_width_pixel = panel_width * screen_width;
+ int panel_height_pixel = panel_height * screen_height;
+
+ // Calculate resize ratios for resizing
+ auto ratioW = (float)panel_width_pixel / tmp_bitmap->width();
+ auto ratioH = (float)panel_height_pixel / tmp_bitmap->height();
+ auto ratioI = (float)tmp_bitmap->height() / tmp_bitmap->width();
+ auto dest_xPixel = tmp_bitmap->width();
+ auto dest_yPixel = tmp_bitmap->height();
+
+ // force 4:3 ratio min
+ if (ui().options().forced_4x3_snapshot() && ratioI < 0.75f && ui_globals::curimage_view == SNAPSHOT_VIEW)
+ {
+ // smaller ratio will ensure that the image fits in the view
+ dest_yPixel = tmp_bitmap->width() * 0.75f;
+ ratioH = (float)panel_height_pixel / dest_yPixel;
+ float ratio = MIN(ratioW, ratioH);
+ dest_xPixel = tmp_bitmap->width() * ratio;
+ dest_yPixel *= ratio;
+ }
+ // resize the bitmap if necessary
+ else if (ratioW < 1 || ratioH < 1 || (ui().options().enlarge_snaps() && !no_available))
+ {
+ // smaller ratio will ensure that the image fits in the view
+ float ratio = MIN(ratioW, ratioH);
+ dest_xPixel = tmp_bitmap->width() * ratio;
+ dest_yPixel = tmp_bitmap->height() * ratio;
+ }
+
+ bitmap_argb32 *dest_bitmap;
+
+ // resample if necessary
+ if (dest_xPixel != tmp_bitmap->width() || dest_yPixel != tmp_bitmap->height())
+ {
+ dest_bitmap = auto_alloc(machine(), bitmap_argb32);
+ dest_bitmap->allocate(dest_xPixel, dest_yPixel);
+ render_color color = { 1.0f, 1.0f, 1.0f, 1.0f };
+ render_resample_argb_bitmap_hq(*dest_bitmap, *tmp_bitmap, color, true);
+ }
+ else
+ dest_bitmap = tmp_bitmap;
+
+ snapx_bitmap->allocate(panel_width_pixel, panel_height_pixel);
+ int x1 = (0.5f * panel_width_pixel) - (0.5f * dest_xPixel);
+ int y1 = (0.5f * panel_height_pixel) - (0.5f * dest_yPixel);
+
+ for (int x = 0; x < dest_xPixel; x++)
+ for (int y = 0; y < dest_yPixel; y++)
+ snapx_bitmap->pix32(y + y1, x + x1) = dest_bitmap->pix32(y, x);
+
+ auto_free(machine(), dest_bitmap);
+
+ // apply bitmap
+ snapx_texture->set_bitmap(*snapx_bitmap, snapx_bitmap->cliprect(), TEXFORMAT_ARGB32);
+ }
+ else
+ snapx_bitmap->reset();
+}
+
+
+//-------------------------------------------------
+// draw toolbar
+//-------------------------------------------------
+
+void menu_select_launch::draw_toolbar(float x1, float y1, float x2, float y2, bool software)
+{
+ // draw a box
+ ui().draw_outlined_box(container, x1, y1, x2, y2, rgb_t(0xEF, 0x12, 0x47, 0x7B));
+
+ // take off the borders
+ x1 += UI_BOX_LR_BORDER;
+ x2 -= UI_BOX_LR_BORDER;
+ y1 += UI_BOX_TB_BORDER;
+ y2 -= UI_BOX_TB_BORDER;
+
+ texture_ptr_vector const &t_texture = software ? m_cache->sw_toolbar_texture() : m_cache->toolbar_texture();
+ bitmap_ptr_vector const &t_bitmap = software ? m_cache->sw_toolbar_bitmap() : m_cache->toolbar_bitmap();
+
+ auto const num_valid(std::count_if(std::begin(t_bitmap), std::end(t_bitmap), [](bitmap_ptr const &e) { return e && e->valid(); }));
+
+ float const space_x = (y2 - y1) * container->manager().ui_aspect(container);
+ float const total = (float(num_valid) * space_x) + (float(num_valid - 1) * 0.001f);
+ x1 += (x2 - x1) * 0.5f - total * 0.5f;
+ x2 = x1 + space_x;
+
+ for (int z = 0; z < UI_TOOLBAR_BUTTONS; ++z)
+ {
+ if (t_bitmap[z] && t_bitmap[z]->valid())
+ {
+ rgb_t color(0xEFEFEFEF);
+ if (mouse_hit && x1 <= mouse_x && x2 > mouse_x && y1 <= mouse_y && y2 > mouse_y)
+ {
+ hover = HOVER_B_FAV + z;
+ color = rgb_t::white;
+ float ypos = y2 + ui().get_line_height() + 2.0f * UI_BOX_TB_BORDER;
+ ui().draw_text_box(container, _(hover_msg[z]), ui::text_layout::CENTER, 0.5f, ypos, UI_BACKGROUND_COLOR);
+ }
+
+ container->add_quad(x1, y1, x2, y2, color, t_texture[z].get(), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+ x1 += space_x + ((z < UI_TOOLBAR_BUTTONS - 1) ? 0.001f : 0.0f);
+ x2 = x1 + space_x;
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// draw favorites star
+//-------------------------------------------------
+
+void menu_select_launch::draw_star(float x0, float y0)
+{
+ float y1 = y0 + ui().get_line_height();
+ float x1 = x0 + ui().get_line_height() * container->manager().ui_aspect();
+ container->add_quad(x0, y0, x1, y1, rgb_t::white, m_cache->star_texture(), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_PACKABLE);
+}
+
+
+void menu_select_launch::set_pressed()
+{
+ (m_repeat == 0) ? m_repeat = osd_ticks() + osd_ticks_per_second() / 2 : m_repeat = osd_ticks() + osd_ticks_per_second() / 4;
+ m_pressed = true;
+}
+
+
+//-------------------------------------------------
+// draw icons
+//-------------------------------------------------
+
+float menu_select_launch::draw_icon(int linenum, void *selectedref, float x0, float y0)
+{
+ if (!ui_globals::has_icons || m_is_swlist)
+ return 0.0f;
+
+ float ud_arrow_width = ui().get_line_height() * container->manager().ui_aspect(container);
+ const game_driver *driver = nullptr;
+
+ if (item[0].flags & FLAG_UI_FAVORITE)
+ {
+ ui_software_info *soft = (ui_software_info *)selectedref;
+ if (soft->startempty == 1)
+ driver = soft->driver;
+ }
+ else
+ driver = (const game_driver *)selectedref;
+
+ auto x1 = x0 + ud_arrow_width;
+ auto y1 = y0 + ui().get_line_height();
+
+ if (m_old_icons[linenum] != driver || ui_globals::redraw_icon)
+ {
+ m_old_icons[linenum] = driver;
+
+ // set clone status
+ bool cloneof = strcmp(driver->parent, "0");
+ if (cloneof)
+ {
+ auto cx = driver_list::find(driver->parent);
+ if (cx != -1 && ((driver_list::driver(cx).flags & MACHINE_IS_BIOS_ROOT) != 0))
+ cloneof = false;
+ }
+
+ // get search path
+ path_iterator path(ui().options().icons_directory());
+ std::string curpath;
+ std::string searchstr(ui().options().icons_directory());
+
+ // iterate over path and add path for zipped formats
+ while (path.next(curpath))
+ searchstr.append(";").append(curpath.c_str()).append(PATH_SEPARATOR).append("icons");
+
+ bitmap_argb32 *tmp = auto_alloc(machine(), bitmap_argb32);
+ emu_file snapfile(searchstr.c_str(), OPEN_FLAG_READ);
+ std::string fullname = std::string(driver->name).append(".ico");
+ render_load_ico(*tmp, snapfile, nullptr, fullname.c_str());
+
+ if (!tmp->valid() && cloneof)
+ {
+ fullname.assign(driver->parent).append(".ico");
+ render_load_ico(*tmp, snapfile, nullptr, fullname.c_str());
+ }
+
+ if (tmp->valid())
+ {
+ float panel_width = x1 - x0;
+ float panel_height = y1 - y0;
+ auto screen_width = machine().render().ui_target().width();
+ auto screen_height = machine().render().ui_target().height();
+
+ if (machine().render().ui_target().orientation() & ORIENTATION_SWAP_XY)
+ std::swap(screen_height, screen_width);
+
+ int panel_width_pixel = panel_width * screen_width;
+ int panel_height_pixel = panel_height * screen_height;
+
+ // Calculate resize ratios for resizing
+ auto ratioW = (float)panel_width_pixel / tmp->width();
+ auto ratioH = (float)panel_height_pixel / tmp->height();
+ auto dest_xPixel = tmp->width();
+ auto dest_yPixel = tmp->height();
+
+ if (ratioW < 1 || ratioH < 1)
+ {
+ // smaller ratio will ensure that the image fits in the view
+ float ratio = MIN(ratioW, ratioH);
+ dest_xPixel = tmp->width() * ratio;
+ dest_yPixel = tmp->height() * ratio;
+ }
+
+ bitmap_argb32 *dest_bitmap;
+ dest_bitmap = auto_alloc(machine(), bitmap_argb32);
+
+ // resample if necessary
+ if (dest_xPixel != tmp->width() || dest_yPixel != tmp->height())
+ {
+ dest_bitmap->allocate(dest_xPixel, dest_yPixel);
+ render_color color = { 1.0f, 1.0f, 1.0f, 1.0f };
+ render_resample_argb_bitmap_hq(*dest_bitmap, *tmp, color, true);
+ }
+ else
+ dest_bitmap = tmp;
+
+ m_icons_bitmap[linenum]->allocate(panel_width_pixel, panel_height_pixel);
+
+ for (int x = 0; x < dest_xPixel; x++)
+ for (int y = 0; y < dest_yPixel; y++)
+ m_icons_bitmap[linenum]->pix32(y, x) = dest_bitmap->pix32(y, x);
+
+ auto_free(machine(), dest_bitmap);
+
+ m_icons_texture[linenum]->set_bitmap(*m_icons_bitmap[linenum], m_icons_bitmap[linenum]->cliprect(), TEXFORMAT_ARGB32);
+ }
+ else if (m_icons_bitmap[linenum] != nullptr)
+ m_icons_bitmap[linenum]->reset();
+
+ auto_free(machine(), tmp);
+ }
+
+ if (m_icons_bitmap[linenum] != nullptr && m_icons_bitmap[linenum]->valid())
+ container->add_quad(x0, y0, x1, y1, rgb_t::white, m_icons_texture[linenum], PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+
+ return ud_arrow_width * 1.5f;
+}
+
+
+//-------------------------------------------------
+// get title and search path for right panel
+//-------------------------------------------------
+
+void menu_select_launch::get_title_search(std::string &snaptext, std::string &searchstr)
+{
+ // get arts title text
+ snaptext.assign(_(arts_info[ui_globals::curimage_view].first));
+
+ // get search path
+ std::string addpath;
+ if (ui_globals::curimage_view == SNAPSHOT_VIEW)
+ {
+ emu_options moptions;
+ searchstr = machine().options().value(arts_info[ui_globals::curimage_view].second);
+ addpath = moptions.value(arts_info[ui_globals::curimage_view].second);
+ }
+ else
+ {
+ ui_options moptions;
+ searchstr = ui().options().value(arts_info[ui_globals::curimage_view].second);
+ addpath = moptions.value(arts_info[ui_globals::curimage_view].second);
+ }
+
+ std::string tmp(searchstr);
+ path_iterator path(tmp.c_str());
+ path_iterator path_iter(addpath.c_str());
+ std::string c_path, curpath;
+
+ // iterate over path and add path for zipped formats
+ while (path.next(curpath))
+ {
+ path_iter.reset();
+ while (path_iter.next(c_path))
+ searchstr.append(";").append(curpath).append(PATH_SEPARATOR).append(c_path);
+ }
+}
+
+
+//-------------------------------------------------
+// handle keys for main menu
+//-------------------------------------------------
+
+void menu_select_launch::handle_keys(UINT32 flags, int &iptkey)
+{
+ bool const ignorepause = stack_has_special_main_menu();
+
+ // bail if no items
+ if (item.size() == 0)
+ return;
+
+ // if we hit select, return TRUE or pop the stack, depending on the item
+ if (exclusive_input_pressed(iptkey, IPT_UI_SELECT, 0))
+ {
+ if (is_last_selected() && m_focus == focused_menu::main)
+ {
+ iptkey = IPT_UI_CANCEL;
+ stack_pop();
+ }
+ return;
+ }
+
+ // hitting cancel also pops the stack
+ if (exclusive_input_pressed(iptkey, IPT_UI_CANCEL, 0))
+ {
+ if (!m_ui_error && !menu_has_search_active())
+ stack_pop();
+ return;
+ }
+
+ // validate the current selection
+ validate_selection(1);
+
+ // swallow left/right keys if they are not appropriate
+ bool ignoreleft = ((item[selected].flags & FLAG_LEFT_ARROW) == 0);
+ bool ignoreright = ((item[selected].flags & FLAG_RIGHT_ARROW) == 0);
+ bool leftclose = (ui_globals::panels_status == HIDE_BOTH || ui_globals::panels_status == HIDE_LEFT_PANEL);
+ bool rightclose = (ui_globals::panels_status == HIDE_BOTH || ui_globals::panels_status == HIDE_RIGHT_PANEL);
+
+ // accept left/right keys as-is with repeat
+ if (!ignoreleft && exclusive_input_pressed(iptkey, IPT_UI_LEFT, (flags & PROCESS_LR_REPEAT) ? 6 : 0))
+ {
+ // Swap the right panel
+ if (m_focus == focused_menu::righttop)
+ iptkey = IPT_UI_LEFT_PANEL;
+ return;
+ }
+
+ if (!ignoreright && exclusive_input_pressed(iptkey, IPT_UI_RIGHT, (flags & PROCESS_LR_REPEAT) ? 6 : 0))
+ {
+ // Swap the right panel
+ if (m_focus == focused_menu::righttop)
+ iptkey = IPT_UI_RIGHT_PANEL;
+ return;
+ }
+
+ // up backs up by one item
+ if (exclusive_input_pressed(iptkey, IPT_UI_UP, 6))
+ {
+ // Filter
+ if (!leftclose && m_focus == focused_menu::left)
+ {
+ iptkey = IPT_UI_UP_FILTER;
+ return;
+ }
+
+ // Infos
+ if (!rightclose && m_focus == focused_menu::rightbottom)
+ {
+ iptkey = IPT_UI_UP_PANEL;
+ m_topline_datsview--;
+ return;
+ }
+
+ if (selected == visible_items + 1 || is_first_selected() || m_ui_error)
+ return;
+
+ selected--;
+
+ if (selected == top_line && top_line != 0)
+ top_line--;
+ }
+
+ // down advances by one item
+ if (exclusive_input_pressed(iptkey, IPT_UI_DOWN, 6))
+ {
+ // Filter
+ if (!leftclose && m_focus == focused_menu::left)
+ {
+ iptkey = IPT_UI_DOWN_FILTER;
+ return;
+ }
+
+ // Infos
+ if (!rightclose && m_focus == focused_menu::rightbottom)
+ {
+ iptkey = IPT_UI_DOWN_PANEL;
+ m_topline_datsview++;
+ return;
+ }
+
+ if (is_last_selected() || selected == visible_items - 1 || m_ui_error)
+ return;
+
+ selected++;
+
+ if (selected == top_line + m_visible_items + (top_line != 0))
+ top_line++;
+ }
+
+ // page up backs up by m_visible_items
+ if (exclusive_input_pressed(iptkey, IPT_UI_PAGE_UP, 6))
+ {
+ // Infos
+ if (!rightclose && m_focus == focused_menu::rightbottom)
+ {
+ iptkey = IPT_UI_DOWN_PANEL;
+ m_topline_datsview -= right_visible_lines - 1;
+ return;
+ }
+
+ if (selected < visible_items && !m_ui_error)
+ {
+ selected -= m_visible_items;
+
+ if (selected < 0)
+ selected = 0;
+
+ top_line -= m_visible_items - (top_line + m_visible_lines == visible_items);
+ }
+ }
+
+ // page down advances by m_visible_items
+ if (exclusive_input_pressed(iptkey, IPT_UI_PAGE_DOWN, 6))
+ {
+ // Infos
+ if (!rightclose && m_focus == focused_menu::rightbottom)
+ {
+ iptkey = IPT_UI_DOWN_PANEL;
+ m_topline_datsview += right_visible_lines - 1;
+ return;
+ }
+
+ if (selected < visible_items && !m_ui_error)
+ {
+ selected += m_visible_lines - 2 + (selected == 0);
+
+ if (selected >= visible_items)
+ selected = visible_items - 1;
+
+ top_line += m_visible_lines - 2;
+ }
+ }
+
+ // home goes to the start
+ if (exclusive_input_pressed(iptkey, IPT_UI_HOME, 0))
+ {
+ // Infos
+ if (!rightclose && m_focus == focused_menu::rightbottom)
+ {
+ iptkey = IPT_UI_DOWN_PANEL;
+ m_topline_datsview = 0;
+ return;
+ }
+
+ if (selected < visible_items && !m_ui_error)
+ {
+ selected = 0;
+ top_line = 0;
+ }
+ }
+
+ // end goes to the last
+ if (exclusive_input_pressed(iptkey, IPT_UI_END, 0))
+ {
+ // Infos
+ if (!rightclose && m_focus == focused_menu::rightbottom)
+ {
+ iptkey = IPT_UI_DOWN_PANEL;
+ m_topline_datsview = m_total_lines;
+ return;
+ }
+
+ if (selected < visible_items && !m_ui_error)
+ selected = top_line = visible_items - 1;
+ }
+
+ // pause enables/disables pause
+ if (!m_ui_error && !ignorepause && exclusive_input_pressed(iptkey, IPT_UI_PAUSE, 0))
+ {
+ if (machine().paused())
+ machine().resume();
+ else
+ machine().pause();
+ }
+
+ // handle a toggle cheats request
+ if (!m_ui_error && machine().ui_input().pressed_repeat(IPT_UI_TOGGLE_CHEAT, 0))
+ mame_machine_manager::instance()->cheat().set_enable(!mame_machine_manager::instance()->cheat().enabled());
+
+ // see if any other UI keys are pressed
+ if (iptkey == IPT_INVALID)
+ {
+ for (int code = IPT_UI_FIRST + 1; code < IPT_UI_LAST; code++)
+ {
+ if (m_ui_error || code == IPT_UI_CONFIGURE || (code == IPT_UI_LEFT && ignoreleft) || (code == IPT_UI_RIGHT && ignoreright) || (code == IPT_UI_PAUSE && ignorepause))
+ continue;
+
+ if (exclusive_input_pressed(iptkey, code, 0))
+ break;
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// handle input events for main menu
+//-------------------------------------------------
+
+void menu_select_launch::handle_events(UINT32 flags, event &ev)
+{
+ auto stop = false;
+ ui_event local_menu_event;
+
+ if (m_pressed)
+ {
+ bool pressed = mouse_pressed();
+ INT32 m_target_x, m_target_y;
+ bool m_button;
+ auto mouse_target = machine().ui_input().find_mouse(&m_target_x, &m_target_y, &m_button);
+ if (mouse_target && m_button && (hover == HOVER_ARROW_DOWN || hover == HOVER_ARROW_UP))
+ {
+ if (pressed)
+ machine().ui_input().push_mouse_down_event(mouse_target, m_target_x, m_target_y);
+ }
+ else
+ reset_pressed();
+ }
+
+ // loop while we have interesting events
+ while (!stop && machine().ui_input().pop_event(&local_menu_event))
+ {
+ switch (local_menu_event.event_type)
+ {
+ // if we are hovering over a valid item, select it with a single click
+ case UI_EVENT_MOUSE_DOWN:
+ {
+ if (m_ui_error)
+ {
+ ev.iptkey = IPT_OTHER;
+ stop = true;
+ }
+ else
+ {
+ if (hover >= 0 && hover < item.size())
+ {
+ if (hover >= visible_items - 1 && selected < visible_items)
+ m_prev_selected = item[selected].ref;
+ selected = hover;
+ m_focus = focused_menu::main;
+ }
+ else if (hover == HOVER_ARROW_UP)
+ {
+ selected -= m_visible_items;
+ if (selected < 0)
+ selected = 0;
+ top_line -= m_visible_items - (top_line + m_visible_lines == visible_items);
+ set_pressed();
+ }
+ else if (hover == HOVER_ARROW_DOWN)
+ {
+ selected += m_visible_lines - 2 + (selected == 0);
+ if (selected >= visible_items)
+ selected = visible_items - 1;
+ top_line += m_visible_lines - 2;
+ set_pressed();
+ }
+ else if (hover == HOVER_UI_RIGHT)
+ ev.iptkey = IPT_UI_RIGHT;
+ else if (hover == HOVER_UI_LEFT)
+ ev.iptkey = IPT_UI_LEFT;
+ else if (hover == HOVER_DAT_DOWN)
+ m_topline_datsview += right_visible_lines - 1;
+ else if (hover == HOVER_DAT_UP)
+ m_topline_datsview -= right_visible_lines - 1;
+ else if (hover == HOVER_LPANEL_ARROW)
+ {
+ if (ui_globals::panels_status == HIDE_LEFT_PANEL)
+ ui_globals::panels_status = SHOW_PANELS;
+ else if (ui_globals::panels_status == HIDE_BOTH)
+ ui_globals::panels_status = HIDE_RIGHT_PANEL;
+ else if (ui_globals::panels_status == SHOW_PANELS)
+ ui_globals::panels_status = HIDE_LEFT_PANEL;
+ else if (ui_globals::panels_status == HIDE_RIGHT_PANEL)
+ ui_globals::panels_status = HIDE_BOTH;
+ }
+ else if (hover == HOVER_RPANEL_ARROW)
+ {
+ if (ui_globals::panels_status == HIDE_RIGHT_PANEL)
+ ui_globals::panels_status = SHOW_PANELS;
+ else if (ui_globals::panels_status == HIDE_BOTH)
+ ui_globals::panels_status = HIDE_LEFT_PANEL;
+ else if (ui_globals::panels_status == SHOW_PANELS)
+ ui_globals::panels_status = HIDE_RIGHT_PANEL;
+ else if (ui_globals::panels_status == HIDE_LEFT_PANEL)
+ ui_globals::panels_status = HIDE_BOTH;
+ }
+ else if (hover == HOVER_B_FAV)
+ {
+ ev.iptkey = IPT_UI_FAVORITES;
+ stop = true;
+ }
+ else if (hover == HOVER_B_EXPORT)
+ {
+ ev.iptkey = IPT_UI_EXPORT;
+ stop = true;
+ }
+ else if (hover == HOVER_B_DATS)
+ {
+ ev.iptkey = IPT_UI_DATS;
+ stop = true;
+ }
+ else if (hover >= HOVER_RP_FIRST && hover <= HOVER_RP_LAST)
+ {
+ ui_globals::rpanel = (HOVER_RP_FIRST - hover) * (-1);
+ stop = true;
+ }
+ else if (hover >= HOVER_SW_FILTER_FIRST && hover <= HOVER_SW_FILTER_LAST)
+ {
+ l_sw_hover = (HOVER_SW_FILTER_FIRST - hover) * (-1);
+ ev.iptkey = IPT_OTHER;
+ stop = true;
+ }
+ else if (hover >= HOVER_FILTER_FIRST && hover <= HOVER_FILTER_LAST)
+ {
+ l_hover = (HOVER_FILTER_FIRST - hover) * (-1);
+ ev.iptkey = IPT_OTHER;
+ stop = true;
+ }
+ }
+ break;
+ }
+
+ // if we are hovering over a valid item, fake a UI_SELECT with a double-click
+ case UI_EVENT_MOUSE_DOUBLE_CLICK:
+ if (hover >= 0 && hover < item.size())
+ {
+ selected = hover;
+ ev.iptkey = IPT_UI_SELECT;
+ }
+
+ if (selected == item.size() - 1)
+ {
+ ev.iptkey = IPT_UI_CANCEL;
+ stack_pop();
+ }
+ stop = true;
+ break;
+
+ // caught scroll event
+ case UI_EVENT_MOUSE_WHEEL:
+ if (hover >= 0 && hover < item.size() - skip_main_items - 1)
+ {
+ if (local_menu_event.zdelta > 0)
+ {
+ if (selected >= visible_items || selected == 0 || m_ui_error)
+ break;
+ selected -= local_menu_event.num_lines;
+ if (selected < top_line + (top_line != 0))
+ top_line -= local_menu_event.num_lines;
+ }
+ else
+ {
+ if (selected >= visible_items - 1 || m_ui_error)
+ break;
+ selected += local_menu_event.num_lines;
+ if (selected > visible_items - 1)
+ selected = visible_items - 1;
+ if (selected >= top_line + m_visible_items + (top_line != 0))
+ top_line += local_menu_event.num_lines;
+ }
+ }
+ break;
+
+ // translate CHAR events into specials
+ case UI_EVENT_CHAR:
+ if (exclusive_input_pressed(ev.iptkey, IPT_UI_CONFIGURE, 0))
+ {
+ ev.iptkey = IPT_UI_CONFIGURE;
+ stop = true;
+ }
+ else
+ {
+ ev.iptkey = IPT_SPECIAL;
+ ev.unichar = local_menu_event.ch;
+ stop = true;
+ }
+ break;
+
+ case UI_EVENT_MOUSE_RDOWN:
+ if (hover >= 0 && hover < item.size() - skip_main_items - 1)
+ {
+ selected = hover;
+ m_prev_selected = item[selected].ref;
+ m_focus = focused_menu::main;
+ ev.iptkey = IPT_CUSTOM;
+ ev.mouse.x0 = local_menu_event.mouse_x;
+ ev.mouse.y0 = local_menu_event.mouse_y;
+ stop = true;
+ }
+ break;
+
+ // ignore everything else
+ default:
+ break;
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// draw main menu
+//-------------------------------------------------
+
+void menu_select_launch::draw(UINT32 flags)
+{
+ bool noinput = (flags & PROCESS_NOINPUT);
+ float line_height = ui().get_line_height();
+ float ud_arrow_width = line_height * machine().render().ui_aspect();
+ float gutter_width = 0.52f * ud_arrow_width;
+ mouse_x = -1, mouse_y = -1;
+ float right_panel_size = (ui_globals::panels_status == HIDE_BOTH || ui_globals::panels_status == HIDE_RIGHT_PANEL) ? 2.0f * UI_BOX_LR_BORDER : 0.3f;
+ float visible_width = 1.0f - 4.0f * UI_BOX_LR_BORDER;
+ float primary_left = (1.0f - visible_width) * 0.5f;
+ float primary_width = visible_width;
+
+ draw_background();
+
+ hover = item.size() + 1;
+ visible_items = (m_is_swlist) ? item.size() - 2 : item.size() - 2 - skip_main_items;
+ float extra_height = (m_is_swlist) ? 2.0f * line_height : (2.0f + skip_main_items) * line_height;
+ float visible_extra_menu_height = customtop + custombottom + extra_height;
+
+ // locate mouse
+ mouse_hit = false;
+ mouse_button = false;
+ if (!noinput)
+ {
+ mouse_target = machine().ui_input().find_mouse(&mouse_target_x, &mouse_target_y, &mouse_button);
+ if (mouse_target)
+ if (mouse_target->map_point_container(mouse_target_x, mouse_target_y, *container, mouse_x, mouse_y))
+ mouse_hit = true;
+ }
+
+ // account for extra space at the top and bottom
+ float visible_main_menu_height = 1.0f - 2.0f * UI_BOX_TB_BORDER - visible_extra_menu_height;
+ m_visible_lines = int(std::trunc(visible_main_menu_height / line_height));
+ visible_main_menu_height = float(m_visible_lines) * line_height;
+
+ if (!m_is_swlist)
+ ui_globals::visible_main_lines = m_visible_lines;
+ else
+ ui_globals::visible_sw_lines = m_visible_lines;
+
+ // compute top/left of inner menu area by centering
+ float visible_left = primary_left;
+ float visible_top = (1.0f - (visible_main_menu_height + visible_extra_menu_height)) * 0.5f;
+
+ // if the menu is at the bottom of the extra, adjust
+ visible_top += customtop;
+
+ // compute left box size
+ float x1 = visible_left - UI_BOX_LR_BORDER;
+ float y1 = visible_top - UI_BOX_TB_BORDER;
+ float x2 = x1 + 2.0f * UI_BOX_LR_BORDER;
+ float y2 = visible_top + visible_main_menu_height + UI_BOX_TB_BORDER + extra_height;
+
+ // add left box
+ visible_left = draw_left_panel(x1, y1, x2, y2);
+ visible_width -= right_panel_size + visible_left - 2.0f * UI_BOX_LR_BORDER;
+
+ // compute and add main box
+ x1 = visible_left - UI_BOX_LR_BORDER;
+ x2 = visible_left + visible_width + UI_BOX_LR_BORDER;
+ float line = visible_top + (float(m_visible_lines) * line_height);
+ ui().draw_outlined_box(container, x1, y1, x2, y2, UI_BACKGROUND_COLOR);
+
+ if (visible_items < m_visible_lines)
+ m_visible_lines = visible_items;
+ if (top_line < 0 || is_first_selected())
+ top_line = 0;
+ if (selected < visible_items && top_line + m_visible_lines >= visible_items)
+ top_line = visible_items - m_visible_lines;
+
+ // 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;
+
+ if (m_prev_selected != nullptr && m_focus == focused_menu::main && selected < visible_items)
+ m_prev_selected = nullptr;
+
+ int const n_loop = (std::min)(m_visible_lines, visible_items);
+ for (int linenum = 0; linenum < n_loop; linenum++)
+ {
+ float line_y = visible_top + (float)linenum * line_height;
+ int itemnum = top_line + linenum;
+ const menu_item &pitem = item[itemnum];
+ const char *itemtext = pitem.text.c_str();
+ rgb_t fgcolor = UI_TEXT_COLOR;
+ rgb_t bgcolor = UI_TEXT_BG_COLOR;
+ rgb_t fgcolor3 = UI_CLONE_COLOR;
+ float line_x0 = x1 + 0.5f * UI_LINE_WIDTH;
+ float line_y0 = line_y;
+ float line_x1 = x2 - 0.5f * UI_LINE_WIDTH;
+ float line_y1 = line_y + line_height;
+
+ // set the hover if this is our item
+ if (mouse_hit && line_x0 <= mouse_x && line_x1 > mouse_x && line_y0 <= mouse_y && line_y1 > mouse_y && is_selectable(pitem))
+ hover = itemnum;
+
+ // if we're selected, draw with a different background
+ if (itemnum == selected && m_focus == focused_menu::main)
+ {
+ fgcolor = rgb_t(0xff, 0xff, 0x00);
+ bgcolor = rgb_t(0xff, 0xff, 0xff);
+ fgcolor3 = rgb_t(0xcc, 0xcc, 0x00);
+ ui().draw_textured_box(container, line_x0 + 0.01f, line_y0, line_x1 - 0.01f, line_y1, bgcolor, rgb_t(43, 43, 43),
+ hilight_main_texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXWRAP(TRUE));
+ }
+ // else if the mouse is over this item, draw with a different background
+ else if (itemnum == hover)
+ {
+ fgcolor = fgcolor3 = UI_MOUSEOVER_COLOR;
+ bgcolor = UI_MOUSEOVER_BG_COLOR;
+ highlight(container, line_x0, line_y0, line_x1, line_y1, bgcolor);
+ }
+ else if (pitem.ref == m_prev_selected)
+ {
+ fgcolor = fgcolor3 = UI_MOUSEOVER_COLOR;
+ bgcolor = UI_MOUSEOVER_BG_COLOR;
+ ui().draw_textured_box(container, line_x0 + 0.01f, line_y0, line_x1 - 0.01f, line_y1, bgcolor, rgb_t(43, 43, 43),
+ hilight_main_texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXWRAP(TRUE));
+ }
+
+ if (linenum == 0 && top_line != 0)
+ {
+ // if we're on the top line, display the up arrow
+ draw_arrow(container, 0.5f * (x1 + x2) - 0.5f * ud_arrow_width, line_y + 0.25f * line_height,
+ 0.5f * (x1 + x2) + 0.5f * ud_arrow_width, line_y + 0.75f * line_height, fgcolor, ROT0);
+
+ if (hover == itemnum)
+ hover = HOVER_ARROW_UP;
+ }
+ else if (linenum == m_visible_lines - 1 && itemnum != visible_items - 1)
+ {
+ // if we're on the bottom line, display the down arrow
+ draw_arrow(container, 0.5f * (x1 + x2) - 0.5f * ud_arrow_width, line_y + 0.25f * line_height,
+ 0.5f * (x1 + x2) + 0.5f * ud_arrow_width, line_y + 0.75f * line_height, fgcolor, ROT0 ^ ORIENTATION_FLIP_Y);
+
+ if (hover == itemnum)
+ hover = HOVER_ARROW_DOWN;
+ }
+ else if (pitem.type == menu_item_type::SEPARATOR)
+ {
+ // if we're just a divider, draw a line
+ container->add_line(visible_left, line_y + 0.5f * line_height, visible_left + visible_width, line_y + 0.5f * line_height,
+ UI_LINE_WIDTH, UI_TEXT_COLOR, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+ }
+ else if (pitem.subtext.empty())
+ {
+ // draw the item centered
+ int item_invert = pitem.flags & FLAG_INVERT;
+ auto icon = draw_icon(linenum, item[itemnum].ref, effective_left, line_y);
+ ui().draw_text_full(container, itemtext, effective_left + icon, line_y, effective_width - icon, ui::text_layout::LEFT, ui::text_layout::TRUNCATE,
+ mame_ui_manager::NORMAL, item_invert ? fgcolor3 : fgcolor, bgcolor, nullptr, nullptr);
+ }
+ else
+ {
+ auto item_invert = pitem.flags & FLAG_INVERT;
+ const char *subitem_text = pitem.subtext.c_str();
+ float item_width, subitem_width;
+
+ // compute right space for subitem
+ ui().draw_text_full(container, subitem_text, effective_left, line_y, ui().get_string_width(pitem.subtext.c_str()),
+ ui::text_layout::RIGHT, ui::text_layout::NEVER, mame_ui_manager::NONE, item_invert ? fgcolor3 : fgcolor, bgcolor, &subitem_width, nullptr);
+ subitem_width += gutter_width;
+
+ // draw the item left-justified
+ ui().draw_text_full(container, itemtext, effective_left, line_y, effective_width - subitem_width,
+ ui::text_layout::LEFT, ui::text_layout::TRUNCATE, mame_ui_manager::NORMAL, item_invert ? fgcolor3 : fgcolor, bgcolor, &item_width, nullptr);
+
+ // draw the subitem right-justified
+ ui().draw_text_full(container, subitem_text, effective_left + item_width, line_y, effective_width - item_width,
+ ui::text_layout::RIGHT, ui::text_layout::NEVER, mame_ui_manager::NORMAL, item_invert ? fgcolor3 : fgcolor, bgcolor, nullptr, nullptr);
+ }
+ }
+
+ for (size_t count = visible_items; count < item.size(); count++)
+ {
+ const menu_item &pitem = item[count];
+ const char *itemtext = pitem.text.c_str();
+ float line_x0 = x1 + 0.5f * UI_LINE_WIDTH;
+ float line_y0 = line;
+ float line_x1 = x2 - 0.5f * UI_LINE_WIDTH;
+ float line_y1 = line + line_height;
+ rgb_t fgcolor = UI_TEXT_COLOR;
+ rgb_t bgcolor = UI_TEXT_BG_COLOR;
+
+ if (mouse_hit && line_x0 <= mouse_x && line_x1 > mouse_x && line_y0 <= mouse_y && line_y1 > mouse_y && is_selectable(pitem))
+ hover = count;
+
+ // if we're selected, draw with a different background
+ if (count == selected && m_focus == focused_menu::main)
+ {
+ fgcolor = rgb_t(0xff, 0xff, 0x00);
+ bgcolor = rgb_t(0xff, 0xff, 0xff);
+ ui().draw_textured_box(container, line_x0 + 0.01f, line_y0, line_x1 - 0.01f, line_y1, bgcolor, rgb_t(43, 43, 43),
+ hilight_main_texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXWRAP(TRUE));
+ }
+ // else if the mouse is over this item, draw with a different background
+ else if (count == hover)
+ {
+ fgcolor = UI_MOUSEOVER_COLOR;
+ bgcolor = UI_MOUSEOVER_BG_COLOR;
+ highlight(container, line_x0, line_y0, line_x1, line_y1, bgcolor);
+ }
+
+ if (pitem.type == menu_item_type::SEPARATOR)
+ container->add_line(visible_left, line + 0.5f * line_height, visible_left + visible_width, line + 0.5f * line_height,
+ UI_LINE_WIDTH, UI_TEXT_COLOR, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+ else
+ ui().draw_text_full(container, itemtext, effective_left, line, effective_width, ui::text_layout::CENTER, ui::text_layout::TRUNCATE,
+ mame_ui_manager::NORMAL, fgcolor, bgcolor, nullptr, nullptr);
+ line += line_height;
+ }
+
+ x1 = x2;
+ x2 += right_panel_size;
+
+ draw_right_panel(get_selection_ref(), x1, y1, x2, y2);
+
+ x1 = primary_left - UI_BOX_LR_BORDER;
+ x2 = primary_left + primary_width + UI_BOX_LR_BORDER;
+
+ // if there is something special to add, do it by calling the virtual method
+ custom_render(get_selection_ref(), customtop, custombottom, x1, y1, x2, y2);
+
+ // return the number of visible lines, minus 1 for top arrow and 1 for bottom arrow
+ m_visible_items = m_visible_lines - (top_line != 0) - (top_line + m_visible_lines != visible_items);
+
+ // reset redraw icon stage
+ if (!m_is_swlist) ui_globals::redraw_icon = false;
+
+ // noinput
+ if (noinput)
+ {
+ int alpha = (1.0f - machine().options().pause_brightness()) * 255.0f;
+ if (alpha > 255)
+ alpha = 255;
+ if (alpha >= 0)
+ container->add_rect(0.0f, 0.0f, 1.0f, 1.0f, rgb_t(alpha, 0x00, 0x00, 0x00), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+ }
+}
+
+
+void menu_select_launch::exit(running_machine &machine)
+{
+ std::lock_guard<std::mutex> guard(s_cache_guard);
+ s_caches.erase(&machine);
+}
+
+} // namespace ui \ No newline at end of file
diff --git a/src/frontend/mame/ui/selmenu.h b/src/frontend/mame/ui/selmenu.h
new file mode 100644
index 00000000000..26f1706c2c4
--- /dev/null
+++ b/src/frontend/mame/ui/selmenu.h
@@ -0,0 +1,134 @@
+// license:BSD-3-Clause
+// copyright-holders:Nicola Salmoria, Aaron Giles, Nathan Woods
+/***************************************************************************
+
+ ui/selmenu.h
+
+ MAME system/software selection menu.
+
+***************************************************************************/
+
+#ifndef MAME_FRONTEND_UI_SELMENU_H
+#define MAME_FRONTEND_UI_SELMENU_H
+
+#pragma once
+
+#include "ui/menu.h"
+
+#include <map>
+#include <memory>
+#include <mutex>
+#include <vector>
+
+
+namespace ui {
+class menu_select_launch : public menu
+{
+public:
+
+ virtual ~menu_select_launch() override;
+
+protected:
+
+ // tab navigation
+ enum class focused_menu
+ {
+ main,
+ left,
+ righttop,
+ rightbottom
+ };
+
+ menu_select_launch(mame_ui_manager &mui, render_container *container, bool is_swlist);
+
+ focused_menu get_focus() const { return m_focus; }
+ void set_focus(focused_menu focus) { m_focus = focus; }
+
+ // draw right box
+ float draw_right_box_title(float x1, float y1, float x2, float y2);
+
+ // images render
+ std::string arts_render_common(float origx1, float origy1, float origx2, float origy2);
+ void arts_render_images(bitmap_argb32 *bitmap, float origx1, float origy1, float origx2, float origy2);
+
+ // draw toolbar
+ void draw_toolbar(float x1, float y1, float x2, float y2, bool software = false);
+
+ // draw star
+ void draw_star(float x0, float y0);
+
+ int visible_items;
+ int m_total_lines;
+ int m_topline_datsview; // right box top line
+ bool m_ui_error;
+
+private:
+ using bitmap_ptr_vector = std::vector<bitmap_ptr>;
+ using texture_ptr_vector = std::vector<texture_ptr>;
+
+ class cache
+ {
+ public:
+ cache(running_machine &machine);
+ ~cache();
+
+ bitmap_argb32 &no_avail_bitmap() { return *m_no_avail_bitmap; }
+ render_texture *star_texture() { return m_star_texture.get(); }
+
+ bitmap_ptr_vector const &toolbar_bitmap() { return m_toolbar_bitmap; }
+ bitmap_ptr_vector const &sw_toolbar_bitmap() { return m_sw_toolbar_bitmap; }
+ texture_ptr_vector const &toolbar_texture() { return m_toolbar_texture; }
+ texture_ptr_vector const &sw_toolbar_texture() { return m_sw_toolbar_texture; }
+
+ private:
+ bitmap_ptr m_no_avail_bitmap;
+ bitmap_ptr m_star_bitmap;
+ texture_ptr m_star_texture;
+
+ bitmap_ptr_vector m_toolbar_bitmap;
+ bitmap_ptr_vector m_sw_toolbar_bitmap;
+ texture_ptr_vector m_toolbar_texture;
+ texture_ptr_vector m_sw_toolbar_texture;
+ };
+ using cache_ptr = std::shared_ptr<cache>;
+ using cache_ptr_map = std::map<running_machine *, cache_ptr>;
+
+ static constexpr std::size_t MAX_ICONS_RENDER = 40;
+
+ void reset_pressed() { m_pressed = false; m_repeat = 0; }
+ bool mouse_pressed() const { return (osd_ticks() >= m_repeat); }
+ void set_pressed();
+
+ float draw_icon(int linenum, void *selectedref, float x1, float y1);
+
+ void get_title_search(std::string &title, std::string &search);
+
+ // handle keys
+ virtual void handle_keys(UINT32 flags, int &iptkey) override;
+
+ // handle mouse
+ virtual void handle_events(UINT32 flags, event &ev) override;
+
+ // draw game list
+ virtual void draw(UINT32 flags) override;
+
+ // cleanup function
+ static void exit(running_machine &machine);
+
+ cache_ptr m_cache;
+ bool m_is_swlist;
+ focused_menu m_focus;
+ bool m_pressed; // mouse button held down
+ osd_ticks_t m_repeat;
+
+ render_texture *m_icons_texture[MAX_ICONS_RENDER];
+ bitmap_ptr m_icons_bitmap[MAX_ICONS_RENDER];
+ game_driver const *m_old_icons[MAX_ICONS_RENDER];
+
+ static std::mutex s_cache_guard;
+ static cache_ptr_map s_caches;
+};
+
+} // namespace ui
+
+#endif // MAME_FRONTEND_UI_SELMENU_H \ No newline at end of file
diff --git a/src/frontend/mame/ui/selsoft.cpp b/src/frontend/mame/ui/selsoft.cpp
index d29d768ce76..bf6763171b2 100644
--- a/src/frontend/mame/ui/selsoft.cpp
+++ b/src/frontend/mame/ui/selsoft.cpp
@@ -125,7 +125,8 @@ bool has_multiple_bios(const game_driver *driver, s_bios &biosname)
// ctor
//-------------------------------------------------
-menu_select_software::menu_select_software(mame_ui_manager &mui, render_container *container, const game_driver *driver) : menu(mui, container)
+menu_select_software::menu_select_software(mame_ui_manager &mui, render_container *container, const game_driver *driver)
+ : menu_select_launch(mui, container, true)
{
if (reselect_last::get())
reselect_last::set(false);
@@ -174,10 +175,10 @@ void menu_select_software::handle()
if (menu_event && menu_event->itemref)
{
- if (ui_error)
+ if (m_ui_error)
{
// reset the error on any future event
- ui_error = false;
+ m_ui_error = false;
machine().ui_input().reset();
}
else if (menu_event->iptkey == IPT_UI_SELECT)
@@ -208,7 +209,7 @@ void menu_select_software::handle()
{
// Infos
ui_globals::cur_sw_dats_view--;
- topline_datsview = 0;
+ m_topline_datsview = 0;
}
}
else if (menu_event->iptkey == IPT_UI_RIGHT)
@@ -225,7 +226,7 @@ void menu_select_software::handle()
{
// Infos
ui_globals::cur_sw_dats_view++;
- topline_datsview = 0;
+ m_topline_datsview = 0;
}
}
else if (menu_event->iptkey == IPT_UI_UP_FILTER && highlight > UI_SW_FIRST)
@@ -322,7 +323,7 @@ void menu_select_software::handle()
{
// Infos
ui_globals::cur_sw_dats_view--;
- topline_datsview = 0;
+ m_topline_datsview = 0;
}
}
else if (menu_event->iptkey == IPT_UI_RIGHT)
@@ -339,7 +340,7 @@ void menu_select_software::handle()
{
// Infos
ui_globals::cur_sw_dats_view++;
- topline_datsview = 0;
+ m_topline_datsview = 0;
}
}
else if (menu_event->iptkey == IPT_UI_LEFT_PANEL)
@@ -371,7 +372,7 @@ void menu_select_software::handle()
}
// if we're in an error state, overlay an error message
- if (ui_error)
+ if (m_ui_error)
ui().draw_text_box(container, _("The selected software is missing one or more required files. "
"Please select a different software.\n\nPress any key to continue."),
ui::text_layout::CENTER, 0.5f, 0.5f, UI_RED_COLOR);
@@ -415,7 +416,7 @@ void menu_select_software::handle()
void menu_select_software::populate()
{
- UINT32 flags_ui = FLAG_UI_SWLIST | FLAG_LEFT_ARROW | FLAG_RIGHT_ARROW;
+ UINT32 flags_ui = FLAG_LEFT_ARROW | FLAG_RIGHT_ARROW;
m_has_empty_start = true;
int old_software = -1;
@@ -897,7 +898,7 @@ void menu_select_software::inkey_select(const event *menu_event)
reselect_last::set(true);
mame_machine_manager::instance()->schedule_new_driver(*ui_swinfo->driver);
machine().schedule_hard_reset();
- menu::stack_reset(machine());
+ stack_reset();
}
}
@@ -948,14 +949,14 @@ void menu_select_software::inkey_select(const event *menu_event)
reselect_last::set(true);
mame_machine_manager::instance()->schedule_new_driver(drivlist.driver());
machine().schedule_hard_reset();
- menu::stack_reset(machine());
+ stack_reset();
}
// otherwise, display an error
else
{
reset(reset_options::REMEMBER_POSITION);
- ui_error = true;
+ m_ui_error = true;
}
}
}
@@ -1652,27 +1653,27 @@ void menu_select_software::infos_render(void *selectedref, float origx1, float o
return;
}
else
- totallines = ui().wrap_text(container, buffer.c_str(), origx1, origy1, origx2 - origx1 - (2.0f * gutter_width), xstart, xend, text_size);
+ m_total_lines = ui().wrap_text(container, buffer.c_str(), origx1, origy1, origx2 - origx1 - (2.0f * gutter_width), xstart, xend, text_size);
int r_visible_lines = floor((origy2 - oy1) / (line_height * text_size));
- if (totallines < r_visible_lines)
- r_visible_lines = totallines;
- if (topline_datsview < 0)
- topline_datsview = 0;
- if (topline_datsview + r_visible_lines >= totallines)
- topline_datsview = totallines - r_visible_lines;
+ if (m_total_lines < r_visible_lines)
+ r_visible_lines = m_total_lines;
+ if (m_topline_datsview < 0)
+ m_topline_datsview = 0;
+ if (m_topline_datsview + r_visible_lines >= m_total_lines)
+ m_topline_datsview = m_total_lines - r_visible_lines;
for (int r = 0; r < r_visible_lines; ++r)
{
- int itemline = r + topline_datsview;
+ int itemline = r + m_topline_datsview;
std::string tempbuf;
tempbuf.assign(buffer.substr(xstart[itemline], xend[itemline] - xstart[itemline]));
// up arrow
- if (r == 0 && topline_datsview != 0)
+ if (r == 0 && m_topline_datsview != 0)
info_arrow(0, origx1, origx2, oy1, line_height, text_size, ud_arrow_width);
// bottom arrow
- else if (r == r_visible_lines - 1 && itemline != totallines - 1)
+ else if (r == r_visible_lines - 1 && itemline != m_total_lines - 1)
info_arrow(1, origx1, origx2, oy1, line_height, text_size, ud_arrow_width);
else
ui().draw_text_full(container, tempbuf.c_str(), origx1 + gutter_width, oy1, origx2 - origx1,
@@ -1682,7 +1683,7 @@ void menu_select_software::infos_render(void *selectedref, float origx1, float o
}
// return the number of visible lines, minus 1 for top arrow and 1 for bottom arrow
- right_visible_lines = r_visible_lines - (topline_datsview != 0) - (topline_datsview + r_visible_lines != totallines);
+ right_visible_lines = r_visible_lines - (m_topline_datsview != 0) - (m_topline_datsview + r_visible_lines != m_total_lines);
}
//-------------------------------------------------
@@ -1972,7 +1973,7 @@ void software_parts::handle()
mame_machine_manager::instance()->schedule_new_driver(*m_uiinfo->driver);
machine().schedule_hard_reset();
- menu::stack_reset(machine());
+ stack_reset();
}
}
}
@@ -2074,7 +2075,7 @@ void bios_selection::handle()
moptions.set_value(OPTION_BIOS, elem.second, OPTION_PRIORITY_CMDLINE, error);
mame_machine_manager::instance()->schedule_new_driver(*s_driver);
machine().schedule_hard_reset();
- menu::stack_reset(machine());
+ stack_reset();
}
else
{
@@ -2112,7 +2113,7 @@ void bios_selection::handle()
reselect_last::set(true);
mame_machine_manager::instance()->schedule_new_driver(drivlist.driver());
machine().schedule_hard_reset();
- menu::stack_reset(machine());
+ stack_reset();
}
}
}
diff --git a/src/frontend/mame/ui/selsoft.h b/src/frontend/mame/ui/selsoft.h
index faf178565f2..9681a8c2068 100644
--- a/src/frontend/mame/ui/selsoft.h
+++ b/src/frontend/mame/ui/selsoft.h
@@ -13,13 +13,14 @@
#define MAME_FRONTEND_UI_SELSOFT_H
#include "ui/custmenu.h"
+#include "ui/selmenu.h"
namespace ui {
using s_bios = std::vector<std::pair<std::string, int>>;
using s_parts = std::unordered_map<std::string, std::string>;
// Menu Class
-class menu_select_software : public menu
+class menu_select_software : public menu_select_launch
{
public:
menu_select_software(mame_ui_manager &mui, render_container *container, const game_driver *driver);
diff --git a/src/frontend/mame/ui/simpleselgame.cpp b/src/frontend/mame/ui/simpleselgame.cpp
index f2325f5e2c1..4526676a960 100644
--- a/src/frontend/mame/ui/simpleselgame.cpp
+++ b/src/frontend/mame/ui/simpleselgame.cpp
@@ -164,7 +164,7 @@ void simple_menu_select_game::inkey_select(const event *menu_event)
{
mame_machine_manager::instance()->schedule_new_driver(*driver);
machine().schedule_hard_reset();
- menu::stack_reset(machine());
+ stack_reset();
}
// otherwise, display an error
@@ -264,7 +264,7 @@ void simple_menu_select_game::populate()
}
// if we're forced into this, allow general input configuration as well
- if (menu::stack_has_special_main_menu())
+ if (stack_has_special_main_menu())
{
item_append(menu_item_type::SEPARATOR);
item_append(_("Configure Options"), "", 0, (void *)1);
diff --git a/src/frontend/mame/ui/sliders.cpp b/src/frontend/mame/ui/sliders.cpp
index 8d4143259e8..2cf36b9c85d 100644
--- a/src/frontend/mame/ui/sliders.cpp
+++ b/src/frontend/mame/ui/sliders.cpp
@@ -53,7 +53,7 @@ void menu_sliders::handle()
// toggle visibility
case IPT_UI_ON_SCREEN_DISPLAY:
if (m_menuless_mode)
- menu::stack_pop(machine());
+ stack_pop();
else
m_hidden = !m_hidden;
break;
@@ -268,7 +268,7 @@ UINT32 menu_sliders::ui_handler(render_container *container, mame_ui_manager &mu
UINT32 result;
// if this is the first call, push the sliders menu
- if (topmost_menu<menu_sliders>() == nullptr)
+ if (topmost_menu<menu_sliders>(mui.machine()) == nullptr)
menu::stack_push<menu_sliders>(mui, container, true);
// handle standard menus
@@ -278,7 +278,7 @@ UINT32 menu_sliders::ui_handler(render_container *container, mame_ui_manager &mu
if (result == UI_HANDLER_CANCEL)
menu::stack_pop(mui.machine());
- menu_sliders *uim = topmost_menu<menu_sliders>();
+ menu_sliders *uim = topmost_menu<menu_sliders>(mui.machine());
return uim && uim->m_menuless_mode ? 0 : UI_HANDLER_CANCEL;
}
diff --git a/src/frontend/mame/ui/swlist.cpp b/src/frontend/mame/ui/swlist.cpp
index 859fdcc6f11..5eb4fe7fd62 100644
--- a/src/frontend/mame/ui/swlist.cpp
+++ b/src/frontend/mame/ui/swlist.cpp
@@ -110,7 +110,7 @@ void menu_software_parts::handle()
software_part_menu_entry *entry = (software_part_menu_entry *) event->itemref;
m_result = entry->type;
*m_selected_part = entry->part;
- menu::stack_pop(machine());
+ stack_pop();
}
}
@@ -244,7 +244,7 @@ void menu_software_list::handle()
{
entry_info *info = (entry_info *) event->itemref;
m_result = info->short_name;
- menu::stack_pop(machine());
+ stack_pop();
}
else if (event->iptkey == IPT_SPECIAL)
{
@@ -316,7 +316,7 @@ void menu_software_list::handle()
if (m_filename_buffer[0] != '\0')
memset(m_filename_buffer, '\0', ARRAY_LENGTH(m_filename_buffer));
m_result = m_filename_buffer;
- menu::stack_pop(machine());
+ stack_pop();
}
}
}
@@ -402,7 +402,7 @@ void menu_software::handle()
if (event != nullptr && event->iptkey == IPT_UI_SELECT) {
//menu::stack_push<menu_software_list>(ui(), container, (software_list_config *)event->itemref, image);
*m_result = (software_list_device *)event->itemref;
- menu::stack_pop(machine());
+ stack_pop();
}
}
diff --git a/src/frontend/mame/ui/ui.cpp b/src/frontend/mame/ui/ui.cpp
index df941f3ceb7..c54ad7ebcd4 100644
--- a/src/frontend/mame/ui/ui.cpp
+++ b/src/frontend/mame/ui/ui.cpp
@@ -289,7 +289,7 @@ void mame_ui_manager::display_startup_screens(bool first_time)
// loop over states
set_handler(UI_CALLBACK_TYPE_GENERAL, &mame_ui_manager::handler_ingame);
- for (state = 0; state < maxstate && !machine().scheduled_event_pending() && !ui::menu::stack_has_special_main_menu(); state++)
+ for (state = 0; state < maxstate && !machine().scheduled_event_pending() && !ui::menu::stack_has_special_main_menu(machine()); state++)
{
// default to standard colors
messagebox_backcolor = UI_BACKGROUND_COLOR;
@@ -328,7 +328,7 @@ void mame_ui_manager::display_startup_screens(bool first_time)
while (machine().input().poll_switches() != INPUT_CODE_INVALID) { }
// loop while we have a handler
- while (m_handler_callback_type == UI_CALLBACK_TYPE_MODAL && !machine().scheduled_event_pending() && !ui::menu::stack_has_special_main_menu())
+ while (m_handler_callback_type == UI_CALLBACK_TYPE_MODAL && !machine().scheduled_event_pending() && !ui::menu::stack_has_special_main_menu(machine()))
{
machine().video().frame_update();
}
@@ -339,7 +339,7 @@ void mame_ui_manager::display_startup_screens(bool first_time)
}
// if we're the empty driver, force the menus on
- if (ui::menu::stack_has_special_main_menu())
+ if (ui::menu::stack_has_special_main_menu(machine()))
show_menu();
}
@@ -381,7 +381,7 @@ void mame_ui_manager::update_and_render(render_container *container)
if (machine().phase() >= MACHINE_PHASE_RESET && (single_step() || machine().paused()))
{
int alpha = (1.0f - machine().options().pause_brightness()) * 255.0f;
- if (ui::menu::stack_has_special_main_menu())
+ if (ui::menu::stack_has_special_main_menu(machine()))
alpha = 255;
if (alpha > 255)
alpha = 255;