summaryrefslogtreecommitdiffstatshomepage
path: root/src/frontend
diff options
context:
space:
mode:
authorGravatarGravatar Vas Crabb <vas@vastheman.com>2019-11-17 02:01:39 +1100
committerGravatarGravatar Vas Crabb <vas@vastheman.com>2019-11-17 02:59:11 +1100
commitbb68893deb460b1247b3dfa15d3d190bfec5a083 (patch)
tree8d50990f749849376120ba4c55ac353cd47bfe9b /src/frontend
parent173bcb30b6876d59a787a68caadaab36b8ccfc6c (diff)
UI updates:
* Cleaned up memory management in some more menus * Don't walk the directory every time the crosshair menu is refreshed * Sort crosshair pictures * Show a selector menu when crosshair picture item is selected
Diffstat (limited to 'src/frontend')
-rw-r--r--src/frontend/mame/ui/menu.cpp1
-rw-r--r--src/frontend/mame/ui/miscmenu.cpp402
-rw-r--r--src/frontend/mame/ui/miscmenu.h24
-rw-r--r--src/frontend/mame/ui/swlist.cpp34
-rw-r--r--src/frontend/mame/ui/swlist.h8
5 files changed, 258 insertions, 211 deletions
diff --git a/src/frontend/mame/ui/menu.cpp b/src/frontend/mame/ui/menu.cpp
index 69e08b5489d..bb56497f32a 100644
--- a/src/frontend/mame/ui/menu.cpp
+++ b/src/frontend/mame/ui/menu.cpp
@@ -317,7 +317,6 @@ void menu::reset(reset_options options)
else
item_append(_("Return to Previous Menu"), "", 0, nullptr);
}
-
}
diff --git a/src/frontend/mame/ui/miscmenu.cpp b/src/frontend/mame/ui/miscmenu.cpp
index b7a52f2a4e5..e91f289b6e9 100644
--- a/src/frontend/mame/ui/miscmenu.cpp
+++ b/src/frontend/mame/ui/miscmenu.cpp
@@ -9,6 +9,13 @@
*********************************************************************/
#include "emu.h"
+#include "ui/miscmenu.h"
+
+#include "ui/inifile.h"
+#include "ui/selector.h"
+#include "ui/submenu.h"
+#include "ui/ui.h"
+
#include "mame.h"
#include "osdnet.h"
#include "mameopts.h"
@@ -18,14 +25,14 @@
#include "romload.h"
#include "uiinput.h"
-#include "ui/ui.h"
-#include "ui/menu.h"
-#include "ui/miscmenu.h"
+
#include "../info.h"
-#include "ui/inifile.h"
-#include "ui/submenu.h"
+#include <algorithm>
+#include <cstring>
#include <fstream>
+#include <iterator>
+
namespace ui {
@@ -271,93 +278,99 @@ void menu_bookkeeping::populate(float &customtop, float &custombottom)
void menu_crosshair::handle()
{
- /* process the menu */
- const event *menu_event = process(PROCESS_LR_REPEAT);
+ // process the menu
+ event const *const menu_event(process(PROCESS_LR_REPEAT));
- /* handle events */
- if (menu_event != nullptr && menu_event->itemref != nullptr)
+ // handle events
+ if (menu_event && menu_event->itemref)
{
- crosshair_item_data *data = (crosshair_item_data *)menu_event->itemref;
- bool changed = false;
- //int set_def = false;
- int newval = data->cur;
-
- /* retreive the user settings */
- render_crosshair &crosshair = machine().crosshair().get_crosshair(data->player);
+ crosshair_item_data &data(*reinterpret_cast<crosshair_item_data *>(menu_event->itemref));
+ bool changed(false);
+ int newval(data.cur);
switch (menu_event->iptkey)
{
- /* if selected, reset to default value */
- case IPT_UI_SELECT:
- newval = data->defvalue;
- //set_def = true;
- break;
+ // if selected, reset to default value
+ case IPT_UI_SELECT:
+ newval = data.defvalue;
+ break;
- /* left decrements */
- case IPT_UI_LEFT:
- newval -= machine().input().code_pressed(KEYCODE_LSHIFT) ? 10 : 1;
- break;
+ // left decrements
+ case IPT_UI_LEFT:
+ newval -= machine().input().code_pressed(KEYCODE_LSHIFT) ? 10 : 1;
+ break;
- /* right increments */
- case IPT_UI_RIGHT:
- newval += machine().input().code_pressed(KEYCODE_LSHIFT) ? 10 : 1;
- break;
+ // right increments
+ case IPT_UI_RIGHT:
+ newval += machine().input().code_pressed(KEYCODE_LSHIFT) ? 10 : 1;
+ break;
}
- /* clamp to range */
- if (newval < data->min)
- newval = data->min;
- if (newval > data->max)
- newval = data->max;
+ // clamp to range
+ if (newval < data.min)
+ newval = data.min;
+ if (newval > data.max)
+ newval = data.max;
- /* if things changed, update */
- if (newval != data->cur)
+ // if things changed, update
+ if (newval != data.cur)
{
- switch (data->type)
+ switch (data.type)
{
- /* visibility state */
- case CROSSHAIR_ITEM_VIS:
- crosshair.set_mode(newval);
- // set visibility as specified by mode - auto mode starts with visibility off
- crosshair.set_visible(newval == CROSSHAIR_VISIBILITY_ON);
- changed = true;
- break;
-
- /* auto time */
- case CROSSHAIR_ITEM_AUTO_TIME:
- machine().crosshair().set_auto_time(newval);
- changed = true;
- break;
+ // visibility state
+ case CROSSHAIR_ITEM_VIS:
+ data.crosshair->set_mode(newval);
+ // set visibility as specified by mode - auto mode starts with visibility off
+ data.crosshair->set_visible(newval == CROSSHAIR_VISIBILITY_ON);
+ changed = true;
+ break;
+
+ // auto time
+ case CROSSHAIR_ITEM_AUTO_TIME:
+ machine().crosshair().set_auto_time(newval);
+ changed = true;
+ break;
}
}
- /* crosshair graphic name */
- if (data->type == CROSSHAIR_ITEM_PIC)
+ // crosshair graphic name
+ if (data.type == CROSSHAIR_ITEM_PIC)
{
switch (menu_event->iptkey)
{
- case IPT_UI_SELECT:
- crosshair.set_default_bitmap();
- changed = true;
- break;
-
- case IPT_UI_LEFT:
- crosshair.set_bitmap_name(data->last_name);
- changed = true;
- break;
-
- case IPT_UI_RIGHT:
- crosshair.set_bitmap_name(data->next_name);
- changed = true;
- break;
+ case IPT_UI_SELECT:
+ {
+ std::vector<std::string> sel;
+ sel.reserve(m_pics.size() + 1);
+ sel.push_back("DEFAULT");
+ std::copy(m_pics.begin(), m_pics.end(), std::back_inserter(sel));
+ menu::stack_push<menu_selector>(
+ ui(), container(), std::move(sel), data.cur,
+ [this, &data] (int selection)
+ {
+ if (!selection)
+ data.crosshair->set_default_bitmap();
+ else
+ data.crosshair->set_bitmap_name(m_pics[selection - 1].c_str());
+ reset(reset_options::REMEMBER_REF);
+ });
+ }
+ break;
+
+ case IPT_UI_LEFT:
+ data.crosshair->set_bitmap_name(data.last_name.c_str());
+ changed = true;
+ break;
+
+ case IPT_UI_RIGHT:
+ data.crosshair->set_bitmap_name(data.next_name.c_str());
+ changed = true;
+ break;
}
}
if (changed)
- {
- /* rebuild the menu */
- reset(reset_options::REMEMBER_POSITION);
- }
+ reset(reset_options::REMEMBER_REF); // rebuild the menu
}
}
@@ -373,142 +386,165 @@ menu_crosshair::menu_crosshair(mame_ui_manager &mui, render_container &container
void menu_crosshair::populate(float &customtop, float &custombottom)
{
- crosshair_item_data *data;
- char temp_text[16];
- int player;
- uint8_t use_auto = false;
- uint32_t flags = 0;
+ if (m_data.empty())
+ {
+ // loop over player and add the manual items
+ for (int player = 0; player < MAX_PLAYERS; player++)
+ {
+ // get the user settings
+ render_crosshair &crosshair(machine().crosshair().get_crosshair(player));
+
+ // add menu items for usable crosshairs
+ if (crosshair.is_used())
+ {
+ // CROSSHAIR_ITEM_VIS - allocate a data item and fill it
+ crosshair_item_data &visdata(*m_data.emplace(m_data.end()));
+ visdata.crosshair = &crosshair;
+ visdata.type = CROSSHAIR_ITEM_VIS;
+ visdata.player = player;
+ visdata.min = CROSSHAIR_VISIBILITY_OFF;
+ visdata.max = CROSSHAIR_VISIBILITY_AUTO;
+ visdata.defvalue = CROSSHAIR_VISIBILITY_DEFAULT;
+
+ // CROSSHAIR_ITEM_PIC - allocate a data item and fill it
+ crosshair_item_data &picdata(*m_data.emplace(m_data.end()));
+ picdata.crosshair = &crosshair;
+ picdata.type = CROSSHAIR_ITEM_PIC;
+ picdata.player = player;
+ // other data item not used by this menu
+ }
+ }
+
+ // CROSSHAIR_ITEM_AUTO_TIME - allocate a data item and fill it
+ crosshair_item_data &timedata(*m_data.emplace(m_data.end()));
+ timedata.type = CROSSHAIR_ITEM_AUTO_TIME;
+ timedata.min = CROSSHAIR_VISIBILITY_AUTOTIME_MIN;
+ timedata.max = CROSSHAIR_VISIBILITY_AUTOTIME_MAX;
+ timedata.defvalue = CROSSHAIR_VISIBILITY_AUTOTIME_DEFAULT;
+ }
- /* loop over player and add the manual items */
- for (player = 0; player < MAX_PLAYERS; player++)
+ if (m_pics.empty())
{
- /* get the user settings */
- render_crosshair &crosshair = machine().crosshair().get_crosshair(player);
+ // open a path to the crosshairs
+ file_enumerator path(machine().options().crosshair_path());
+ for (osd::directory::entry const *dir = path.next(); dir; dir = path.next())
+ {
+ // look for files ending in .png
+ size_t const length(std::strlen(dir->name));
+ if ((length > 4) && core_filename_ends_with(dir->name, ".png"))
+ m_pics.emplace_back(dir->name, length - 4);
+ }
+ std::stable_sort(
+ m_pics.begin(),
+ m_pics.end(),
+ [] (std::string const &a, std::string const &b) { return 0 > core_stricmp(a.c_str(), b.c_str()); });
+ }
+
+ // Make sure to keep these matched to the CROSSHAIR_VISIBILITY_xxx types
+ static char const *const vis_text[] = { "Off", "On", "Auto" };
- /* add menu items for usable crosshairs */
- if (crosshair.is_used())
+ bool use_auto = false;
+ for (crosshair_item_data &data : m_data)
+ {
+ switch (data.type)
{
- /* Make sure to keep these matched to the CROSSHAIR_VISIBILITY_xxx types */
- static const char *const vis_text[] = { "Off", "On", "Auto" };
-
- /* track if we need the auto time menu */
- if (crosshair.mode() == CROSSHAIR_VISIBILITY_AUTO) use_auto = true;
-
- /* CROSSHAIR_ITEM_VIS - allocate a data item and fill it */
- data = (crosshair_item_data *)m_pool_alloc(sizeof(*data));
- data->type = CROSSHAIR_ITEM_VIS;
- data->player = player;
- data->min = CROSSHAIR_VISIBILITY_OFF;
- data->max = CROSSHAIR_VISIBILITY_AUTO;
- data->defvalue = CROSSHAIR_VISIBILITY_DEFAULT;
- data->cur = crosshair.mode();
-
- /* put on arrows */
- if (data->cur > data->min)
- flags |= FLAG_LEFT_ARROW;
- if (data->cur < data->max)
- flags |= FLAG_RIGHT_ARROW;
-
- /* add CROSSHAIR_ITEM_VIS menu */
- sprintf(temp_text, "P%d Visibility", player + 1);
- item_append(temp_text, vis_text[crosshair.mode()], flags, data);
-
- /* CROSSHAIR_ITEM_PIC - allocate a data item and fill it */
- data = (crosshair_item_data *)m_pool_alloc(sizeof(*data));
- data->type = CROSSHAIR_ITEM_PIC;
- data->player = player;
- data->last_name[0] = 0;
- /* other data item not used by this menu */
-
- /* search for crosshair graphics */
-
- /* open a path to the crosshairs */
- file_enumerator path(machine().options().crosshair_path());
- const osd::directory::entry *dir;
- /* reset search flags */
- bool using_default = false;
- bool finished = false;
- bool found = false;
-
- /* if we are using the default, then we just need to find the first in the list */
- if (*crosshair.bitmap_name() == '\0')
- using_default = true;
-
- /* look for the current name, then remember the name before */
- /* and find the next name */
- while (((dir = path.next()) != nullptr) && !finished)
+ case CROSSHAIR_ITEM_VIS:
{
- int length = strlen(dir->name);
+ // track if we need the auto time menu
+ if (data.crosshair->mode() == CROSSHAIR_VISIBILITY_AUTO)
+ use_auto = true;
- /* look for files ending in .png with a name not larger then 9 chars*/
- if ((length > 4) && (length <= CROSSHAIR_PIC_NAME_LENGTH + 4) && core_filename_ends_with(dir->name, ".png"))
- {
- /* remove .png from length */
- length -= 4;
+ data.cur = data.crosshair->mode();
+
+ // put on arrows
+ uint32_t flags(0U);
+ if (data.cur > data.min)
+ flags |= FLAG_LEFT_ARROW;
+ if (data.cur < data.max)
+ flags |= FLAG_RIGHT_ARROW;
+ // add CROSSHAIR_ITEM_VIS menu */
+ item_append(util::string_format(_("P%d Visibility"), data.player + 1), vis_text[data.crosshair->mode()], flags, &data);
+ }
+ break;
+
+ case CROSSHAIR_ITEM_PIC:
+ // search for crosshair graphics
+ {
+ // reset search flags
+ bool const using_default(*data.crosshair->bitmap_name() == '\0');
+ bool finished(false);
+ bool found(false);
+ data.cur = using_default ? 0U : 1U;
+ data.last_name.clear();
+ data.next_name.clear();
+
+ // look for the current name, then remember the name before and find the next name
+ for (auto it = m_pics.begin(); it != m_pics.end() && !finished; ++it)
+ {
+ // if we are using the default, then we just need to find the first in the list
if (found || using_default)
{
- /* get the next name */
- strncpy(data->next_name, dir->name, length);
- data->next_name[length] = 0;
+ // get the next name
+ data.next_name = *it;
finished = true;
}
- else if (!strncmp(dir->name, crosshair.bitmap_name(), length))
+ else if (data.crosshair->bitmap_name() == *it)
{
- /* we found the current name */
- /* so loop once more to find the next name */
+ // we found the current name so loop once more to find the next name
found = true;
}
else
- /* remember last name */
- /* we will do it here in case files get added to the directory */
{
- strncpy(data->last_name, dir->name, length);
- data->last_name[length] = 0;
+ // remember last name - we will do it here in case files get added to the directory
+ ++data.cur;
+ data.last_name = *it;
}
}
+
+ // if name not found then next item is DEFAULT
+ if (!found && !using_default)
+ {
+ data.cur = 0U;
+ data.next_name.clear();
+ finished = true;
+ }
+
+ // set up the selection flags
+ uint32_t flags(0U);
+ if (finished)
+ flags |= FLAG_RIGHT_ARROW;
+ if (found)
+ flags |= FLAG_LEFT_ARROW;
+
+ // add CROSSHAIR_ITEM_PIC menu
+ item_append(util::string_format(_("P%d Crosshair"), data.player + 1), using_default ? "DEFAULT" : data.crosshair->bitmap_name(), flags, &data);
}
- /* if name not found then next item is DEFAULT */
- if (!found && !using_default)
+ break;
+
+ case CROSSHAIR_ITEM_AUTO_TIME:
+ if (use_auto)
{
- data->next_name[0] = 0;
- finished = true;
+ data.cur = machine().crosshair().auto_time();
+
+ // put on arrows in visible menu
+ uint32_t flags(0U);
+ if (data.cur > data.min)
+ flags |= FLAG_LEFT_ARROW;
+ if (data.cur < data.max)
+ flags |= FLAG_RIGHT_ARROW;
+
+ // add CROSSHAIR_ITEM_AUTO_TIME menu
+ item_append(_("Visible Delay"), util::string_format("%d", data.cur), flags, &data);
}
- /* setup the selection flags */
- flags = 0;
- if (finished)
- flags |= FLAG_RIGHT_ARROW;
- if (found)
- flags |= FLAG_LEFT_ARROW;
-
- /* add CROSSHAIR_ITEM_PIC menu */
- sprintf(temp_text, "P%d Crosshair", player + 1);
- item_append(temp_text, using_default ? "DEFAULT" : crosshair.bitmap_name(), flags, data);
+ else
+ {
+ // leave a blank filler line when not in auto time so size does not rescale
+ //item_append("", "", nullptr, nullptr);
+ }
+ break;
}
}
- if (use_auto)
- {
- /* CROSSHAIR_ITEM_AUTO_TIME - allocate a data item and fill it */
- data = (crosshair_item_data *)m_pool_alloc(sizeof(*data));
- data->type = CROSSHAIR_ITEM_AUTO_TIME;
- data->min = CROSSHAIR_VISIBILITY_AUTOTIME_MIN;
- data->max = CROSSHAIR_VISIBILITY_AUTOTIME_MAX;
- data->defvalue = CROSSHAIR_VISIBILITY_AUTOTIME_DEFAULT;
- data->cur = machine().crosshair().auto_time();
-
- /* put on arrows in visible menu */
- if (data->cur > data->min)
- flags |= FLAG_LEFT_ARROW;
- if (data->cur < data->max)
- flags |= FLAG_RIGHT_ARROW;
-
- /* add CROSSHAIR_ITEM_AUTO_TIME menu */
- sprintf(temp_text, "%d", machine().crosshair().auto_time());
- item_append(_("Visible Delay"), temp_text, flags, data);
- }
-// else
-// /* leave a blank filler line when not in auto time so size does not rescale */
-// item_append("", "", nullptr, nullptr);
}
menu_crosshair::~menu_crosshair()
diff --git a/src/frontend/mame/ui/miscmenu.h b/src/frontend/mame/ui/miscmenu.h
index 4df94c60a78..acff544dee6 100644
--- a/src/frontend/mame/ui/miscmenu.h
+++ b/src/frontend/mame/ui/miscmenu.h
@@ -13,12 +13,15 @@
#pragma once
+#include "ui/menu.h"
+
#include "crsshair.h"
#include "emuopts.h"
#include <utility>
#include <vector>
+
namespace ui {
class menu_keyboard_mode : public menu
@@ -69,23 +72,24 @@ private:
CROSSHAIR_ITEM_AUTO_TIME
};
- // FIXME: use std::string instead of fixed-length arrays
- constexpr static int CROSSHAIR_PIC_NAME_LENGTH = 12;
-
/* internal crosshair menu item data */
struct crosshair_item_data
{
- uint8_t type;
- uint8_t player;
- uint8_t min, max;
- uint8_t cur;
- uint8_t defvalue;
- char last_name[CROSSHAIR_PIC_NAME_LENGTH + 1];
- char next_name[CROSSHAIR_PIC_NAME_LENGTH + 1];
+ render_crosshair *crosshair = nullptr;
+ uint8_t type = 0U;
+ uint8_t player = 0U;
+ uint8_t min = 0U, max = 0U;
+ uint32_t cur = 0U;
+ uint8_t defvalue = 0U;
+ std::string last_name;
+ std::string next_name;
};
virtual void populate(float &customtop, float &custombottom) override;
virtual void handle() override;
+
+ std::vector<crosshair_item_data> m_data;
+ std::vector<std::string> m_pics;
};
class menu_quit_game : public menu
diff --git a/src/frontend/mame/ui/swlist.cpp b/src/frontend/mame/ui/swlist.cpp
index dc0e98407fe..b0dba549efc 100644
--- a/src/frontend/mame/ui/swlist.cpp
+++ b/src/frontend/mame/ui/swlist.cpp
@@ -75,38 +75,40 @@ menu_software_parts::~menu_software_parts()
void menu_software_parts::populate(float &customtop, float &custombottom)
{
+ m_entries.clear();
+
if (m_other_opt)
{
- software_part_menu_entry *entry1 = (software_part_menu_entry *) m_pool_alloc(sizeof(*entry1));
- entry1->type = result::EMPTY;
- entry1->part = nullptr;
- item_append(_("[empty slot]"), "", 0, entry1);
+ software_part_menu_entry &entry1(*m_entries.emplace(m_entries.end()));
+ entry1.type = result::EMPTY;
+ entry1.part = nullptr;
+ item_append(_("[empty slot]"), "", 0, &entry1);
- software_part_menu_entry *entry2 = (software_part_menu_entry *) m_pool_alloc(sizeof(*entry2));
- entry2->type = result::FMGR;
- entry2->part = nullptr;
- item_append(_("[file manager]"), "", 0, entry2);
+ software_part_menu_entry &entry2(*m_entries.emplace(m_entries.end()));
+ entry2.type = result::FMGR;
+ entry2.part = nullptr;
+ item_append(_("[file manager]"), "", 0, &entry2);
- software_part_menu_entry *entry3 = (software_part_menu_entry *) m_pool_alloc(sizeof(*entry3));
- entry3->type = result::SWLIST;
- entry3->part = nullptr;
- item_append(_("[software list]"), "", 0, entry3);
+ software_part_menu_entry &entry3(*m_entries.emplace(m_entries.end()));
+ entry3.type = result::SWLIST;
+ entry3.part = nullptr;
+ item_append(_("[software list]"), "", 0, &entry3);
}
for (const software_part &swpart : m_info->parts())
{
if (swpart.matches_interface(m_interface))
{
- software_part_menu_entry *entry = (software_part_menu_entry *) m_pool_alloc(sizeof(*entry));
+ software_part_menu_entry &entry(*m_entries.emplace(m_entries.end()));
// check if the available parts have specific part_id to be displayed (e.g. "Map Disc", "Bonus Disc", etc.)
// if not, we simply display "part_name"; if yes we display "part_name (part_id)"
std::string menu_part_name(swpart.name());
if (swpart.feature("part_id") != nullptr)
menu_part_name.append(" (").append(swpart.feature("part_id")).append(")");
- entry->type = result::ENTRY;
- entry->part = &swpart;
- item_append(m_info->shortname(), menu_part_name, 0, entry);
+ entry.type = result::ENTRY;
+ entry.part = &swpart;
+ item_append(m_info->shortname(), menu_part_name, 0, &entry);
}
}
}
diff --git a/src/frontend/mame/ui/swlist.h b/src/frontend/mame/ui/swlist.h
index d0239c2c389..a9947cd8daf 100644
--- a/src/frontend/mame/ui/swlist.h
+++ b/src/frontend/mame/ui/swlist.h
@@ -13,8 +13,11 @@
#include "ui/menu.h"
+#include <list>
+
namespace ui {
+
// ======================> menu_software_parts
class menu_software_parts : public menu
@@ -33,15 +36,18 @@ public:
virtual ~menu_software_parts() override;
private:
- struct software_part_menu_entry {
+ struct software_part_menu_entry
+ {
result type;
const software_part *part;
};
+ using entry_list = std::list<software_part_menu_entry>;
virtual void populate(float &customtop, float &custombottom) override;
virtual void handle() override;
// variables
+ entry_list m_entries;
const software_info * m_info;
const char * m_interface;
const software_part ** m_selected_part;