From ae727d2cc640fef650d6c76694b83b159d3065ba Mon Sep 17 00:00:00 2001 From: Vas Crabb Date: Mon, 14 Jan 2019 04:55:29 +1100 Subject: UI cleanup continues: * Fix crash on builds with fewer than 16 drivers * Fix "available" filter in internal UI * Get rid of some UI globals that shouldn't be global * Better encapsulation in UI * Clean up favourites manager - in particular kill hidden state and O(n) walks * This breaks adding systems/software to favourites from the main tab menu --- src/frontend/mame/clifront.cpp | 9 +- src/frontend/mame/mame.cpp | 4 +- src/frontend/mame/ui/inifile.cpp | 524 ++++++++++++++++++++------------- src/frontend/mame/ui/inifile.h | 90 +++--- src/frontend/mame/ui/mainmenu.cpp | 6 +- src/frontend/mame/ui/menu.cpp | 1 + src/frontend/mame/ui/menu.h | 3 - src/frontend/mame/ui/miscmenu.cpp | 99 ++++--- src/frontend/mame/ui/miscmenu.h | 22 +- src/frontend/mame/ui/optsmenu.cpp | 365 +++++++++++++---------- src/frontend/mame/ui/optsmenu.h | 53 +++- src/frontend/mame/ui/selector.cpp | 1 - src/frontend/mame/ui/selgame.cpp | 426 ++++++++++++++++++--------- src/frontend/mame/ui/selgame.h | 14 +- src/frontend/mame/ui/selmenu.cpp | 206 +++++-------- src/frontend/mame/ui/selmenu.h | 18 +- src/frontend/mame/ui/selsoft.cpp | 23 +- src/frontend/mame/ui/simpleselgame.cpp | 8 +- src/frontend/mame/ui/utils.cpp | 298 +++++++++---------- src/frontend/mame/ui/utils.h | 148 +++++----- 20 files changed, 1312 insertions(+), 1006 deletions(-) (limited to 'src/frontend') diff --git a/src/frontend/mame/clifront.cpp b/src/frontend/mame/clifront.cpp index 276c73f0e63..28249e7bd3e 100644 --- a/src/frontend/mame/clifront.cpp +++ b/src/frontend/mame/clifront.cpp @@ -300,16 +300,19 @@ int cli_frontend::execute(std::vector &args) // work out how wide the titles need to be int titlelen(0); for (int match : matches) - titlelen = std::max(titlelen, int(strlen(drivlist.driver(match).type.fullname()))); + if (0 <= match) + titlelen = (std::max)(titlelen, int(strlen(drivlist.driver(match).type.fullname()))); // print them out osd_printf_error("\n\"%s\" approximately matches the following\n" "supported machines (best match first):\n\n", m_options.attempted_system_name().c_str()); for (int match : matches) { - game_driver const &drv(drivlist.driver(match)); - if (match != -1) + if (0 <= match) + { + game_driver const &drv(drivlist.driver(match)); osd_printf_error("%s", util::string_format("%-18s%-*s(%s, %s)\n", drv.name, titlelen + 2, drv.type.fullname(), drv.manufacturer, drv.year).c_str()); + } } } } diff --git a/src/frontend/mame/mame.cpp b/src/frontend/mame/mame.cpp index e1eb535ea68..f3c08f661e9 100644 --- a/src/frontend/mame/mame.cpp +++ b/src/frontend/mame/mame.cpp @@ -304,13 +304,13 @@ void mame_machine_manager::ui_initialize(running_machine& machine) void mame_machine_manager::create_custom(running_machine& machine) { // start the inifile manager - m_inifile = std::make_unique(machine, m_ui->options()); + m_inifile = std::make_unique(m_ui->options()); // allocate autoboot timer m_autoboot_timer = machine.scheduler().timer_alloc(timer_expired_delegate(FUNC(mame_machine_manager::autoboot_callback), this)); // start favorite manager - m_favorite = std::make_unique(machine, m_ui->options()); + m_favorite = std::make_unique(m_ui->options()); } void mame_machine_manager::load_cheatfiles(running_machine& machine) diff --git a/src/frontend/mame/ui/inifile.cpp b/src/frontend/mame/ui/inifile.cpp index 852884fea6a..9a7f30087dc 100644 --- a/src/frontend/mame/ui/inifile.cpp +++ b/src/frontend/mame/ui/inifile.cpp @@ -1,5 +1,5 @@ // license:BSD-3-Clause -// copyright-holders:Maurizio Petrarota +// copyright-holders:Maurizio Petrarota, Vas Crabb /*************************************************************************** ui/inifile.cpp @@ -16,13 +16,24 @@ #include "drivenum.h" #include "softlist_dev.h" +#include +#include +#include + + +namespace { + +char const FAVORITE_FILENAME[] = "favorites.ini"; + +} // anonymous namespace + //------------------------------------------------- // ctor //------------------------------------------------- -inifile_manager::inifile_manager(running_machine &machine, ui_options &moptions) - : m_options(moptions) +inifile_manager::inifile_manager(ui_options &options) + : m_options(options) , m_ini_index() { // scan directories and create index @@ -108,204 +119,103 @@ void inifile_manager::init_category(std::string &&filename, emu_file &file) FAVORITE MANAGER **************************************************************************/ -//------------------------------------------------- -// ctor -//------------------------------------------------- - -favorite_manager::favorite_manager(running_machine &machine, ui_options &moptions) - : m_machine(machine) - , m_options(moptions) +bool favorite_manager::favorite_compare::operator()(ui_software_info const &lhs, ui_software_info const &rhs) const { - parse_favorite(); -} + assert(lhs.driver); + assert(rhs.driver); -//------------------------------------------------- -// add a game -//------------------------------------------------- - -void favorite_manager::add_favorite_game(const game_driver *driver) -{ - m_list.emplace(driver->type.fullname(), *driver); - save_favorite_games(); -} - -//------------------------------------------------- -// add a system -//------------------------------------------------- - -void favorite_manager::add_favorite_game(ui_software_info &swinfo) -{ - m_list.emplace(swinfo.longname, swinfo); - save_favorite_games(); -} - -//------------------------------------------------- -// add a game / system -//------------------------------------------------- - -void favorite_manager::add_favorite_game() -{ - if ((machine().system().flags & machine_flags::MASK_TYPE) == machine_flags::TYPE_ARCADE) + if (!lhs.startempty) { - add_favorite_game(&machine().system()); - return; + if (rhs.startempty) + return false; + else if (lhs.listname < rhs.listname) + return true; + else if (lhs.listname > rhs.listname) + return false; + else if (lhs.shortname < rhs.shortname) + return true; + else if (lhs.shortname > rhs.shortname) + return false; } - - auto software_avail = false; - for (device_image_interface &image : image_interface_iterator(machine().root_device())) + else if (!rhs.startempty) { - if (image.exists() && image.loaded_through_softlist()) - { - const software_info *swinfo = image.software_entry(); - const software_part *part = image.part_entry(); - ui_software_info tmpmatches; - tmpmatches.shortname = swinfo->shortname(); - tmpmatches.longname = image.longname(); - tmpmatches.parentname = swinfo->parentname(); - tmpmatches.year = image.year(); - tmpmatches.publisher = image.manufacturer(); - tmpmatches.supported = image.supported(); - tmpmatches.part = part->name(); - tmpmatches.driver = &machine().system(); - tmpmatches.listname = strensure(image.software_list_name()); - tmpmatches.interface = part->interface(); - tmpmatches.instance = image.instance_name(); - tmpmatches.startempty = 0; - tmpmatches.parentlongname.clear(); - if (!swinfo->parentname().empty()) - { - auto swlist = software_list_device::find_by_name(machine().config(), image.software_list_name()); - for (const software_info &c_swinfo : swlist->get_info()) - { - std::string c_parent(c_swinfo.parentname()); - if (!c_parent.empty() && c_parent == swinfo->shortname()) - { - tmpmatches.parentlongname = c_swinfo.longname(); - break; - } - } - } - - tmpmatches.usage.clear(); - for (const feature_list_item &flist : swinfo->other_info()) - if (!strcmp(flist.name().c_str(), "usage")) - tmpmatches.usage = flist.value(); - - tmpmatches.devicetype = strensure(image.image_type_name()); - tmpmatches.available = true; - software_avail = true; - m_list.emplace(tmpmatches.longname, tmpmatches); - save_favorite_games(); - } + return true; } - if (!software_avail) - add_favorite_game(&machine().system()); + return 0 > std::strncmp(lhs.driver->name, rhs.driver->name, ARRAY_LENGTH(lhs.driver->name)); } -//------------------------------------------------- -// remove a favorite from list -//------------------------------------------------- - -void favorite_manager::remove_favorite_game(ui_software_info const &swinfo) +bool favorite_manager::favorite_compare::operator()(ui_software_info const &lhs, game_driver const &rhs) const { - for (auto e = m_list.begin(); e != m_list.end(); ++e) - if (e->second == swinfo) - { - m_list.erase(e); - break; - } - m_current = m_list.begin(); - save_favorite_games(); -} - -//------------------------------------------------- -// remove a favorite from list -//------------------------------------------------- + assert(lhs.driver); -void favorite_manager::remove_favorite_game() -{ - m_list.erase(m_current); - m_current = m_list.begin(); - save_favorite_games(); + if (!lhs.startempty) + return false; + else + return 0 > std::strncmp(lhs.driver->name, rhs.name, ARRAY_LENGTH(rhs.name)); } -//------------------------------------------------- -// check if game is already in favorite list -//------------------------------------------------- - -bool favorite_manager::isgame_favorite() +bool favorite_manager::favorite_compare::operator()(game_driver const &lhs, ui_software_info const &rhs) const { - if ((machine().system().flags & machine_flags::MASK_TYPE) == machine_flags::TYPE_ARCADE) - return isgame_favorite(&machine().system()); - - auto image_loaded = false; + assert(rhs.driver); - for (device_image_interface &image : image_interface_iterator(machine().root_device())) - { - const software_info *swinfo = image.software_entry(); - if (image.exists() && swinfo != nullptr) - { - image_loaded = true; - for (auto current = m_list.begin(); current != m_list.end(); ++current) - if (current->second.shortname == swinfo->shortname() && - current->second.listname == image.software_list_name()) - { - m_current = current; - return true; - } - } - } - - if (!image_loaded) - return isgame_favorite(&machine().system()); - - m_current = m_list.begin(); - return false; + if (!rhs.startempty) + return true; + else + return 0 > std::strncmp(lhs.name, rhs.driver->name, ARRAY_LENGTH(lhs.name)); } -//------------------------------------------------- -// check if game is already in favorite list -//------------------------------------------------- - -bool favorite_manager::isgame_favorite(const game_driver *driver) +bool favorite_manager::favorite_compare::operator()(ui_software_info const &lhs, running_software_key const &rhs) const { - for (auto current = m_list.begin(); current != m_list.end(); ++current) - if (current->second.driver == driver && current->second.shortname == driver->name) - { - m_current = current; - return true; - } - - m_current = m_list.begin(); - return false; + assert(lhs.driver); + assert(std::get<1>(rhs)); + + if (lhs.startempty) + return true; + else if (lhs.listname < std::get<1>(rhs)) + return true; + else if (lhs.listname > std::get<1>(rhs)) + return false; + else if (lhs.shortname < std::get<2>(rhs)) + return true; + else if (lhs.shortname > std::get<2>(rhs)) + return false; + else + return 0 > std::strncmp(lhs.driver->name, std::get<0>(rhs).name, ARRAY_LENGTH(lhs.driver->name)); } -//------------------------------------------------- -// check if game is already in favorite list -//------------------------------------------------- - -bool favorite_manager::isgame_favorite(ui_software_info const &swinfo) +bool favorite_manager::favorite_compare::operator()(running_software_key const &lhs, ui_software_info const &rhs) const { - for (auto current = m_list.begin(); current != m_list.end(); ++current) - if (current->second == swinfo) - { - m_current = current; - return true; - } - - m_current = m_list.begin(); - return false; + assert(std::get<1>(lhs)); + assert(rhs.driver); + + if (rhs.startempty) + return false; + else if (std::get<1>(lhs) < rhs.listname) + return true; + else if (std::get<1>(lhs) > rhs.listname) + return false; + else if (std::get<2>(lhs) < rhs.shortname) + return true; + else if (std::get<2>(lhs) > rhs.shortname) + return false; + else + return 0 > std::strncmp(std::get<0>(lhs).name, rhs.driver->name, ARRAY_LENGTH(rhs.driver->name)); } + //------------------------------------------------- -// parse favorite file +// construction/destruction //------------------------------------------------- -void favorite_manager::parse_favorite() +favorite_manager::favorite_manager(ui_options &options) + : m_options(options) + , m_favorites() + , m_sorted() + , m_need_sort(true) { emu_file file(m_options.ui_path(), OPEN_FLAG_READ); - if (file.open(favorite_filename) == osd_file::error::NONE) + if (file.open(FAVORITE_FILENAME) == osd_file::error::NONE) { char readbuf[1024]; file.gets(readbuf, 1024); @@ -332,7 +242,8 @@ void favorite_manager::parse_favorite() file.gets(readbuf, 1024); chartrimcarriage(readbuf); auto dx = driver_list::find(readbuf); - if (dx == -1) continue; + if (0 > dx) + continue; tmpmatches.driver = &driver_list::driver(dx); file.gets(readbuf, 1024); tmpmatches.listname = chartrimcarriage(readbuf); @@ -350,53 +261,258 @@ void favorite_manager::parse_favorite() tmpmatches.devicetype = chartrimcarriage(readbuf); file.gets(readbuf, 1024); tmpmatches.available = atoi(readbuf); - m_list.emplace(tmpmatches.longname, tmpmatches); + m_favorites.emplace(std::move(tmpmatches)); } file.close(); } } + //------------------------------------------------- -// save favorite +// add //------------------------------------------------- -void favorite_manager::save_favorite_games() +void favorite_manager::add_favorite_system(game_driver const &driver) +{ + add_impl(driver); +} + +void favorite_manager::add_favorite_software(ui_software_info const &swinfo) +{ + add_impl(swinfo); +} + +void favorite_manager::add_favorite(running_machine &machine) +{ +#if 0 + apply_running_machine( + machine, + [this] (auto &&key, bool &done) + { + add_impl(std::forward(key)); + done = true; + }); +#endif +} + +template void favorite_manager::add_impl(T &&key) +{ + auto const ins(m_favorites.emplace(std::forward(key))); + if (ins.second) + { + if (!m_sorted.empty()) + m_sorted.emplace_back(std::ref(*ins.first)); + m_need_sort = true; + save_favorites(); + } +} + + +//------------------------------------------------- +// check +//------------------------------------------------- + +bool favorite_manager::is_favorite_system(game_driver const &driver) const +{ + return check_impl(driver); +} + +bool favorite_manager::is_favorite_software(ui_software_info const &swinfo) const +{ + auto found(m_favorites.lower_bound(swinfo)); + if ((m_favorites.end() != found) && (found->listname == swinfo.listname) && (found->shortname == swinfo.shortname)) + return true; + else if (m_favorites.begin() == found) + return false; + + // need to back up and check for matching software with lexically earlier driver + --found; + return (found->listname == swinfo.listname) && (found->shortname == swinfo.shortname); +} + +bool favorite_manager::is_favorite(running_machine &machine) const +{ + bool result(false); + apply_running_machine( + machine, + [this, &result] (auto const &key, bool &done) + { + assert(!result); + result = check_impl(key); + done = done || result; + }); + return result; +} + +bool favorite_manager::is_favorite_system_software(ui_software_info const &swinfo) const +{ + return check_impl(swinfo); +} + +template bool favorite_manager::check_impl(T const &key) const +{ + return m_favorites.find(key) != m_favorites.end(); +} + + +//------------------------------------------------- +// remove +//------------------------------------------------- + +void favorite_manager::remove_favorite_system(game_driver const &driver) +{ + remove_impl(driver); +} + +void favorite_manager::remove_favorite_software(ui_software_info const &swinfo) +{ + remove_impl(swinfo); +} + +void favorite_manager::remove_favorite(running_machine &machine) +{ + apply_running_machine(machine, [this] (auto const &key, bool &done) { done = remove_impl(key); }); +} + +template bool favorite_manager::remove_impl(T const &key) +{ + auto const found(m_favorites.find(key)); + if (m_favorites.end() != found) + { + m_favorites.erase(found); + m_sorted.clear(); + m_need_sort = true; + save_favorites(); + return true; + } + else + { + return false; + } +} + + +//------------------------------------------------- +// implementation +//------------------------------------------------- + +template +void favorite_manager::apply_running_machine(running_machine &machine, T &&action) +{ + bool done(false); + + // TODO: this should be changed - it interacts poorly with slotted arcade systems + if ((machine.system().flags & machine_flags::MASK_TYPE) == machine_flags::TYPE_ARCADE) + { + action(machine.system(), done); + } + else + { + bool have_software(false); + for (device_image_interface &image_dev : image_interface_iterator(machine.root_device())) + { + software_info const *const sw(image_dev.software_entry()); + if (image_dev.exists() && image_dev.loaded_through_softlist() && sw) + { + assert(image_dev.software_list_name()); + + have_software = true; + action(running_software_key(machine.system(), image_dev.software_list_name(), sw->shortname()), done); + if (done) + return; + } + } + + if (!have_software) + action(machine.system(), done); + } +} + +void favorite_manager::update_sorted() +{ + if (m_need_sort) + { + if (m_sorted.empty()) + std::copy(m_favorites.begin(), m_favorites.end(), std::back_inserter(m_sorted)); + + assert(m_favorites.size() == m_sorted.size()); + std::stable_sort( + m_sorted.begin(), + m_sorted.end(), + [] (ui_software_info const &lhs, ui_software_info const &rhs) -> bool + { + assert(lhs.driver); + assert(rhs.driver); + + int cmp; + + cmp = core_stricmp(lhs.longname.c_str(), rhs.longname.c_str()); + if (0 > cmp) + return true; + else if (0 < cmp) + return false; + + cmp = core_stricmp(lhs.driver->type.fullname(), rhs.driver->type.fullname()); + if (0 > cmp) + return true; + else if (0 < cmp) + return false; + + cmp = std::strcmp(lhs.listname.c_str(), rhs.listname.c_str()); + if (0 > cmp) + return true; + else if (0 < cmp) + return false; + + return false; + }); + + m_need_sort = false; + } +} + +void favorite_manager::save_favorites() { // attempt to open the output file emu_file file(m_options.ui_path(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS); - if (file.open(favorite_filename) == osd_file::error::NONE) + if (file.open(FAVORITE_FILENAME) == osd_file::error::NONE) { - if (m_list.empty()) + if (m_favorites.empty()) { + // delete it if there are no favorites file.remove_on_close(); - file.close(); - return; } - - // generate the favorite INI - std::ostringstream text; - text << "[ROOT_FOLDER]\n[Favorite]\n\n"; - for (auto & e : m_list) + else { - auto elem = e.second; - text << elem.shortname << '\n'; - text << elem.longname << '\n'; - text << elem.parentname << '\n'; - text << elem.year << '\n'; - text << elem.publisher << '\n'; - util::stream_format(text, "%d\n", elem.supported); - text << elem.part << '\n'; - util::stream_format(text, "%s\n", elem.driver->name); - text << elem.listname << '\n'; - text << elem.interface << '\n'; - text << elem.instance << '\n'; - util::stream_format(text, "%d\n", elem.startempty); - text << elem.parentlongname << '\n'; - text << elem.usage << '\n'; - text << elem.devicetype << '\n'; - util::stream_format(text, "%d\n", elem.available); + // generate the favorite INI + file.puts("[ROOT_FOLDER]\n[Favorite]\n\n"); + util::ovectorstream buf; + for (ui_software_info const &info : m_favorites) + { + buf.clear(); + buf.rdbuf()->clear(); + + buf << info.shortname << '\n'; + buf << info.longname << '\n'; + buf << info.parentname << '\n'; + buf << info.year << '\n'; + buf << info.publisher << '\n'; + util::stream_format(buf, "%d\n", info.supported); + buf << info.part << '\n'; + util::stream_format(buf, "%s\n", info.driver->name); + buf << info.listname << '\n'; + buf << info.interface << '\n'; + buf << info.instance << '\n'; + util::stream_format(buf, "%d\n", info.startempty); + buf << info.parentlongname << '\n'; + buf << info.usage << '\n'; + buf << info.devicetype << '\n'; + util::stream_format(buf, "%d\n", info.available); + + buf.put('\0'); + file.puts(&buf.vec()[0]); + } } - file.puts(text.str().c_str()); file.close(); } } diff --git a/src/frontend/mame/ui/inifile.h b/src/frontend/mame/ui/inifile.h index 49344fd01eb..68adca3c917 100644 --- a/src/frontend/mame/ui/inifile.h +++ b/src/frontend/mame/ui/inifile.h @@ -1,5 +1,5 @@ // license:BSD-3-Clause -// copyright-holders:Maurizio Petrarota +// copyright-holders:Maurizio Petrarota, Vas Crabb /*************************************************************************** ui/inifile.h @@ -7,7 +7,6 @@ UI INIs file manager. ***************************************************************************/ - #ifndef MAME_FRONTEND_UI_INIFILE_H #define MAME_FRONTEND_UI_INIFILE_H @@ -15,6 +14,10 @@ #include "ui/utils.h" +#include +#include +#include +#include #include @@ -28,7 +31,7 @@ class inifile_manager { public: // construction/destruction - inifile_manager(running_machine &machine, ui_options &moptions); + inifile_manager(ui_options &options); // load systems from category void load_ini_category(size_t file, size_t category, std::unordered_set &result) const; @@ -59,52 +62,67 @@ class favorite_manager { public: // construction/destruction - favorite_manager(running_machine &machine, ui_options &moptions); - - // favorites comparator - struct ci_less - { - bool operator() (const std::string &s1, const std::string &s2) const - { - return (core_stricmp(s1.c_str(), s2.c_str()) < 0); - } - }; - - // favorite indices - std::multimap m_list; - - // getters - running_machine &machine() const { return m_machine; } + favorite_manager(ui_options &options); // add - void add_favorite_game(); - void add_favorite_game(const game_driver *driver); - void add_favorite_game(ui_software_info &swinfo); + void add_favorite_system(game_driver const &driver); + void add_favorite_software(ui_software_info const &swinfo); + void add_favorite(running_machine &machine); // check - bool isgame_favorite(); - bool isgame_favorite(const game_driver *driver); - bool isgame_favorite(ui_software_info const &swinfo); - - // save - void save_favorite_games(); + bool is_favorite_system(game_driver const &driver) const; + bool is_favorite_software(ui_software_info const &swinfo) const; + bool is_favorite_system_software(ui_software_info const &swinfo) const; + bool is_favorite(running_machine &machine) const; // remove - void remove_favorite_game(); - void remove_favorite_game(ui_software_info const &swinfo); + void remove_favorite_system(game_driver const &driver); + void remove_favorite_software(ui_software_info const &swinfo); + void remove_favorite(running_machine &machine); + + // walk + template void apply(T &&action) + { + for (auto const &item : m_favorites) + action(item); + } + template void apply_sorted(T &&action) + { + update_sorted(); + for (auto const &item : m_sorted) + action(item.get()); + } private: - const char *favorite_filename = "favorites.ini"; + using running_software_key = std::tuple; + + struct favorite_compare + { + using is_transparent = std::true_type; + + bool operator()(ui_software_info const &lhs, ui_software_info const &rhs) const; + bool operator()(ui_software_info const &lhs, game_driver const &rhs) const; + bool operator()(game_driver const &lhs, ui_software_info const &rhs) const; + bool operator()(ui_software_info const &lhs, running_software_key const &rhs) const; + bool operator()(running_software_key const &lhs, ui_software_info const &rhs) const; + }; - // current - std::multimap::iterator m_current; + using favorites_set = std::set; + using sorted_favorites = std::vector >; - // parse file ui_favorite - void parse_favorite(); + // implementation + template static void apply_running_machine(running_machine &machine, T &&action); + template void add_impl(T &&key); + template bool check_impl(T const &key) const; + template bool remove_impl(T const &key); + void update_sorted(); + void save_favorites(); // internal state - running_machine &m_machine; // reference to our machine ui_options &m_options; + favorites_set m_favorites; + sorted_favorites m_sorted; + bool m_need_sort; }; #endif // MAME_FRONTEND_UI_INIFILE_H diff --git a/src/frontend/mame/ui/mainmenu.cpp b/src/frontend/mame/ui/mainmenu.cpp index 30b2fbae1e0..b9befd90991 100644 --- a/src/frontend/mame/ui/mainmenu.cpp +++ b/src/frontend/mame/ui/mainmenu.cpp @@ -123,7 +123,7 @@ void menu_main::populate(float &customtop, float &custombottom) item_append(menu_item_type::SEPARATOR); - if (!mame_machine_manager::instance()->favorite().isgame_favorite()) + if (!mame_machine_manager::instance()->favorite().is_favorite(machine())) item_append(_("Add To Favorites"), "", 0, (void *)ADD_FAVORITE); else item_append(_("Remove From Favorites"), "", 0, (void *)REMOVE_FAVORITE); @@ -249,12 +249,12 @@ void menu_main::handle() break; case ADD_FAVORITE: - mame_machine_manager::instance()->favorite().add_favorite_game(); + mame_machine_manager::instance()->favorite().add_favorite(machine()); reset(reset_options::REMEMBER_POSITION); break; case REMOVE_FAVORITE: - mame_machine_manager::instance()->favorite().remove_favorite_game(); + mame_machine_manager::instance()->favorite().remove_favorite(machine()); reset(reset_options::REMEMBER_POSITION); break; diff --git a/src/frontend/mame/ui/menu.cpp b/src/frontend/mame/ui/menu.cpp index 3a0eff12c5e..9a8fb8255e3 100644 --- a/src/frontend/mame/ui/menu.cpp +++ b/src/frontend/mame/ui/menu.cpp @@ -31,6 +31,7 @@ namespace ui { + /*************************************************************************** CONSTANTS ***************************************************************************/ diff --git a/src/frontend/mame/ui/menu.h b/src/frontend/mame/ui/menu.h index 1a6c2d977f8..f0c9600d509 100644 --- a/src/frontend/mame/ui/menu.h +++ b/src/frontend/mame/ui/menu.h @@ -151,7 +151,6 @@ protected: void reset(reset_options options); void reset_parent(reset_options options) { m_parent->reset(options); } - void reset_topmost(reset_options options) { m_global_state->reset_topmost(options); } template T *topmost_menu() const { return m_global_state->topmost_menu(); } template static T *topmost_menu(running_machine &machine) { return get_global_state(machine)->topmost_menu(); } @@ -310,8 +309,6 @@ private: 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 T *topmost_menu() const { return dynamic_cast(m_stack.get()); } diff --git a/src/frontend/mame/ui/miscmenu.cpp b/src/frontend/mame/ui/miscmenu.cpp index 57b1412dd5d..e2f1f0615fc 100644 --- a/src/frontend/mame/ui/miscmenu.cpp +++ b/src/frontend/mame/ui/miscmenu.cpp @@ -663,25 +663,40 @@ void menu_export::populate(float &customtop, float &custombottom) // ctor / dtor //------------------------------------------------- -menu_machine_configure::menu_machine_configure(mame_ui_manager &mui, render_container &container, const game_driver *prev, float _x0, float _y0) +menu_machine_configure::menu_machine_configure( + mame_ui_manager &mui, + render_container &container, + game_driver const &drv, + std::function &&handler, + float x0, float y0) : menu(mui, container) - , m_drv(prev) - , x0(_x0) - , y0(_y0) + , m_handler(std::move(handler)) + , m_drv(drv) + , m_x0(x0) + , m_y0(y0) , m_curbios(0) - , m_fav_reset(false) + , m_was_favorite(mame_machine_manager::instance()->favorite().is_favorite_system(drv)) + , m_want_favorite(m_was_favorite) { // parse the INI file std::ostringstream error; osd_setup_osd_specific_emu_options(m_opts); - mame_options::parse_standard_inis(m_opts, error, m_drv); + mame_options::parse_standard_inis(m_opts, error, &m_drv); setup_bios(); } menu_machine_configure::~menu_machine_configure() { - if (m_fav_reset) - reset_topmost(reset_options::SELECT_FIRST); + if (m_was_favorite != m_want_favorite) + { + if (m_want_favorite) + mame_machine_manager::instance()->favorite().add_favorite_system(m_drv); + else + mame_machine_manager::instance()->favorite().remove_favorite_system(m_drv); + } + + if (m_handler) + m_handler(m_want_favorite, m_was_favorite != m_want_favorite); } //------------------------------------------------- @@ -692,16 +707,16 @@ void menu_machine_configure::handle() { // process the menu process_parent(); - const event *menu_event = process(PROCESS_NOIMAGE, x0, y0); + const event *menu_event = process(PROCESS_NOIMAGE, m_x0, m_y0); if (menu_event != nullptr && menu_event->itemref != nullptr) { if (menu_event->iptkey == IPT_UI_SELECT) { switch ((uintptr_t)menu_event->itemref) { - case SAVE: + case SAVE: { - std::string filename(m_drv->name); + std::string filename(m_drv.name); emu_file file(machine().options().ini_path(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE); osd_file::error filerr = file.open(filename.c_str(), ".ini"); if (filerr == osd_file::error::NONE) @@ -710,36 +725,30 @@ void menu_machine_configure::handle() file.puts(inistring.c_str()); ui().popup_time(2, "%s", _("\n Configuration saved \n\n")); } - break; } - case ADDFAV: - mame_machine_manager::instance()->favorite().add_favorite_game(m_drv); - reset(reset_options::REMEMBER_POSITION); - break; - case DELFAV: - mame_machine_manager::instance()->favorite().remove_favorite_game(); - if (main_filters::actual == machine_filter::FAVORITE) - { - m_fav_reset = true; - menu::stack_pop(); - } - else - reset(reset_options::REMEMBER_POSITION); - break; - case CONTROLLER: - if (menu_event->iptkey == IPT_UI_SELECT) - menu::stack_push(ui(), container(), submenu::control_options, m_drv, &m_opts); - break; - case VIDEO: - if (menu_event->iptkey == IPT_UI_SELECT) - menu::stack_push(ui(), container(), submenu::video_options, m_drv, &m_opts); - break; - case ADVANCED: - if (menu_event->iptkey == IPT_UI_SELECT) - menu::stack_push(ui(), container(), submenu::advanced_options, m_drv, &m_opts); - break; - default: - break; + break; + case ADDFAV: + m_want_favorite = true; + reset(reset_options::REMEMBER_POSITION); + break; + case DELFAV: + m_want_favorite = false; + reset(reset_options::REMEMBER_POSITION); + break; + case CONTROLLER: + if (menu_event->iptkey == IPT_UI_SELECT) + menu::stack_push(ui(), container(), submenu::control_options, &m_drv, &m_opts); + break; + case VIDEO: + if (menu_event->iptkey == IPT_UI_SELECT) + menu::stack_push(ui(), container(), submenu::video_options, &m_drv, &m_opts); + break; + case ADVANCED: + if (menu_event->iptkey == IPT_UI_SELECT) + menu::stack_push(ui(), container(), submenu::advanced_options, &m_drv, &m_opts); + break; + default: + break; } } else if (menu_event->iptkey == IPT_UI_LEFT || menu_event->iptkey == IPT_UI_RIGHT) @@ -773,7 +782,7 @@ void menu_machine_configure::populate(float &customtop, float &custombottom) item_append(_(submenu::control_options[0].description), "", 0, (void *)(uintptr_t)CONTROLLER); item_append(menu_item_type::SEPARATOR); - if (!mame_machine_manager::instance()->favorite().isgame_favorite(m_drv)) + if (!m_want_favorite) item_append(_("Add To Favorites"), "", 0, (void *)ADDFAV); else item_append(_("Remove From Favorites"), "", 0, (void *)DELFAV); @@ -790,7 +799,7 @@ void menu_machine_configure::populate(float &customtop, float &custombottom) void menu_machine_configure::custom_render(void *selectedref, float top, float bottom, float origx1, float origy1, float origx2, float origy2) { - char const *const text[] = { _("Configure machine:"), m_drv->type.fullname() }; + char const *const text[] = { _("Configure machine:"), m_drv.type.fullname() }; draw_text_box( std::begin(text), std::end(text), origx1, origx2, origy1 - top, origy1 - UI_BOX_TB_BORDER, @@ -800,19 +809,19 @@ void menu_machine_configure::custom_render(void *selectedref, float top, float b void menu_machine_configure::setup_bios() { - if (m_drv->rom == nullptr) + if (!m_drv.rom) return; std::string specbios(m_opts.bios()); char const *default_name(nullptr); - for (tiny_rom_entry const *rom = m_drv->rom; !ROMENTRY_ISEND(rom); ++rom) + for (tiny_rom_entry const *rom = m_drv.rom; !ROMENTRY_ISEND(rom); ++rom) { if (ROMENTRY_ISDEFAULT_BIOS(rom)) default_name = rom->name; } std::size_t bios_count = 0; - for (romload::system_bios const &bios : romload::entries(m_drv->rom).get_system_bioses()) + for (romload::system_bios const &bios : romload::entries(m_drv.rom).get_system_bioses()) { std::string name(bios.get_description()); u32 const bios_flags(bios.get_value()); diff --git a/src/frontend/mame/ui/miscmenu.h b/src/frontend/mame/ui/miscmenu.h index 65ef235de57..4df94c60a78 100644 --- a/src/frontend/mame/ui/miscmenu.h +++ b/src/frontend/mame/ui/miscmenu.h @@ -20,6 +20,7 @@ #include namespace ui { + class menu_keyboard_mode : public menu { public: @@ -134,7 +135,12 @@ private: class menu_machine_configure : public menu { public: - menu_machine_configure(mame_ui_manager &mui, render_container &container, const game_driver *prev, float x0 = 0.0f, float y0 = 0.0f); + menu_machine_configure( + mame_ui_manager &mui, + render_container &container, + game_driver const &drv, + std::function &&handler = nullptr, + float x0 = 0.0f, float y0 = 0.0f); virtual ~menu_machine_configure(); protected: @@ -158,13 +164,17 @@ private: virtual void populate(float &customtop, float &custombottom) override; virtual void handle() override; - const game_driver *m_drv; + void setup_bios(); + + std::function const m_handler; + game_driver const &m_drv; emu_options m_opts; - float x0, y0; + float const m_x0; + float const m_y0; s_bios m_bios; std::size_t m_curbios; - void setup_bios(); - bool m_fav_reset; + bool const m_was_favorite; + bool m_want_favorite; }; //------------------------------------------------- @@ -186,4 +196,4 @@ protected: } // namespace ui -#endif /* MAME_FRONTEND_UI_MISCMENU_H */ +#endif // MAME_FRONTEND_UI_MISCMENU_H diff --git a/src/frontend/mame/ui/optsmenu.cpp b/src/frontend/mame/ui/optsmenu.cpp index fd29c3329bc..4452fae9bce 100644 --- a/src/frontend/mame/ui/optsmenu.cpp +++ b/src/frontend/mame/ui/optsmenu.cpp @@ -30,182 +30,44 @@ namespace ui { // ctor //------------------------------------------------- -menu_game_options::menu_game_options(mame_ui_manager &mui, render_container &container) : menu(mui, container) +menu_simple_game_options::menu_simple_game_options( + mame_ui_manager &mui, + render_container &container, + std::function &&handler) + : menu(mui, container) + , m_handler(std::move(handler)) { - m_main = main_filters::actual; } //------------------------------------------------- // dtor //------------------------------------------------- -menu_game_options::~menu_game_options() +menu_simple_game_options::~menu_simple_game_options() { - main_filters::actual = m_main; - reset_topmost(reset_options::SELECT_FIRST); ui().save_ui_options(); - ui_globals::switch_image = true; + if (m_handler) + m_handler(); } //------------------------------------------------- // handle //------------------------------------------------- -void menu_game_options::handle() +void menu_simple_game_options::handle() { - bool changed = false; - // process the menu - const event *menu_event; - if (machine().options().ui() == emu_options::UI_SIMPLE) - { - menu_event = process(PROCESS_LR_REPEAT); - } - else - { - process_parent(); - menu_event = process(PROCESS_LR_REPEAT | PROCESS_NOIMAGE); - } - - if (menu_event != nullptr && menu_event->itemref != nullptr) - switch ((uintptr_t)menu_event->itemref) - { - case FILTER_MENU: - if (menu_event->iptkey == IPT_UI_LEFT || menu_event->iptkey == IPT_UI_RIGHT) - { - (menu_event->iptkey == IPT_UI_RIGHT) ? ++m_main : --m_main; - changed = true; - } - else if (menu_event->iptkey == IPT_UI_SELECT) - { - std::vector s_sel(machine_filter::COUNT); - for (unsigned index = 0; index < s_sel.size(); ++index) - s_sel[index] = machine_filter::display_name(machine_filter::type(index)); - - menu::stack_push( - ui(), container(), std::move(s_sel), m_main, - [this] (int selection) - { - m_main = machine_filter::type(selection); - reset(reset_options::REMEMBER_REF); - }); - } - break; - case FILTER_ADJUST: - if (menu_event->iptkey == IPT_UI_LEFT) - { - changed = main_filters::filters.find(m_main)->second->adjust_left(); - } - else if (menu_event->iptkey == IPT_UI_RIGHT) - { - changed = main_filters::filters.find(m_main)->second->adjust_right(); - } - else if (menu_event->iptkey == IPT_UI_SELECT) - { - main_filters::filters.find(m_main)->second->show_ui( - ui(), - container(), - [this] (machine_filter &filter) - { - if (machine_filter::CUSTOM == filter.get_type()) - { - emu_file file(ui().options().ui_path(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS); - if (file.open("custom_", emulator_info::get_configname(), "_filter.ini") == osd_file::error::NONE) - { - filter.save_ini(file, 0); - file.close(); - } - } - reset(reset_options::REMEMBER_REF); - }); - } - break; - case CONF_DIR: - if (menu_event->iptkey == IPT_UI_SELECT) - menu::stack_push(ui(), container()); - break; - case MISC_MENU: - if (menu_event->iptkey == IPT_UI_SELECT) - { - menu::stack_push(ui(), container(), submenu::misc_options); - ui_globals::reset = true; - } - break; - case SOUND_MENU: - if (menu_event->iptkey == IPT_UI_SELECT) - { - menu::stack_push(ui(), container()); - ui_globals::reset = true; - } - break; - case DISPLAY_MENU: - if (menu_event->iptkey == IPT_UI_SELECT) - { - menu::stack_push(ui(), container(), submenu::video_options); - ui_globals::reset = true; - } - break; - case CUSTOM_MENU: - if (menu_event->iptkey == IPT_UI_SELECT) - menu::stack_push(ui(), container()); - break; - case CONTROLLER_MENU: - if (menu_event->iptkey == IPT_UI_SELECT) - menu::stack_push(ui(), container(), submenu::control_options); - break; - case CGI_MENU: - if (menu_event->iptkey == IPT_UI_SELECT) - menu::stack_push(ui(), container()); - break; - case ADVANCED_MENU: - if (menu_event->iptkey == IPT_UI_SELECT) - { - menu::stack_push(ui(), container(), submenu::advanced_options); - ui_globals::reset = true; - } - break; - case SAVE_CONFIG: - if (menu_event->iptkey == IPT_UI_SELECT) - ui().save_main_option(); - break; - } - - if (changed) - reset(reset_options::REMEMBER_REF); + event const *const menu_event(process(PROCESS_LR_REPEAT)); + if (menu_event && menu_event->itemref) + handle_item_event(*menu_event); } //------------------------------------------------- // populate //------------------------------------------------- -void menu_game_options::populate(float &customtop, float &custombottom) +void menu_simple_game_options::populate(float &customtop, float &custombottom) { - if (machine().options().ui() != emu_options::UI_SIMPLE) - { - // set filter arrow - std::string fbuff; - - // add filter item - uint32_t arrow_flags = get_arrow_flags(machine_filter::FIRST, machine_filter::LAST, m_main); - auto active_filter(main_filters::filters.find(m_main)); - if (main_filters::filters.end() == active_filter) - active_filter = main_filters::filters.emplace(m_main, machine_filter::create(m_main)).first; - item_append(_("Filter"), active_filter->second->display_name(), arrow_flags, (void *)(uintptr_t)FILTER_MENU); - - // add subitem if the filter wants it - if (active_filter->second->wants_adjuster()) - { - std::string name("^!"); - convert_command_glyph(name); - item_append(name, active_filter->second->adjust_text(), active_filter->second->arrow_flags(), (void *)(FILTER_ADJUST)); - } - - item_append(menu_item_type::SEPARATOR); - - // add options items - item_append(_("Customize UI"), "", 0, (void *)(uintptr_t)CUSTOM_MENU); - item_append(_("Configure Directories"), "", 0, (void *)(uintptr_t)CONF_DIR); - } item_append(_(submenu::video_options[0].description), "", 0, (void *)(uintptr_t)DISPLAY_MENU); item_append(_("Sound Options"), "", 0, (void *)(uintptr_t)SOUND_MENU); item_append(_(submenu::misc_options[0].description), "", 0, (void *)(uintptr_t)MISC_MENU); @@ -219,11 +81,62 @@ void menu_game_options::populate(float &customtop, float &custombottom) customtop = ui().get_line_height() + 3.0f * UI_BOX_TB_BORDER; } +//------------------------------------------------- +// handle item +//------------------------------------------------- + +void menu_simple_game_options::handle_item_event(event const &menu_event) +{ + switch ((uintptr_t)menu_event.itemref) + { + case MISC_MENU: + if (menu_event.iptkey == IPT_UI_SELECT) + { + menu::stack_push(ui(), container(), submenu::misc_options); + ui_globals::reset = true; + } + break; + case SOUND_MENU: + if (menu_event.iptkey == IPT_UI_SELECT) + { + menu::stack_push(ui(), container()); + ui_globals::reset = true; + } + break; + case DISPLAY_MENU: + if (menu_event.iptkey == IPT_UI_SELECT) + { + menu::stack_push(ui(), container(), submenu::video_options); + ui_globals::reset = true; + } + break; + case CONTROLLER_MENU: + if (menu_event.iptkey == IPT_UI_SELECT) + menu::stack_push(ui(), container(), submenu::control_options); + break; + case CGI_MENU: + if (menu_event.iptkey == IPT_UI_SELECT) + menu::stack_push(ui(), container()); + break; + case ADVANCED_MENU: + if (menu_event.iptkey == IPT_UI_SELECT) + { + menu::stack_push(ui(), container(), submenu::advanced_options); + ui_globals::reset = true; + } + break; + case SAVE_CONFIG: + if (menu_event.iptkey == IPT_UI_SELECT) + ui().save_main_option(); + break; + } +} + //------------------------------------------------- // perform our special rendering //------------------------------------------------- -void menu_game_options::custom_render(void *selectedref, float top, float bottom, float origx1, float origy1, float origx2, float origy2) +void menu_simple_game_options::custom_render(void *selectedref, float top, float bottom, float origx1, float origy1, float origx2, float origy2) { char const *const toptext[] = { _("Settings") }; draw_text_box( @@ -234,4 +147,150 @@ void menu_game_options::custom_render(void *selectedref, float top, float bottom } +//------------------------------------------------- +// ctor +//------------------------------------------------- + +menu_game_options::menu_game_options( + mame_ui_manager &mui, + render_container &container, + machine_filter_data &filter_data, + std::function &&handler) + : menu_simple_game_options(mui, container, std::move(handler)) + , m_filter_data(filter_data) + , m_main_filter(filter_data.get_current_filter_type()) +{ +} + +//------------------------------------------------- +// dtor +//------------------------------------------------- + +menu_game_options::~menu_game_options() +{ + m_filter_data.set_current_filter_type(m_main_filter); +} + +//------------------------------------------------- +// handle +//------------------------------------------------- + +void menu_game_options::handle() +{ + // process the menu + process_parent(); + event const *const menu_event(process(PROCESS_LR_REPEAT | PROCESS_NOIMAGE)); + if (menu_event && menu_event->itemref) + handle_item_event(*menu_event); +} + +//------------------------------------------------- +// populate +//------------------------------------------------- + +void menu_game_options::populate(float &customtop, float &custombottom) +{ + // set filter arrow + std::string fbuff; + + // add filter item + uint32_t arrow_flags = get_arrow_flags(machine_filter::FIRST, machine_filter::LAST, m_main_filter); + machine_filter &active_filter(m_filter_data.get_filter(m_main_filter)); + item_append(_("Filter"), active_filter.display_name(), arrow_flags, (void *)(uintptr_t)FILTER_MENU); + + // add subitem if the filter wants it + if (active_filter.wants_adjuster()) + { + std::string name("^!"); + convert_command_glyph(name); + item_append(name, active_filter.adjust_text(), active_filter.arrow_flags(), (void *)(FILTER_ADJUST)); + } + + item_append(menu_item_type::SEPARATOR); + + // add options items + item_append(_("Customize UI"), "", 0, (void *)(uintptr_t)CUSTOM_MENU); + item_append(_("Configure Directories"), "", 0, (void *)(uintptr_t)CONF_DIR); + + // add the options that don't relate to the UI + menu_simple_game_options::populate(customtop, custombottom); +} + +//------------------------------------------------- +// handle item +//------------------------------------------------- + +void menu_game_options::handle_item_event(event const &menu_event) +{ + bool changed = false; + + switch ((uintptr_t)menu_event.itemref) + { + case FILTER_MENU: + if (menu_event.iptkey == IPT_UI_LEFT || menu_event.iptkey == IPT_UI_RIGHT) + { + (menu_event.iptkey == IPT_UI_RIGHT) ? ++m_main_filter : --m_main_filter; + changed = true; + } + else if (menu_event.iptkey == IPT_UI_SELECT) + { + std::vector s_sel(machine_filter::COUNT); + for (unsigned index = 0; index < s_sel.size(); ++index) + s_sel[index] = machine_filter::display_name(machine_filter::type(index)); + + menu::stack_push( + ui(), container(), std::move(s_sel), m_main_filter, + [this] (int selection) + { + m_main_filter = machine_filter::type(selection); + reset(reset_options::REMEMBER_REF); + }); + } + break; + case FILTER_ADJUST: + if (menu_event.iptkey == IPT_UI_LEFT) + { + changed = m_filter_data.get_filter(m_main_filter).adjust_left(); + } + else if (menu_event.iptkey == IPT_UI_RIGHT) + { + changed = m_filter_data.get_filter(m_main_filter).adjust_right(); + } + else if (menu_event.iptkey == IPT_UI_SELECT) + { + m_filter_data.get_filter(m_main_filter).show_ui( + ui(), + container(), + [this] (machine_filter &filter) + { + if (machine_filter::CUSTOM == filter.get_type()) + { + emu_file file(ui().options().ui_path(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS); + if (file.open("custom_", emulator_info::get_configname(), "_filter.ini") == osd_file::error::NONE) + { + filter.save_ini(file, 0); + file.close(); + } + } + reset(reset_options::REMEMBER_REF); + }); + } + break; + case CONF_DIR: + if (menu_event.iptkey == IPT_UI_SELECT) + menu::stack_push(ui(), container()); + break; + case CUSTOM_MENU: + if (menu_event.iptkey == IPT_UI_SELECT) + menu::stack_push(ui(), container()); + break; + default: + menu_simple_game_options::handle_item_event(menu_event); + return; + } + + if (changed) + reset(reset_options::REMEMBER_REF); +} + } // namespace ui diff --git a/src/frontend/mame/ui/optsmenu.h b/src/frontend/mame/ui/optsmenu.h index e9650e3a95b..2afe9b68a89 100644 --- a/src/frontend/mame/ui/optsmenu.h +++ b/src/frontend/mame/ui/optsmenu.h @@ -17,23 +17,27 @@ namespace ui { -class menu_game_options : public menu + +class menu_simple_game_options : public menu { public: - menu_game_options(mame_ui_manager &mui, render_container &container); - virtual ~menu_game_options() override; + menu_simple_game_options( + mame_ui_manager &mui, + render_container &container, + std::function &&handler); + virtual ~menu_simple_game_options() override; protected: virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override; + virtual void handle() override; + virtual void populate(float &customtop, float &custombottom) override; + + void handle_item_event(event const &menu_event); private: enum { - FILTER_MENU = 1, - FILTER_ADJUST, - CONF_DIR, - DISPLAY_MENU, - CUSTOM_MENU, + DISPLAY_MENU = 1001, SOUND_MENU, CONTROLLER_MENU, MISC_MENU, @@ -43,12 +47,39 @@ private: SAVE_CONFIG }; - virtual void populate(float &customtop, float &custombottom) override; + std::function const m_handler; +}; + + +class menu_game_options : public menu_simple_game_options +{ +public: + menu_game_options( + mame_ui_manager &mui, + render_container &container, + machine_filter_data &filter_data, + std::function &&handler); + virtual ~menu_game_options() override; + +protected: virtual void handle() override; + virtual void populate(float &customtop, float &custombottom) override; + + void handle_item_event(event const &menu_event); + +private: + enum + { + FILTER_MENU = 2001, + FILTER_ADJUST, + CONF_DIR, + CUSTOM_MENU + }; - machine_filter::type m_main; + machine_filter_data &m_filter_data; + machine_filter::type m_main_filter; }; } // namespace ui -#endif /* MAME_FRONTEND_UI_OPTSMENU_H */ +#endif // MAME_FRONTEND_UI_OPTSMENU_H diff --git a/src/frontend/mame/ui/selector.cpp b/src/frontend/mame/ui/selector.cpp index 7f5441afc2c..83738641142 100644 --- a/src/frontend/mame/ui/selector.cpp +++ b/src/frontend/mame/ui/selector.cpp @@ -60,7 +60,6 @@ void menu_selector::handle() m_handler(selection); - ui_globals::switch_image = true; 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 acc9dd666b1..c36392e8b10 100644 --- a/src/frontend/mame/ui/selgame.cpp +++ b/src/frontend/mame/ui/selgame.cpp @@ -39,6 +39,8 @@ #include #include +#include "ui/icorender.h" // this is inline code + extern const char UI_VERSION_TAG[]; @@ -49,21 +51,15 @@ class menu_select_game::persistent_data public: enum available : unsigned { - AVAIL_NONE = 0, - AVAIL_SORTED_LIST = 1 << 0, - AVAIL_BIOS_COUNT = 1 << 1, - AVAIL_UCS_SHORTNAME = 1 << 2, - AVAIL_UCS_DESCRIPTION = 1 << 3, - AVAIL_UCS_MANUF_DESC = 1 << 4 + AVAIL_NONE = 0U, + AVAIL_SORTED_LIST = 1U << 0, + AVAIL_BIOS_COUNT = 1U << 1, + AVAIL_UCS_SHORTNAME = 1U << 2, + AVAIL_UCS_DESCRIPTION = 1U << 3, + AVAIL_UCS_MANUF_DESC = 1U << 4, + AVAIL_FILTER_DATA = 1U << 5 }; - persistent_data() - : m_started(false) - , m_available(AVAIL_NONE) - , m_bios_count(0) - { - } - ~persistent_data() { if (m_thread) @@ -109,7 +105,26 @@ public: return std::find_if(m_sorted_list.begin(), m_sorted_list.end(), [] (ui_system_info const &info) { return !info.available; }) != m_sorted_list.end(); } + machine_filter_data &filter_data() + { + wait_available(AVAIL_FILTER_DATA); + return m_filter_data; + } + + static persistent_data &instance() + { + static persistent_data data; + return data; + } + private: + persistent_data() + : m_started(false) + , m_available(AVAIL_NONE) + , m_bios_count(0) + { + } + void notify_available(available value) { std::unique_lock lock(m_mutex); @@ -140,8 +155,8 @@ private: ++m_bios_count; m_sorted_list.emplace_back(driver, x, false); - c_mnfct::add(driver.manufacturer); - c_year::add(driver.year); + m_filter_data.add_manufacturer(driver.manufacturer); + m_filter_data.add_year(driver.year); } } @@ -155,6 +170,10 @@ private: [] (ui_system_info const &lhs, ui_system_info const &rhs) { return sorted_game_list(lhs.driver, rhs.driver); }); notify_available(AVAIL_SORTED_LIST); + // sort manufacturers and years + m_filter_data.finalise(); + notify_available(AVAIL_FILTER_DATA); + // convert shortnames to UCS-4 for (ui_system_info &info : m_sorted_list) info.ucs_shortname = ustr_from_utf8(normalize_unicode(info.driver->name, unicode_normalization_form::D, true)); @@ -175,22 +194,21 @@ private: info.ucs_manufacturer_description = ustr_from_utf8(normalize_unicode(buf, unicode_normalization_form::D, true)); } notify_available(AVAIL_UCS_MANUF_DESC); - - // sort manufacturers and years - c_mnfct::finalise(); - c_year::finalise(); } - std::mutex m_mutex; - std::condition_variable m_condition; - std::unique_ptr m_thread; - std::atomic m_started; - std::atomic m_available; - std::vector m_sorted_list; - int m_bios_count; + // synchronisation + std::mutex m_mutex; + std::condition_variable m_condition; + std::unique_ptr m_thread; + std::atomic m_started; + std::atomic m_available; + + // data + std::vector m_sorted_list; + machine_filter_data m_filter_data; + int m_bios_count; }; -menu_select_game::persistent_data menu_select_game::s_persistent_data; bool menu_select_game::s_first_start = true; @@ -200,15 +218,20 @@ bool menu_select_game::s_first_start = true; menu_select_game::menu_select_game(mame_ui_manager &mui, render_container &container, const char *gamename) : menu_select_launch(mui, container, false) + , m_persistent_data(persistent_data::instance()) + , m_icons(MAX_ICONS_RENDER) + , m_has_icons(false) + , m_displaylist() + , m_searchlist() + , m_searched_fields(persistent_data::AVAIL_NONE) { std::string error_string, last_filter, sub_filter; ui_options &moptions = mui.options(); // load drivers cache - s_persistent_data.cache_data(); + m_persistent_data.cache_data(); // check if there are available icons - ui_globals::has_icons = false; file_enumerator path(moptions.icons_directory()); const osd::directory::entry *dir; while ((dir = path.next()) != nullptr) @@ -216,7 +239,7 @@ menu_select_game::menu_select_game(mame_ui_manager &mui, render_container &conta std::string src(dir->name); if (src.find(".ico") != std::string::npos || src.find("icons") != std::string::npos) { - ui_globals::has_icons = true; + m_has_icons = true; break; } } @@ -248,29 +271,21 @@ menu_select_game::menu_select_game(mame_ui_manager &mui, render_container &conta emu_file file(ui().options().ui_path(), OPEN_FLAG_READ); if (file.open_ram(fake_ini.c_str(), fake_ini.size()) == osd_file::error::NONE) { - machine_filter::ptr flt(machine_filter::create(file)); - if (flt) - { - main_filters::actual = flt->get_type(); - main_filters::filters.emplace(main_filters::actual, std::move(flt)); - } + m_persistent_data.filter_data().load_ini(file); file.close(); } } // do this after processing the last used filter setting so it overwrites the placeholder load_custom_filters(); - m_filter_highlight = main_filters::actual; + m_filter_highlight = m_persistent_data.filter_data().get_current_filter_type(); if (!moptions.remember_last()) reselect_last::reset(); mui.machine().options().set_value(OPTION_SNAPNAME, "%g/%i", OPTION_PRIORITY_CMDLINE); - ui_globals::curimage_view = FIRST_VIEW; ui_globals::curdats_view = 0; - ui_globals::switch_image = false; - ui_globals::default_image = true; ui_globals::panels_status = moptions.hide_panels(); ui_globals::curdats_total = 1; } @@ -291,17 +306,7 @@ menu_select_game::~menu_select_game() if (driver) last_driver = driver->name; - std::string filter; - auto const active_filter(main_filters::filters.find(main_filters::actual)); - if (main_filters::filters.end() != active_filter) - { - char const *val(active_filter->second->filter_text()); - filter = val ? util::string_format("%s,%s", active_filter->second->config_name(), val) : active_filter->second->config_name(); - } - else - { - filter = machine_filter::config_name(main_filters::actual); - } + std::string const filter(m_persistent_data.filter_data().get_config_string()); ui_options &mopt = ui().options(); mopt.set_value(OPTION_LAST_RIGHT_PANEL, ui_globals::rpanel, OPTION_PRIORITY_CMDLINE); @@ -405,7 +410,8 @@ void menu_select_game::handle() { menu::stack_push( ui(), container(), - reinterpret_cast(m_prev_selected), + *reinterpret_cast(m_prev_selected), + nullptr, menu_event->mouse.x0, menu_event->mouse.y0); } else @@ -413,18 +419,21 @@ void menu_select_game::handle() ui_software_info *sw = reinterpret_cast(m_prev_selected); menu::stack_push( ui(), container(), - (const game_driver *)sw->driver, + *sw->driver, + [this, empty = sw->startempty] (bool fav, bool changed) + { + if (changed) + reset(empty ? reset_options::SELECT_FIRST : reset_options::REMEMBER_REF); + }, menu_event->mouse.x0, menu_event->mouse.y0); } break; case IPT_UI_LEFT: - if (ui_globals::rpanel == RP_IMAGES && ui_globals::curimage_view > FIRST_VIEW) + if (ui_globals::rpanel == RP_IMAGES) { // Images - ui_globals::curimage_view--; - ui_globals::switch_image = true; - ui_globals::default_image = false; + previous_image_view(); } else if (ui_globals::rpanel == RP_INFOS) { @@ -434,12 +443,10 @@ void menu_select_game::handle() break; case IPT_UI_RIGHT: - if (ui_globals::rpanel == RP_IMAGES && ui_globals::curimage_view < LAST_VIEW) + if (ui_globals::rpanel == RP_IMAGES) { // Images - ui_globals::curimage_view++; - ui_globals::switch_image = true; - ui_globals::default_image = false; + next_image_view(); } else if (ui_globals::rpanel == RP_INFOS) { @@ -455,14 +462,14 @@ void menu_select_game::handle() if (!isfavorite()) { game_driver const *const driver(reinterpret_cast(menu_event->itemref)); - if (!mfav.isgame_favorite(driver)) + if (!mfav.is_favorite_system(*driver)) { - mfav.add_favorite_game(driver); + mfav.add_favorite_system(*driver); machine().popmessage(_("%s\n added to favorites list."), driver->type.fullname()); } else { - mfav.remove_favorite_game(); + mfav.remove_favorite_system(*driver); machine().popmessage(_("%s\n removed from favorites list."), driver->type.fullname()); } } @@ -470,19 +477,19 @@ void menu_select_game::handle() { ui_software_info const *const swinfo(reinterpret_cast(menu_event->itemref)); machine().popmessage(_("%s\n removed from favorites list."), swinfo->longname); - mfav.remove_favorite_game(*swinfo); + mfav.remove_favorite_software(*swinfo); reset(reset_options::SELECT_FIRST); } } break; case IPT_UI_AUDIT_FAST: - if (s_persistent_data.unavailable_systems()) - menu::stack_push(ui(), container(), s_persistent_data.sorted_list(), menu_audit::mode::FAST); + if (m_persistent_data.unavailable_systems()) + menu::stack_push(ui(), container(), m_persistent_data.sorted_list(), menu_audit::mode::FAST); break; case IPT_UI_AUDIT_ALL: - menu::stack_push(ui(), container(), s_persistent_data.sorted_list(), menu_audit::mode::ALL); + menu::stack_push(ui(), container(), m_persistent_data.sorted_list(), menu_audit::mode::ALL); break; } } @@ -499,10 +506,10 @@ void menu_select_game::handle() void menu_select_game::populate(float &customtop, float &custombottom) { - ui_globals::redraw_icon = true; - ui_globals::switch_image = true; + set_redraw_icon(); + set_switch_image(); int old_item_selected = -1; - uint32_t flags_ui = FLAG_LEFT_ARROW | FLAG_RIGHT_ARROW; + constexpr uint32_t flags_ui = FLAG_LEFT_ARROW | FLAG_RIGHT_ARROW; if (!isfavorite()) { @@ -518,12 +525,12 @@ void menu_select_game::populate(float &customtop, float &custombottom) m_displaylist.clear(); // if filter is set on category, build category list - auto const it(main_filters::filters.find(main_filters::actual)); - std::vector const &sorted(s_persistent_data.sorted_list()); - if (main_filters::filters.end() == it) + machine_filter const *const flt(m_persistent_data.filter_data().get_current_filter()); + std::vector const &sorted(m_persistent_data.sorted_list()); + if (!flt) std::copy(sorted.begin(), sorted.end(), std::back_inserter(m_displaylist)); else - it->second->apply(sorted.begin(), sorted.end(), std::back_inserter(m_displaylist)); + flt->apply(sorted.begin(), sorted.end(), std::back_inserter(m_displaylist)); // iterate over entries int curitem = 0; @@ -549,36 +556,34 @@ void menu_select_game::populate(float &customtop, float &custombottom) { // populate favorites list m_search.clear(); - int curitem = 0; - - // iterate over entries - for (auto &favmap : mame_machine_manager::instance()->favorite().m_list) - { - auto flags = flags_ui | FLAG_UI_FAVORITE; - if (favmap.second.startempty == 1) - { - if (old_item_selected == -1 && favmap.second.shortname == reselect_last::driver()) - old_item_selected = curitem; - - bool cloneof = strcmp(favmap.second.driver->parent, "0"); - if (cloneof) + mame_machine_manager::instance()->favorite().apply_sorted( + [this, &old_item_selected, curitem = 0] (ui_software_info const &info) mutable { - int cx = driver_list::find(favmap.second.driver->parent); - if (cx != -1 && ((driver_list::driver(cx).flags & machine_flags::IS_BIOS_ROOT) != 0)) - cloneof = false; - } + auto flags = flags_ui | FLAG_UI_FAVORITE; + if (info.startempty == 1) + { + if (old_item_selected == -1 && info.shortname == reselect_last::driver()) + old_item_selected = curitem; - item_append(favmap.second.longname, "", (cloneof) ? (flags | FLAG_INVERT) : flags, (void *)&favmap.second); - } - else - { - if (old_item_selected == -1 && favmap.second.shortname == reselect_last::driver()) - old_item_selected = curitem; - item_append(favmap.second.longname, favmap.second.devicetype, - favmap.second.parentname.empty() ? flags : (FLAG_INVERT | flags), (void *)&favmap.second); - } - curitem++; - } + bool cloneof = strcmp(info.driver->parent, "0"); + if (cloneof) + { + int cx = driver_list::find(info.driver->parent); + if (cx != -1 && ((driver_list::driver(cx).flags & machine_flags::IS_BIOS_ROOT) != 0)) + cloneof = false; + } + + item_append(info.longname, "", (cloneof) ? (flags | FLAG_INVERT) : flags, (void *)&info); + } + else + { + if (old_item_selected == -1 && info.shortname == reselect_last::driver()) + old_item_selected = curitem; + item_append(info.longname, info.devicetype, + info.parentname.empty() ? flags : (FLAG_INVERT | flags), (void *)&info); + } + curitem++; + }); } item_append(menu_item_type::SEPARATOR, flags_ui); @@ -639,11 +644,11 @@ void menu_select_game::build_available_list() // build a name for it for (src = dir->name; *src != 0 && *src != '.' && dst < &drivername[ARRAY_LENGTH(drivername) - 1]; ++src) - *dst++ = tolower((uint8_t) * src); + *dst++ = tolower(uint8_t(*src)); *dst = 0; - int drivnum = driver_list::find(drivername); - if (drivnum != -1 && !included[drivnum]) + int const drivnum = driver_list::find(drivername); + if (0 <= drivnum) included[drivnum] = true; } @@ -715,7 +720,7 @@ void menu_select_game::build_available_list() } // copy into the persistent sorted list - for (ui_system_info &info : s_persistent_data.sorted_list()) + for (ui_system_info &info : m_persistent_data.sorted_list()) info.available = included[info.index]; } @@ -752,13 +757,17 @@ void menu_select_game::inkey_select(const event *menu_event) if ((uintptr_t)driver == CONF_OPTS) { // special case for configure options - menu::stack_push(ui(), container()); + menu::stack_push( + ui(), + container(), + m_persistent_data.filter_data(), + [this] () { reset(reset_options::SELECT_FIRST); }); } else if (uintptr_t(driver) == CONF_MACHINE) { // special case for configure machine if (m_prev_selected) - menu::stack_push(ui(), container(), reinterpret_cast(m_prev_selected)); + menu::stack_push(ui(), container(), *reinterpret_cast(m_prev_selected)); return; } else if ((uintptr_t)driver == CONF_PLUGINS) @@ -810,7 +819,11 @@ void menu_select_game::inkey_select_favorite(const event *menu_event) if ((uintptr_t)ui_swinfo == CONF_OPTS) { // special case for configure options - menu::stack_push(ui(), container()); + menu::stack_push( + ui(), + container(), + m_persistent_data.filter_data(), + [this] () { reset(reset_options::SELECT_FIRST); }); } else if ((uintptr_t)ui_swinfo == CONF_MACHINE) { @@ -818,7 +831,15 @@ void menu_select_game::inkey_select_favorite(const event *menu_event) if (m_prev_selected) { ui_software_info *swinfo = reinterpret_cast(m_prev_selected); - menu::stack_push(ui(), container(), (const game_driver *)swinfo->driver); + menu::stack_push( + ui(), + container(), + *swinfo->driver, + [this, empty = swinfo->startempty] (bool fav, bool changed) + { + if (changed) + reset(empty ? reset_options::SELECT_FIRST : reset_options::REMEMBER_REF); + }); } return; } @@ -889,7 +910,7 @@ void menu_select_game::inkey_select_favorite(const event *menu_event) bool menu_select_game::isfavorite() const { - return machine_filter::FAVORITE == main_filters::actual; + return machine_filter::FAVORITE == m_persistent_data.filter_data().get_current_filter_type(); } @@ -937,7 +958,7 @@ void menu_select_game::populate_search() // ensure search list is populated if (m_searchlist.empty()) { - std::vector const &sorted(s_persistent_data.sorted_list()); + std::vector const &sorted(m_persistent_data.sorted_list()); m_searchlist.reserve(sorted.size()); for (ui_system_info const &info : sorted) m_searchlist.emplace_back(1.0, std::ref(info)); @@ -945,20 +966,19 @@ void menu_select_game::populate_search() // keep track of what we matched against const std::u32string ucs_search(ustr_from_utf8(normalize_unicode(m_search, unicode_normalization_form::D, true))); - unsigned matched(0); // match shortnames - if (s_persistent_data.is_available(persistent_data::AVAIL_UCS_SHORTNAME)) + if (m_persistent_data.is_available(persistent_data::AVAIL_UCS_SHORTNAME)) { - matched |= persistent_data::AVAIL_UCS_SHORTNAME; + m_searched_fields |= persistent_data::AVAIL_UCS_SHORTNAME; for (std::pair > &info : m_searchlist) info.first = util::edit_distance(ucs_search, info.second.get().ucs_shortname); } // match descriptions - if (s_persistent_data.is_available(persistent_data::AVAIL_UCS_DESCRIPTION)) + if (m_persistent_data.is_available(persistent_data::AVAIL_UCS_DESCRIPTION)) { - matched |= persistent_data::AVAIL_UCS_DESCRIPTION; + m_searched_fields |= persistent_data::AVAIL_UCS_DESCRIPTION; for (std::pair > &info : m_searchlist) { if (info.first) @@ -970,9 +990,9 @@ void menu_select_game::populate_search() } // match " " - if (s_persistent_data.is_available(persistent_data::AVAIL_UCS_MANUF_DESC)) + if (m_persistent_data.is_available(persistent_data::AVAIL_UCS_MANUF_DESC)) { - matched |= persistent_data::AVAIL_UCS_MANUF_DESC; + m_searched_fields |= persistent_data::AVAIL_UCS_MANUF_DESC; for (std::pair > &info : m_searchlist) { if (info.first) @@ -1154,6 +1174,132 @@ void menu_select_game::general_info(const game_driver *driver, std::string &buff buffer = str.str(); } + +//------------------------------------------------- +// draw icons +//------------------------------------------------- + +float menu_select_game::draw_icon(int linenum, void *selectedref, float x0, float y0) +{ + if (!m_has_icons) + 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(); + + icon_cache::iterator icon(m_icons.find(driver)); + if ((m_icons.end() == icon) || redraw_icon()) + { + if (m_icons.end() == icon) + { + texture_ptr texture(machine().render().texture_alloc(), [&render = machine().render()] (render_texture *texture) { render.texture_free(texture); }); + icon = m_icons.emplace( + std::piecewise_construct, + std::forward_as_tuple(driver), + std::forward_as_tuple(std::piecewise_construct, std::forward_as_tuple(std::move(texture)), std::tuple<>())).first; + } + + // set clone status + bool cloneof = strcmp(driver->parent, "0"); + if (cloneof) + { + auto cx = driver_list::find(driver->parent); + if ((cx >= 0) && (driver_list::driver(cx).flags & machine_flags::IS_BIOS_ROOT)) + 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; + 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()); + } + + bitmap_argb32 &bitmap(icon->second.second); + 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 = std::min(ratioW, ratioH); + dest_xPixel = tmp.width() * ratio; + dest_yPixel = tmp.height() * ratio; + } + + bitmap_argb32 dest_bitmap; + + // 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 = std::move(tmp); + + bitmap.allocate(panel_width_pixel, panel_height_pixel); + for (int x = 0; x < dest_xPixel; x++) + for (int y = 0; y < dest_yPixel; y++) + bitmap.pix32(y, x) = dest_bitmap.pix32(y, x); + + icon->second.first->set_bitmap(bitmap, bitmap.cliprect(), TEXFORMAT_ARGB32); + } + else + { + bitmap.reset(); + } + } + + if (icon->second.second.valid()) + container().add_quad(x0, y0, x1, y1, rgb_t::white(), icon->second.first.get(), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA)); + + return ud_arrow_width * 1.5f; +} + + void menu_select_game::inkey_export() { std::vector list; @@ -1167,13 +1313,13 @@ void menu_select_game::inkey_export() if (isfavorite()) { // iterate over favorites - for (auto & favmap : mame_machine_manager::instance()->favorite().m_list) - { - if (favmap.second.startempty == 1) - list.push_back(favmap.second.driver); - else - return; - } + mame_machine_manager::instance()->favorite().apply( + [&list] (ui_software_info const &info) + { + assert(info.driver); + if (info.startempty) + list.push_back(info.driver); + }); } else { @@ -1228,7 +1374,7 @@ bool menu_select_game::load_available_machines() file.close(); // turn it into the sorted system list we all love - for (ui_system_info &info : s_persistent_data.sorted_list()) + for (ui_system_info &info : m_persistent_data.sorted_list()) { std::unordered_set::iterator const it(available.find(&info.driver->name[0])); bool const found(available.end() != it); @@ -1249,9 +1395,9 @@ void menu_select_game::load_custom_filters() emu_file file(ui().options().ui_path(), OPEN_FLAG_READ); if (file.open("custom_", emulator_info::get_configname(), "_filter.ini") == osd_file::error::NONE) { - machine_filter::ptr flt(machine_filter::create(file)); + machine_filter::ptr flt(machine_filter::create(file, m_persistent_data.filter_data())); if (flt) - main_filters::filters[flt->get_type()] = std::move(flt); // not emplace/insert - could replace bogus filter from ui.ini line + m_persistent_data.filter_data().set_filter(std::move(flt)); // not emplace/insert - could replace bogus filter from ui.ini line file.close(); } @@ -1264,7 +1410,8 @@ void menu_select_game::load_custom_filters() float menu_select_game::draw_left_panel(float x1, float y1, float x2, float y2) { - return menu_select_launch::draw_left_panel(main_filters::actual, main_filters::filters, x1, y1, x2, y2); + machine_filter_data &filter_data(m_persistent_data.filter_data()); + return menu_select_launch::draw_left_panel(filter_data.get_current_filter_type(), filter_data.get_filters(), x1, y1, x2, y2); } @@ -1293,7 +1440,7 @@ void menu_select_game::make_topbox_text(std::string &line0, std::string &line1, bare_build_version, visible_items, (driver_list::total() - 1), - s_persistent_data.bios_count()); + m_persistent_data.bios_count()); if (isfavorite()) { @@ -1301,10 +1448,10 @@ void menu_select_game::make_topbox_text(std::string &line0, std::string &line1, } else { - auto const it(main_filters::filters.find(main_filters::actual)); - char const *const filter((main_filters::filters.end() != it) ? it->second->filter_text() : nullptr); + machine_filter const *const it(m_persistent_data.filter_data().get_current_filter()); + char const *const filter(it ? it->filter_text() : nullptr); if (filter) - line1 = string_format(_("%1$s: %2$s - Search: %3$s_"), it->second->display_name(), filter, m_search); + line1 = string_format(_("%1$s: %2$s - Search: %3$s_"), it->display_name(), filter, m_search); else line1 = string_format(_("Search: %1$s_"), m_search); } @@ -1331,15 +1478,12 @@ void menu_select_game::filter_selected() { if ((machine_filter::FIRST <= m_filter_highlight) && (machine_filter::LAST >= m_filter_highlight)) { - m_search.clear(); - auto it(main_filters::filters.find(machine_filter::type(m_filter_highlight))); - if (main_filters::filters.end() == it) - it = main_filters::filters.emplace(machine_filter::type(m_filter_highlight), machine_filter::create(machine_filter::type(m_filter_highlight))).first; - it->second->show_ui( + m_persistent_data.filter_data().get_filter(machine_filter::type(m_filter_highlight)).show_ui( ui(), container(), [this] (machine_filter &filter) { + set_switch_image(); machine_filter::type const new_type(filter.get_type()); if (machine_filter::CUSTOM == new_type) { @@ -1350,7 +1494,7 @@ void menu_select_game::filter_selected() file.close(); } } - main_filters::actual = new_type; + m_persistent_data.filter_data().set_current_filter_type(new_type); reset(reset_options::SELECT_FIRST); }); } diff --git a/src/frontend/mame/ui/selgame.h b/src/frontend/mame/ui/selgame.h index d3ab264ed50..7d5d906a1c1 100644 --- a/src/frontend/mame/ui/selgame.h +++ b/src/frontend/mame/ui/selgame.h @@ -39,14 +39,19 @@ private: CONF_PLUGINS, }; + using icon_cache = util::lru_cache_map >; + class persistent_data; + persistent_data &m_persistent_data; + icon_cache m_icons; + bool m_has_icons; std::vector > m_displaylist; - static persistent_data s_persistent_data; - static bool s_first_start; - std::vector > > m_searchlist; + unsigned m_searched_fields; + + static bool s_first_start; virtual void populate(float &customtop, float &custombottom) override; virtual void handle() override; @@ -84,6 +89,9 @@ private: // General info virtual void general_info(const game_driver *driver, std::string &buffer) override; + // drawing + virtual float draw_icon(int linenum, void *selectedref, float x1, float y1) override; + // handlers void inkey_select(const event *menu_event); void inkey_select_favorite(const event *menu_event); diff --git a/src/frontend/mame/ui/selmenu.cpp b/src/frontend/mame/ui/selmenu.cpp index 90dd7af789f..2702ae9260d 100644 --- a/src/frontend/mame/ui/selmenu.cpp +++ b/src/frontend/mame/ui/selmenu.cpp @@ -12,7 +12,6 @@ #include "ui/selmenu.h" #include "ui/datmenu.h" -#include "ui/icorender.h" #include "ui/info.h" #include "ui/inifile.h" @@ -45,6 +44,28 @@ namespace ui { namespace { +enum +{ + FIRST_VIEW = 0, + SNAPSHOT_VIEW = FIRST_VIEW, + CABINETS_VIEW, + CPANELS_VIEW, + PCBS_VIEW, + FLYERS_VIEW, + TITLES_VIEW, + ENDS_VIEW, + ARTPREV_VIEW, + BOSSES_VIEW, + LOGOS_VIEW, + VERSUS_VIEW, + GAMEOVER_VIEW, + HOWTO_VIEW, + SCORES_VIEW, + SELECT_VIEW, + MARQUEES_VIEW, + LAST_VIEW = MARQUEES_VIEW +}; + std::pair const arts_info[] = { { __("Snapshots"), OPTION_SNAPSHOT_DIRECTORY }, @@ -437,8 +458,11 @@ menu_select_launch::menu_select_launch(mame_ui_manager &mui, render_container &c , m_pressed(false) , m_repeat(0) , m_right_visible_lines(0) + , m_redraw_icon(false) + , m_switch_image(false) + , m_default_image(true) + , m_image_view(FIRST_VIEW) , m_flags(256) - , m_icons(MAX_ICONS_RENDER) { // set up persistent cache for machine run { @@ -459,6 +483,28 @@ menu_select_launch::menu_select_launch(mame_ui_manager &mui, render_container &c } +void menu_select_launch::next_image_view() +{ + if (LAST_VIEW > m_image_view) + { + ++m_image_view; + set_switch_image(); + m_default_image = false; + } +} + + +void menu_select_launch::previous_image_view() +{ + if (FIRST_VIEW < m_image_view) + { + --m_image_view; + set_switch_image(); + m_default_image = false; + } +} + + bool menu_select_launch::dismiss_error() { bool const result = m_ui_error; @@ -562,7 +608,7 @@ void menu_select_launch::custom_render(void *selectedref, float top, float botto rgb_t color = UI_BACKGROUND_COLOR; if (swinfo && ((swinfo->startempty != 1) || !driver)) { - isstar = mame_machine_manager::instance()->favorite().isgame_favorite(*swinfo); + isstar = mame_machine_manager::instance()->favorite().is_favorite_system_software(*swinfo); // first line is long name or system tempbuf[0] = make_software_description(*swinfo); @@ -598,7 +644,7 @@ void menu_select_launch::custom_render(void *selectedref, float top, float botto } else if (driver) { - isstar = mame_machine_manager::instance()->favorite().isgame_favorite(driver); + isstar = mame_machine_manager::instance()->favorite().is_favorite_system(*driver); // first line is game description/game name tempbuf[0] = make_driver_description(*driver); @@ -1051,122 +1097,8 @@ void menu_select_launch::set_pressed() 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(); - - icon_cache::iterator icon(m_icons.find(driver)); - if ((m_icons.end() == icon) || ui_globals::redraw_icon) - { - if (m_icons.end() == icon) - { - texture_ptr texture(machine().render().texture_alloc(), [&render = machine().render()] (render_texture *texture) { render.texture_free(texture); }); - icon = m_icons.emplace( - std::piecewise_construct, - std::forward_as_tuple(driver), - std::forward_as_tuple(std::piecewise_construct, std::forward_as_tuple(std::move(texture)), std::tuple<>())).first; - } - - // set clone status - bool cloneof = strcmp(driver->parent, "0"); - if (cloneof) - { - auto cx = driver_list::find(driver->parent); - if ((cx >= 0) && (driver_list::driver(cx).flags & machine_flags::IS_BIOS_ROOT)) - 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; - 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()); - } - - bitmap_argb32 &bitmap(icon->second.second); - 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 = std::min(ratioW, ratioH); - dest_xPixel = tmp.width() * ratio; - dest_yPixel = tmp.height() * ratio; - } - - bitmap_argb32 dest_bitmap; - - // 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 = std::move(tmp); - - bitmap.allocate(panel_width_pixel, panel_height_pixel); - for (int x = 0; x < dest_xPixel; x++) - for (int y = 0; y < dest_yPixel; y++) - bitmap.pix32(y, x) = dest_bitmap.pix32(y, x); - - icon->second.first->set_bitmap(bitmap, bitmap.cliprect(), TEXFORMAT_ARGB32); - } - else - { - bitmap.reset(); - } - } - - if (icon->second.second.valid()) - container().add_quad(x0, y0, x1, y1, rgb_t::white(), icon->second.first.get(), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA)); - - return ud_arrow_width * 1.5f; + // derived class must implement this + return 0.0f; } @@ -1177,21 +1109,21 @@ float menu_select_launch::draw_icon(int linenum, void *selectedref, float x0, fl 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)); + snaptext.assign(_(arts_info[m_image_view].first)); // get search path std::string addpath; - if (ui_globals::curimage_view == SNAPSHOT_VIEW) + if (m_image_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); + searchstr = machine().options().value(arts_info[m_image_view].second); + addpath = moptions.value(arts_info[m_image_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); + searchstr = ui().options().value(arts_info[m_image_view].second); + addpath = moptions.value(arts_info[m_image_view].second); } std::string tmp(searchstr); @@ -1901,7 +1833,7 @@ void menu_select_launch::draw(uint32_t flags) 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; + m_redraw_icon = false; // noinput if (noinput) @@ -2044,14 +1976,14 @@ void menu_select_launch::arts_render(float origx1, float origy1, float origx2, f { m_cache->set_snapx_driver(nullptr); - if (ui_globals::default_image) - ui_globals::curimage_view = (software->startempty == 0) ? SNAPSHOT_VIEW : CABINETS_VIEW; + if (m_default_image) + m_image_view = (software->startempty == 0) ? SNAPSHOT_VIEW : CABINETS_VIEW; // arts title and searchpath std::string const searchstr = arts_render_common(origx1, origy1, origx2, origy2); // loads the image if necessary - if (!m_cache->snapx_software_is(software) || !snapx_valid() || ui_globals::switch_image) + if (!m_cache->snapx_software_is(software) || !snapx_valid() || m_switch_image) { emu_file snapfile(searchstr.c_str(), OPEN_FLAG_READ); bitmap_argb32 tmp_bitmap; @@ -2097,7 +2029,7 @@ void menu_select_launch::arts_render(float origx1, float origy1, float origx2, f } m_cache->set_snapx_software(software); - ui_globals::switch_image = false; + m_switch_image = false; arts_render_images(std::move(tmp_bitmap), origx1, origy1, origx2, origy2); } @@ -2108,13 +2040,13 @@ void menu_select_launch::arts_render(float origx1, float origy1, float origx2, f { m_cache->set_snapx_software(nullptr); - if (ui_globals::default_image) - ui_globals::curimage_view = ((driver->flags & machine_flags::MASK_TYPE) != machine_flags::TYPE_ARCADE) ? CABINETS_VIEW : SNAPSHOT_VIEW; + if (m_default_image) + m_image_view = ((driver->flags & machine_flags::MASK_TYPE) != machine_flags::TYPE_ARCADE) ? CABINETS_VIEW : SNAPSHOT_VIEW; std::string const searchstr = arts_render_common(origx1, origy1, origx2, origy2); // loads the image if necessary - if (!m_cache->snapx_driver_is(driver) || !snapx_valid() || ui_globals::switch_image) + if (!m_cache->snapx_driver_is(driver) || !snapx_valid() || m_switch_image) { emu_file snapfile(searchstr.c_str(), OPEN_FLAG_READ); snapfile.set_restrict_to_mediapath(true); @@ -2166,7 +2098,7 @@ void menu_select_launch::arts_render(float origx1, float origy1, float origx2, f } m_cache->set_snapx_driver(driver); - ui_globals::switch_image = false; + m_switch_image = false; arts_render_images(std::move(tmp_bitmap), origx1, origy1, origx2, origy2); } @@ -2224,7 +2156,7 @@ std::string menu_select_launch::arts_render_common(float origx1, float origy1, f ui::text_layout::CENTER, ui::text_layout::TRUNCATE, mame_ui_manager::NORMAL, fgcolor, bgcolor, nullptr, nullptr, tmp_size); - draw_common_arrow(origx1, origy1 + UI_BOX_TB_BORDER, origx2, origy2, ui_globals::curimage_view, FIRST_VIEW, LAST_VIEW, title_size); + draw_common_arrow(origx1, origy1 + UI_BOX_TB_BORDER, origx2, origy2, m_image_view, FIRST_VIEW, LAST_VIEW, title_size); return searchstr; } @@ -2274,7 +2206,7 @@ void menu_select_launch::arts_render_images(bitmap_argb32 &&tmp_bitmap, float or 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) + if (ui().options().forced_4x3_snapshot() && ratioI < 0.75f && m_image_view == SNAPSHOT_VIEW) { // smaller ratio will ensure that the image fits in the view dest_yPixel = tmp_bitmap.width() * 0.75f; diff --git a/src/frontend/mame/ui/selmenu.h b/src/frontend/mame/ui/selmenu.h index 1c5b6bdadd9..2dec44ac96c 100644 --- a/src/frontend/mame/ui/selmenu.h +++ b/src/frontend/mame/ui/selmenu.h @@ -34,6 +34,7 @@ public: virtual ~menu_select_launch() override; protected: + static constexpr std::size_t MAX_ICONS_RENDER = 128; // tab navigation enum class focused_menu @@ -93,6 +94,8 @@ protected: focused_menu get_focus() const { return m_focus; } void set_focus(focused_menu focus) { m_focus = focus; } + void next_image_view(); + void previous_image_view(); bool dismiss_error(); void set_error(reset_options ropt, std::string &&message); @@ -114,6 +117,11 @@ protected: void draw_common_arrow(float origx1, float origy1, float origx2, float origy2, int current, int dmin, int dmax, float title); void draw_info_arrow(int ub, float origx1, float origx2, float oy1, float line_height, float text_size, float ud_arrow_width); + // forcing refresh + bool redraw_icon() const { return m_redraw_icon; } + void set_redraw_icon() { m_redraw_icon = true; } + void set_switch_image() { m_switch_image = true; } + bool draw_error_text(); template @@ -188,9 +196,6 @@ private: using cache_ptr_map = std::map; using flags_cache = util::lru_cache_map; - using icon_cache = util::lru_cache_map >; - - static constexpr std::size_t MAX_ICONS_RENDER = 128; void reset_pressed() { m_pressed = false; m_repeat = 0; } bool mouse_pressed() const { return (osd_ticks() >= m_repeat); } @@ -230,7 +235,7 @@ private: void draw_toolbar(float x1, float y1, float x2, float y2); void draw_star(float x0, float y0); - float draw_icon(int linenum, void *selectedref, float x1, float y1); + virtual float draw_icon(int linenum, void *selectedref, float x1, float y1); void get_title_search(std::string &title, std::string &search); @@ -289,8 +294,11 @@ private: int m_right_visible_lines; // right box lines + bool m_redraw_icon; + bool m_switch_image; + bool m_default_image; + uint8_t m_image_view; flags_cache m_flags; - icon_cache m_icons; static std::mutex s_cache_guard; static cache_ptr_map s_caches; diff --git a/src/frontend/mame/ui/selsoft.cpp b/src/frontend/mame/ui/selsoft.cpp index e1eb1f75c33..5891ab73f2b 100644 --- a/src/frontend/mame/ui/selsoft.cpp +++ b/src/frontend/mame/ui/selsoft.cpp @@ -91,8 +91,7 @@ menu_select_software::menu_select_software(mame_ui_manager &mui, render_containe load_sw_custom_filters(); m_filter_highlight = m_filter_type; - ui_globals::curimage_view = SNAPSHOT_VIEW; - ui_globals::switch_image = true; + set_switch_image(); ui_globals::cur_sw_dats_view = 0; ui_globals::cur_sw_dats_total = 1; } @@ -103,8 +102,6 @@ menu_select_software::menu_select_software(mame_ui_manager &mui, render_containe menu_select_software::~menu_select_software() { - ui_globals::curimage_view = CABINETS_VIEW; - ui_globals::switch_image = true; } //------------------------------------------------- @@ -135,12 +132,10 @@ void menu_select_software::handle() break; case IPT_UI_LEFT: - if (ui_globals::rpanel == RP_IMAGES && ui_globals::curimage_view > FIRST_VIEW) + if (ui_globals::rpanel == RP_IMAGES) { // Images - ui_globals::curimage_view--; - ui_globals::switch_image = true; - ui_globals::default_image = false; + previous_image_view(); } else if (ui_globals::rpanel == RP_INFOS && ui_globals::cur_sw_dats_view > 0) { @@ -151,12 +146,10 @@ void menu_select_software::handle() break; case IPT_UI_RIGHT: - if (ui_globals::rpanel == RP_IMAGES && ui_globals::curimage_view < LAST_VIEW) + if (ui_globals::rpanel == RP_IMAGES) { // Images - ui_globals::curimage_view++; - ui_globals::switch_image = true; - ui_globals::default_image = false; + next_image_view(); } else if (ui_globals::rpanel == RP_INFOS && ui_globals::cur_sw_dats_view < (ui_globals::cur_sw_dats_total - 1)) { @@ -205,16 +198,16 @@ void menu_select_software::handle() if ((uintptr_t)swinfo > 2) { favorite_manager &mfav = mame_machine_manager::instance()->favorite(); - if (!mfav.isgame_favorite(*swinfo)) + if (!mfav.is_favorite_system_software(*swinfo)) { - mfav.add_favorite_game(*swinfo); + mfav.add_favorite_software(*swinfo); machine().popmessage(_("%s\n added to favorites list."), swinfo->longname.c_str()); } else { machine().popmessage(_("%s\n removed from favorites list."), swinfo->longname.c_str()); - mfav.remove_favorite_game(); + mfav.remove_favorite_software(*swinfo); } } } diff --git a/src/frontend/mame/ui/simpleselgame.cpp b/src/frontend/mame/ui/simpleselgame.cpp index 604c2b32d41..e22e61b6a2b 100644 --- a/src/frontend/mame/ui/simpleselgame.cpp +++ b/src/frontend/mame/ui/simpleselgame.cpp @@ -163,7 +163,13 @@ void simple_menu_select_game::inkey_select(const event *menu_event) // special case for configure inputs if ((uintptr_t)driver == 1) - menu::stack_push(ui(), container()); + { + menu::stack_push( + ui(), + container(), + [this] () { reset(reset_options::SELECT_FIRST); }); + } + // anything else is a driver else { diff --git a/src/frontend/mame/ui/utils.cpp b/src/frontend/mame/ui/utils.cpp index f82435d3864..baebce20bb3 100644 --- a/src/frontend/mame/ui/utils.cpp +++ b/src/frontend/mame/ui/utils.cpp @@ -98,26 +98,6 @@ constexpr char const *SOFTWARE_FILTER_NAMES[software_filter::COUNT] = { -//------------------------------------------------- -// static filter data -//------------------------------------------------- - -std::mutex f_filter_data_mutex; -std::condition_variable f_filter_data_condition; -std::atomic f_mnfct_finalised(false), f_year_finalised(false); -std::vector f_mnfct_ui, f_year_ui; -std::unordered_set f_mnfct_tmp, f_year_tmp; - -std::string trim_manufacturer(std::string const &mfg) -{ - size_t const found(mfg.find('(')); - if ((found != std::string::npos) && (found > 0)) - return mfg.substr(0, found - 1); - else - return mfg; -} - - //------------------------------------------------- // base implementation for simple filters //------------------------------------------------- @@ -664,7 +644,7 @@ template class available_machine_filter_impl : public simple_filter_impl_base { public: - available_machine_filter_impl(char const *value, emu_file *file, unsigned indent) { } + available_machine_filter_impl(machine_filter_data const &data, char const *value, emu_file *file, unsigned indent) { } virtual bool apply(ui_system_info const &system) const override { return system.available; } }; @@ -674,7 +654,7 @@ template class working_machine_filter_impl : public simple_filter_impl_base { public: - working_machine_filter_impl(char const *value, emu_file *file, unsigned indent) { } + working_machine_filter_impl(machine_filter_data const &data, char const *value, emu_file *file, unsigned indent) { } virtual bool apply(ui_system_info const &system) const override { return !(system.driver->flags & machine_flags::NOT_WORKING); } }; @@ -684,7 +664,7 @@ template class mechanical_machine_filter_impl : public simple_filter_impl_base { public: - mechanical_machine_filter_impl(char const *value, emu_file *file, unsigned indent) { } + mechanical_machine_filter_impl(machine_filter_data const &data, char const *value, emu_file *file, unsigned indent) { } virtual bool apply(ui_system_info const &system) const override { return system.driver->flags & machine_flags::MECHANICAL; } }; @@ -694,7 +674,7 @@ template class bios_machine_filter_impl : public simple_filter_impl_base { public: - bios_machine_filter_impl(char const *value, emu_file *file, unsigned indent) { } + bios_machine_filter_impl(machine_filter_data const &data, char const *value, emu_file *file, unsigned indent) { } virtual bool apply(ui_system_info const &system) const override { return system.driver->flags & machine_flags::IS_BIOS_ROOT; } }; @@ -704,7 +684,7 @@ template class parents_machine_filter_impl : public simple_filter_impl_base { public: - parents_machine_filter_impl(char const *value, emu_file *file, unsigned indent) { } + parents_machine_filter_impl(machine_filter_data const &data, char const *value, emu_file *file, unsigned indent) { } virtual bool apply(ui_system_info const &system) const override { @@ -719,7 +699,7 @@ template class chd_machine_filter_impl : public simple_filter_impl_base { public: - chd_machine_filter_impl(char const *value, emu_file *file, unsigned indent) { } + chd_machine_filter_impl(machine_filter_data const &data, char const *value, emu_file *file, unsigned indent) { } virtual bool apply(ui_system_info const &system) const override { @@ -737,7 +717,7 @@ template class save_machine_filter_impl : public simple_filter_impl_base { public: - save_machine_filter_impl(char const *value, emu_file *file, unsigned indent) { } + save_machine_filter_impl(machine_filter_data const &data, char const *value, emu_file *file, unsigned indent) { } virtual bool apply(ui_system_info const &system) const override { return system.driver->flags & machine_flags::SUPPORTS_SAVE; } }; @@ -747,7 +727,7 @@ template class vertical_machine_filter_impl : public simple_filter_impl_base { public: - vertical_machine_filter_impl(char const *value, emu_file *file, unsigned indent) { } + vertical_machine_filter_impl(machine_filter_data const &data, char const *value, emu_file *file, unsigned indent) { } virtual bool apply(ui_system_info const &system) const override { return system.driver->flags & machine_flags::SWAP_XY; } }; @@ -761,8 +741,8 @@ public: class manufacturer_machine_filter : public choice_filter_impl_base { public: - manufacturer_machine_filter(char const *value, emu_file *file, unsigned indent) - : choice_filter_impl_base(c_mnfct::ui(), value) + manufacturer_machine_filter(machine_filter_data const &data, char const *value, emu_file *file, unsigned indent) + : choice_filter_impl_base(data.manufacturers(), value) { } @@ -773,7 +753,7 @@ public: else if (!selection_valid()) return false; - std::string const name(trim_manufacturer(system.driver->manufacturer)); + std::string const name(machine_filter_data::extract_manufacturer(system.driver->manufacturer)); return !name.empty() && (selection_text() == name); } }; @@ -782,8 +762,8 @@ public: class year_machine_filter : public choice_filter_impl_base { public: - year_machine_filter(char const *value, emu_file *file, unsigned indent) - : choice_filter_impl_base(c_year::ui(), value) + year_machine_filter(machine_filter_data const &data, char const *value, emu_file *file, unsigned indent) + : choice_filter_impl_base(data.years(), value) { } @@ -800,7 +780,10 @@ template