mirror of
https://github.com/holub/mame
synced 2025-04-22 00:11:58 +03:00
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
This commit is contained in:
parent
8f330896e2
commit
ae727d2cc6
@ -300,16 +300,19 @@ int cli_frontend::execute(std::vector<std::string> &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());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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<inifile_manager>(machine, m_ui->options());
|
||||
m_inifile = std::make_unique<inifile_manager>(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<favorite_manager>(machine, m_ui->options());
|
||||
m_favorite = std::make_unique<favorite_manager>(m_ui->options());
|
||||
}
|
||||
|
||||
void mame_machine_manager::load_cheatfiles(running_machine& machine)
|
||||
|
@ -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 <algorithm>
|
||||
#include <cstring>
|
||||
#include <iterator>
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
auto software_avail = false;
|
||||
for (device_image_interface &image : image_interface_iterator(machine().root_device()))
|
||||
{
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
if (!software_avail)
|
||||
add_favorite_game(&machine().system());
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// remove a favorite from list
|
||||
//-------------------------------------------------
|
||||
|
||||
void favorite_manager::remove_favorite_game(ui_software_info const &swinfo)
|
||||
{
|
||||
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
|
||||
//-------------------------------------------------
|
||||
|
||||
void favorite_manager::remove_favorite_game()
|
||||
{
|
||||
m_list.erase(m_current);
|
||||
m_current = m_list.begin();
|
||||
save_favorite_games();
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// check if game is already in favorite list
|
||||
//-------------------------------------------------
|
||||
|
||||
bool favorite_manager::isgame_favorite()
|
||||
{
|
||||
if ((machine().system().flags & machine_flags::MASK_TYPE) == machine_flags::TYPE_ARCADE)
|
||||
return isgame_favorite(&machine().system());
|
||||
|
||||
auto image_loaded = false;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// check if game is already in favorite list
|
||||
//-------------------------------------------------
|
||||
|
||||
bool favorite_manager::isgame_favorite(const game_driver *driver)
|
||||
{
|
||||
for (auto current = m_list.begin(); current != m_list.end(); ++current)
|
||||
if (current->second.driver == driver && current->second.shortname == driver->name)
|
||||
{
|
||||
m_current = current;
|
||||
if (rhs.startempty)
|
||||
return false;
|
||||
else if (lhs.listname < rhs.listname)
|
||||
return true;
|
||||
}
|
||||
|
||||
m_current = m_list.begin();
|
||||
return false;
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// check if game is already in favorite list
|
||||
//-------------------------------------------------
|
||||
|
||||
bool favorite_manager::isgame_favorite(ui_software_info const &swinfo)
|
||||
{
|
||||
for (auto current = m_list.begin(); current != m_list.end(); ++current)
|
||||
if (current->second == swinfo)
|
||||
{
|
||||
m_current = current;
|
||||
else if (lhs.listname > rhs.listname)
|
||||
return false;
|
||||
else if (lhs.shortname < rhs.shortname)
|
||||
return true;
|
||||
}
|
||||
else if (lhs.shortname > rhs.shortname)
|
||||
return false;
|
||||
}
|
||||
else if (!rhs.startempty)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
m_current = m_list.begin();
|
||||
return false;
|
||||
return 0 > std::strncmp(lhs.driver->name, rhs.driver->name, ARRAY_LENGTH(lhs.driver->name));
|
||||
}
|
||||
|
||||
bool favorite_manager::favorite_compare::operator()(ui_software_info const &lhs, game_driver const &rhs) const
|
||||
{
|
||||
assert(lhs.driver);
|
||||
|
||||
if (!lhs.startempty)
|
||||
return false;
|
||||
else
|
||||
return 0 > std::strncmp(lhs.driver->name, rhs.name, ARRAY_LENGTH(rhs.name));
|
||||
}
|
||||
|
||||
bool favorite_manager::favorite_compare::operator()(game_driver const &lhs, ui_software_info const &rhs) const
|
||||
{
|
||||
assert(rhs.driver);
|
||||
|
||||
if (!rhs.startempty)
|
||||
return true;
|
||||
else
|
||||
return 0 > std::strncmp(lhs.name, rhs.driver->name, ARRAY_LENGTH(lhs.name));
|
||||
}
|
||||
|
||||
bool favorite_manager::favorite_compare::operator()(ui_software_info const &lhs, running_software_key const &rhs) const
|
||||
{
|
||||
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));
|
||||
}
|
||||
|
||||
bool favorite_manager::favorite_compare::operator()(running_software_key const &lhs, ui_software_info const &rhs) const
|
||||
{
|
||||
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<decltype(key)>(key));
|
||||
done = true;
|
||||
});
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename T> void favorite_manager::add_impl(T &&key)
|
||||
{
|
||||
auto const ins(m_favorites.emplace(std::forward<T>(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 <typename T> 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 <typename T> 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 <typename T>
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
@ -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 <functional>
|
||||
#include <set>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
#include <unordered_set>
|
||||
|
||||
|
||||
@ -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<game_driver const *> &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<std::string, ui_software_info, ci_less> 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 <typename T> void apply(T &&action)
|
||||
{
|
||||
for (auto const &item : m_favorites)
|
||||
action(item);
|
||||
}
|
||||
template <typename T> 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<game_driver const &, char const *, std::string const &>;
|
||||
|
||||
// current
|
||||
std::multimap<std::string, ui_software_info>::iterator m_current;
|
||||
struct favorite_compare
|
||||
{
|
||||
using is_transparent = std::true_type;
|
||||
|
||||
// parse file ui_favorite
|
||||
void parse_favorite();
|
||||
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;
|
||||
};
|
||||
|
||||
using favorites_set = std::set<ui_software_info, favorite_compare>;
|
||||
using sorted_favorites = std::vector<std::reference_wrapper<ui_software_info const> >;
|
||||
|
||||
// implementation
|
||||
template <typename T> static void apply_running_machine(running_machine &machine, T &&action);
|
||||
template <typename T> void add_impl(T &&key);
|
||||
template <typename T> bool check_impl(T const &key) const;
|
||||
template <typename T> 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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -31,6 +31,7 @@
|
||||
|
||||
|
||||
namespace ui {
|
||||
|
||||
/***************************************************************************
|
||||
CONSTANTS
|
||||
***************************************************************************/
|
||||
|
@ -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 <typename T> T *topmost_menu() const { return m_global_state->topmost_menu<T>(); }
|
||||
template <typename T> static T *topmost_menu(running_machine &machine) { return get_global_state(machine)->topmost_menu<T>(); }
|
||||
@ -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 <typename T>
|
||||
T *topmost_menu() const { return dynamic_cast<T *>(m_stack.get()); }
|
||||
|
||||
|
@ -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<void (bool, bool)> &&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<submenu>(ui(), container(), submenu::control_options, m_drv, &m_opts);
|
||||
break;
|
||||
case VIDEO:
|
||||
if (menu_event->iptkey == IPT_UI_SELECT)
|
||||
menu::stack_push<submenu>(ui(), container(), submenu::video_options, m_drv, &m_opts);
|
||||
break;
|
||||
case ADVANCED:
|
||||
if (menu_event->iptkey == IPT_UI_SELECT)
|
||||
menu::stack_push<submenu>(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<submenu>(ui(), container(), submenu::control_options, &m_drv, &m_opts);
|
||||
break;
|
||||
case VIDEO:
|
||||
if (menu_event->iptkey == IPT_UI_SELECT)
|
||||
menu::stack_push<submenu>(ui(), container(), submenu::video_options, &m_drv, &m_opts);
|
||||
break;
|
||||
case ADVANCED:
|
||||
if (menu_event->iptkey == IPT_UI_SELECT)
|
||||
menu::stack_push<submenu>(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());
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include <vector>
|
||||
|
||||
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<void (bool, bool)> &&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<void (bool, bool)> 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
|
||||
|
@ -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<void ()> &&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<std::string> 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<menu_selector>(
|
||||
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<menu_directory>(ui(), container());
|
||||
break;
|
||||
case MISC_MENU:
|
||||
if (menu_event->iptkey == IPT_UI_SELECT)
|
||||
{
|
||||
menu::stack_push<submenu>(ui(), container(), submenu::misc_options);
|
||||
ui_globals::reset = true;
|
||||
}
|
||||
break;
|
||||
case SOUND_MENU:
|
||||
if (menu_event->iptkey == IPT_UI_SELECT)
|
||||
{
|
||||
menu::stack_push<menu_sound_options>(ui(), container());
|
||||
ui_globals::reset = true;
|
||||
}
|
||||
break;
|
||||
case DISPLAY_MENU:
|
||||
if (menu_event->iptkey == IPT_UI_SELECT)
|
||||
{
|
||||
menu::stack_push<submenu>(ui(), container(), submenu::video_options);
|
||||
ui_globals::reset = true;
|
||||
}
|
||||
break;
|
||||
case CUSTOM_MENU:
|
||||
if (menu_event->iptkey == IPT_UI_SELECT)
|
||||
menu::stack_push<menu_custom_ui>(ui(), container());
|
||||
break;
|
||||
case CONTROLLER_MENU:
|
||||
if (menu_event->iptkey == IPT_UI_SELECT)
|
||||
menu::stack_push<submenu>(ui(), container(), submenu::control_options);
|
||||
break;
|
||||
case CGI_MENU:
|
||||
if (menu_event->iptkey == IPT_UI_SELECT)
|
||||
menu::stack_push<menu_input_groups>(ui(), container());
|
||||
break;
|
||||
case ADVANCED_MENU:
|
||||
if (menu_event->iptkey == IPT_UI_SELECT)
|
||||
{
|
||||
menu::stack_push<submenu>(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<uint16_t>(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<submenu>(ui(), container(), submenu::misc_options);
|
||||
ui_globals::reset = true;
|
||||
}
|
||||
break;
|
||||
case SOUND_MENU:
|
||||
if (menu_event.iptkey == IPT_UI_SELECT)
|
||||
{
|
||||
menu::stack_push<menu_sound_options>(ui(), container());
|
||||
ui_globals::reset = true;
|
||||
}
|
||||
break;
|
||||
case DISPLAY_MENU:
|
||||
if (menu_event.iptkey == IPT_UI_SELECT)
|
||||
{
|
||||
menu::stack_push<submenu>(ui(), container(), submenu::video_options);
|
||||
ui_globals::reset = true;
|
||||
}
|
||||
break;
|
||||
case CONTROLLER_MENU:
|
||||
if (menu_event.iptkey == IPT_UI_SELECT)
|
||||
menu::stack_push<submenu>(ui(), container(), submenu::control_options);
|
||||
break;
|
||||
case CGI_MENU:
|
||||
if (menu_event.iptkey == IPT_UI_SELECT)
|
||||
menu::stack_push<menu_input_groups>(ui(), container());
|
||||
break;
|
||||
case ADVANCED_MENU:
|
||||
if (menu_event.iptkey == IPT_UI_SELECT)
|
||||
{
|
||||
menu::stack_push<submenu>(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<void ()> &&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<uint16_t>(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<std::string> 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<menu_selector>(
|
||||
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<menu_directory>(ui(), container());
|
||||
break;
|
||||
case CUSTOM_MENU:
|
||||
if (menu_event.iptkey == IPT_UI_SELECT)
|
||||
menu::stack_push<menu_custom_ui>(ui(), container());
|
||||
break;
|
||||
default:
|
||||
menu_simple_game_options::handle_item_event(menu_event);
|
||||
return;
|
||||
}
|
||||
|
||||
if (changed)
|
||||
reset(reset_options::REMEMBER_REF);
|
||||
}
|
||||
|
||||
} // namespace ui
|
||||
|
@ -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<void ()> &&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;
|
||||
virtual void handle() override;
|
||||
std::function<void ()> const m_handler;
|
||||
};
|
||||
|
||||
machine_filter::type m_main;
|
||||
|
||||
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<void ()> &&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_data &m_filter_data;
|
||||
machine_filter::type m_main_filter;
|
||||
};
|
||||
|
||||
} // namespace ui
|
||||
|
||||
#endif /* MAME_FRONTEND_UI_OPTSMENU_H */
|
||||
#endif // MAME_FRONTEND_UI_OPTSMENU_H
|
||||
|
@ -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)
|
||||
|
@ -39,6 +39,8 @@
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
|
||||
#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<std::mutex> 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<std::thread> m_thread;
|
||||
std::atomic<bool> m_started;
|
||||
std::atomic<unsigned> m_available;
|
||||
std::vector<ui_system_info> m_sorted_list;
|
||||
int m_bios_count;
|
||||
// synchronisation
|
||||
std::mutex m_mutex;
|
||||
std::condition_variable m_condition;
|
||||
std::unique_ptr<std::thread> m_thread;
|
||||
std::atomic<bool> m_started;
|
||||
std::atomic<unsigned> m_available;
|
||||
|
||||
// data
|
||||
std::vector<ui_system_info> 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<menu_machine_configure>(
|
||||
ui(), container(),
|
||||
reinterpret_cast<const game_driver *>(m_prev_selected),
|
||||
*reinterpret_cast<const game_driver *>(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<ui_software_info *>(m_prev_selected);
|
||||
menu::stack_push<menu_machine_configure>(
|
||||
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<game_driver const *>(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<ui_software_info const *>(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<menu_audit>(ui(), container(), s_persistent_data.sorted_list(), menu_audit::mode::FAST);
|
||||
if (m_persistent_data.unavailable_systems())
|
||||
menu::stack_push<menu_audit>(ui(), container(), m_persistent_data.sorted_list(), menu_audit::mode::FAST);
|
||||
break;
|
||||
|
||||
case IPT_UI_AUDIT_ALL:
|
||||
menu::stack_push<menu_audit>(ui(), container(), s_persistent_data.sorted_list(), menu_audit::mode::ALL);
|
||||
menu::stack_push<menu_audit>(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<ui_system_info> 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<ui_system_info> 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<menu_game_options>(ui(), container());
|
||||
menu::stack_push<menu_game_options>(
|
||||
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<menu_machine_configure>(ui(), container(), reinterpret_cast<const game_driver *>(m_prev_selected));
|
||||
menu::stack_push<menu_machine_configure>(ui(), container(), *reinterpret_cast<const game_driver *>(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<menu_game_options>(ui(), container());
|
||||
menu::stack_push<menu_game_options>(
|
||||
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<ui_software_info *>(m_prev_selected);
|
||||
menu::stack_push<menu_machine_configure>(ui(), container(), (const game_driver *)swinfo->driver);
|
||||
menu::stack_push<menu_machine_configure>(
|
||||
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<ui_system_info> const &sorted(s_persistent_data.sorted_list());
|
||||
std::vector<ui_system_info> 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<double, std::reference_wrapper<ui_system_info const> > &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<double, std::reference_wrapper<ui_system_info const> > &info : m_searchlist)
|
||||
{
|
||||
if (info.first)
|
||||
@ -970,9 +990,9 @@ void menu_select_game::populate_search()
|
||||
}
|
||||
|
||||
// match "<manufacturer> <description>"
|
||||
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<double, std::reference_wrapper<ui_system_info const> > &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<game_driver const *> 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<std::string>::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<machine_filter>(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<machine_filter>(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);
|
||||
});
|
||||
}
|
||||
|
@ -39,14 +39,19 @@ private:
|
||||
CONF_PLUGINS,
|
||||
};
|
||||
|
||||
using icon_cache = util::lru_cache_map<game_driver const *, std::pair<texture_ptr, bitmap_argb32> >;
|
||||
|
||||
class persistent_data;
|
||||
|
||||
persistent_data &m_persistent_data;
|
||||
icon_cache m_icons;
|
||||
bool m_has_icons;
|
||||
std::vector<std::reference_wrapper<ui_system_info const> > m_displaylist;
|
||||
|
||||
static persistent_data s_persistent_data;
|
||||
static bool s_first_start;
|
||||
|
||||
std::vector<std::pair<double, std::reference_wrapper<ui_system_info const> > > 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);
|
||||
|
@ -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<char const *, char const *> 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;
|
||||
|
@ -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 <typename Filter>
|
||||
@ -188,9 +196,6 @@ private:
|
||||
using cache_ptr_map = std::map<running_machine *, cache_ptr>;
|
||||
|
||||
using flags_cache = util::lru_cache_map<game_driver const *, system_flags>;
|
||||
using icon_cache = util::lru_cache_map<game_driver const *, std::pair<texture_ptr, bitmap_argb32> >;
|
||||
|
||||
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;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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<menu_game_options>(ui(), container());
|
||||
{
|
||||
menu::stack_push<menu_simple_game_options>(
|
||||
ui(),
|
||||
container(),
|
||||
[this] () { reset(reset_options::SELECT_FIRST); });
|
||||
}
|
||||
|
||||
// anything else is a driver
|
||||
else
|
||||
{
|
||||
|
@ -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<bool> f_mnfct_finalised(false), f_year_finalised(false);
|
||||
std::vector<std::string> f_mnfct_ui, f_year_ui;
|
||||
std::unordered_set<std::string> 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 <machine_filter::type Type = machine_filter::AVAILABLE>
|
||||
class available_machine_filter_impl : public simple_filter_impl_base<machine_filter, Type>
|
||||
{
|
||||
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 <machine_filter::type Type = machine_filter::WORKING>
|
||||
class working_machine_filter_impl : public simple_filter_impl_base<machine_filter, Type>
|
||||
{
|
||||
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 <machine_filter::type Type = machine_filter::MECHANICAL>
|
||||
class mechanical_machine_filter_impl : public simple_filter_impl_base<machine_filter, Type>
|
||||
{
|
||||
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 <machine_filter::type Type = machine_filter::BIOS>
|
||||
class bios_machine_filter_impl : public simple_filter_impl_base<machine_filter, Type>
|
||||
{
|
||||
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 <machine_filter::type Type = machine_filter::PARENTS>
|
||||
class parents_machine_filter_impl : public simple_filter_impl_base<machine_filter, Type>
|
||||
{
|
||||
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 <machine_filter::type Type = machine_filter::CHD>
|
||||
class chd_machine_filter_impl : public simple_filter_impl_base<machine_filter, Type>
|
||||
{
|
||||
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 <machine_filter::type Type = machine_filter::SAVE>
|
||||
class save_machine_filter_impl : public simple_filter_impl_base<machine_filter, Type>
|
||||
{
|
||||
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 <machine_filter::type Type = machine_filter::VERTICAL>
|
||||
class vertical_machine_filter_impl : public simple_filter_impl_base<machine_filter, Type>
|
||||
{
|
||||
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<machine_filter, machine_filter::MANUFACTURER>
|
||||
{
|
||||
public:
|
||||
manufacturer_machine_filter(char const *value, emu_file *file, unsigned indent)
|
||||
: choice_filter_impl_base<machine_filter, machine_filter::MANUFACTURER>(c_mnfct::ui(), value)
|
||||
manufacturer_machine_filter(machine_filter_data const &data, char const *value, emu_file *file, unsigned indent)
|
||||
: choice_filter_impl_base<machine_filter, machine_filter::MANUFACTURER>(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<machine_filter, machine_filter::YEAR>
|
||||
{
|
||||
public:
|
||||
year_machine_filter(char const *value, emu_file *file, unsigned indent)
|
||||
: choice_filter_impl_base<machine_filter, machine_filter::YEAR>(c_year::ui(), value)
|
||||
year_machine_filter(machine_filter_data const &data, char const *value, emu_file *file, unsigned indent)
|
||||
: choice_filter_impl_base<machine_filter, machine_filter::YEAR>(data.years(), value)
|
||||
{
|
||||
}
|
||||
|
||||
@ -800,7 +780,10 @@ template <template <machine_filter::type T> class Base, machine_filter::type Typ
|
||||
class inverted_machine_filter : public Base<Type>
|
||||
{
|
||||
public:
|
||||
inverted_machine_filter(char const *value, emu_file *file, unsigned indent) : Base<Type>(value, file, indent) { }
|
||||
inverted_machine_filter(machine_filter_data const &data, char const *value, emu_file *file, unsigned indent)
|
||||
: Base<Type>(data, value, file, indent)
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool apply(ui_system_info const &system) const override { return !Base<Type>::apply(system); }
|
||||
};
|
||||
@ -833,7 +816,7 @@ template <machine_filter::type Type>
|
||||
class inclusive_machine_filter_impl : public simple_filter_impl_base<machine_filter, Type>
|
||||
{
|
||||
public:
|
||||
inclusive_machine_filter_impl(char const *value, emu_file *file, unsigned indent) { }
|
||||
inclusive_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 true; }
|
||||
};
|
||||
@ -850,7 +833,7 @@ using favorite_machine_filter = inclusive_machine_filter_impl<machine_filt
|
||||
class category_machine_filter : public simple_filter_impl_base<machine_filter, machine_filter::CATEGORY>
|
||||
{
|
||||
public:
|
||||
category_machine_filter(char const *value, emu_file *file, unsigned indent)
|
||||
category_machine_filter(machine_filter_data const &data, char const *value, emu_file *file, unsigned indent)
|
||||
: m_ini(0)
|
||||
, m_group(0)
|
||||
, m_include_clones(false)
|
||||
@ -1183,14 +1166,15 @@ void category_machine_filter::menu_configure::handle()
|
||||
class custom_machine_filter : public composite_filter_impl_base<custom_machine_filter, machine_filter, machine_filter::CUSTOM>
|
||||
{
|
||||
public:
|
||||
custom_machine_filter(char const *value, emu_file *file, unsigned indent)
|
||||
custom_machine_filter(machine_filter_data const &data, char const *value, emu_file *file, unsigned indent)
|
||||
: composite_filter_impl_base<custom_machine_filter, machine_filter, machine_filter::CUSTOM>()
|
||||
, m_data(data)
|
||||
{
|
||||
populate(value, file, indent);
|
||||
}
|
||||
|
||||
ptr create(type n) const { return machine_filter::create(n); }
|
||||
ptr create(emu_file &file, unsigned indent) const { return machine_filter::create(file, indent); }
|
||||
ptr create(type n) const { return machine_filter::create(n, m_data); }
|
||||
ptr create(emu_file &file, unsigned indent) const { return machine_filter::create(file, m_data, indent); }
|
||||
|
||||
static bool type_allowed(unsigned pos, type n)
|
||||
{
|
||||
@ -1234,6 +1218,9 @@ public:
|
||||
{
|
||||
return (CATEGORY == n) || (MANUFACTURER == n) || (YEAR == n);
|
||||
}
|
||||
|
||||
private:
|
||||
machine_filter_data const &m_data;
|
||||
};
|
||||
|
||||
|
||||
@ -1461,21 +1448,101 @@ private:
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// static data for machine filters
|
||||
//-------------------------------------------------
|
||||
|
||||
void machine_filter_data::add_manufacturer(std::string const &manufacturer)
|
||||
{
|
||||
std::string name(extract_manufacturer(manufacturer));
|
||||
std::vector<std::string>::iterator const pos(std::lower_bound(m_manufacturers.begin(), m_manufacturers.end(), name));
|
||||
if ((m_manufacturers.end() == pos) || (*pos != name))
|
||||
m_manufacturers.emplace(pos, std::move(name));
|
||||
}
|
||||
|
||||
void machine_filter_data::add_year(std::string const &year)
|
||||
{
|
||||
std::vector<std::string>::iterator const pos(std::lower_bound(m_years.begin(), m_years.end(), year));
|
||||
if ((m_years.end() == pos) || (*pos != year))
|
||||
m_years.emplace(pos, year);
|
||||
}
|
||||
|
||||
void machine_filter_data::finalise()
|
||||
{
|
||||
std::stable_sort(m_manufacturers.begin(), m_manufacturers.end());
|
||||
std::stable_sort(m_years.begin(), m_years.end());
|
||||
}
|
||||
|
||||
std::string machine_filter_data::extract_manufacturer(std::string const &manufacturer)
|
||||
{
|
||||
size_t const found(manufacturer.find('('));
|
||||
if ((found != std::string::npos) && (found > 0))
|
||||
return manufacturer.substr(0, found - 1);
|
||||
else
|
||||
return manufacturer;
|
||||
}
|
||||
|
||||
void machine_filter_data::set_filter(machine_filter::ptr &&filter)
|
||||
{
|
||||
m_filters[filter->get_type()] = std::move(filter);
|
||||
}
|
||||
|
||||
machine_filter &machine_filter_data::get_filter(machine_filter::type type)
|
||||
{
|
||||
auto it(m_filters.find(type));
|
||||
if (m_filters.end() == it)
|
||||
it = m_filters.emplace(type, machine_filter::create(type, *this)).first;
|
||||
|
||||
assert(it->second);
|
||||
return *it->second;
|
||||
}
|
||||
|
||||
std::string machine_filter_data::get_config_string() const
|
||||
{
|
||||
auto const active_filter(m_filters.find(m_current_filter));
|
||||
if (m_filters.end() != active_filter)
|
||||
{
|
||||
char const *const val(active_filter->second->filter_text());
|
||||
return val ? util::string_format("%s,%s", active_filter->second->config_name(), val) : active_filter->second->config_name();
|
||||
}
|
||||
else
|
||||
{
|
||||
return machine_filter::config_name(m_current_filter);
|
||||
}
|
||||
}
|
||||
|
||||
bool machine_filter_data::load_ini(emu_file &file)
|
||||
{
|
||||
machine_filter::ptr flt(machine_filter::create(file, *this));
|
||||
if (flt)
|
||||
{
|
||||
// TODO: it should possibly replace an existing item here, but it may be relying on that not happening because it never clears the first start flag
|
||||
m_current_filter = flt->get_type();
|
||||
m_filters.emplace(m_current_filter, std::move(flt));
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// static data for software filters
|
||||
//-------------------------------------------------
|
||||
|
||||
void software_filter_data::add_region(std::string const &str)
|
||||
void software_filter_data::add_region(std::string const &longname)
|
||||
{
|
||||
std::string name(extract_region(str));
|
||||
std::string name(extract_region(longname));
|
||||
std::vector<std::string>::iterator const pos(std::lower_bound(m_regions.begin(), m_regions.end(), name));
|
||||
if ((m_regions.end() == pos) || (*pos != str))
|
||||
if ((m_regions.end() == pos) || (*pos != name))
|
||||
m_regions.emplace(pos, std::move(name));
|
||||
}
|
||||
|
||||
void software_filter_data::add_publisher(std::string const &str)
|
||||
void software_filter_data::add_publisher(std::string const &publisher)
|
||||
{
|
||||
std::string name(extract_publisher(str));
|
||||
std::string name(extract_publisher(publisher));
|
||||
std::vector<std::string>::iterator const pos(std::lower_bound(m_publishers.begin(), m_publishers.end(), name));
|
||||
if ((m_publishers.end() == pos) || (*pos != name))
|
||||
m_publishers.emplace(pos, std::move(name));
|
||||
@ -1540,62 +1607,62 @@ std::string software_filter_data::extract_publisher(std::string const &publisher
|
||||
// public machine filter interface
|
||||
//-------------------------------------------------
|
||||
|
||||
machine_filter::ptr machine_filter::create(type n, char const *value, emu_file *file, unsigned indent)
|
||||
machine_filter::ptr machine_filter::create(type n, machine_filter_data const &data, char const *value, emu_file *file, unsigned indent)
|
||||
{
|
||||
assert(COUNT > n);
|
||||
switch (n)
|
||||
{
|
||||
case ALL:
|
||||
return std::make_unique<all_machine_filter>(value, file, indent);
|
||||
return std::make_unique<all_machine_filter>(data, value, file, indent);
|
||||
case AVAILABLE:
|
||||
return std::make_unique<available_machine_filter>(value, file, indent);
|
||||
return std::make_unique<available_machine_filter>(data, value, file, indent);
|
||||
case UNAVAILABLE:
|
||||
return std::make_unique<unavailable_machine_filter>(value, file, indent);
|
||||
return std::make_unique<unavailable_machine_filter>(data, value, file, indent);
|
||||
case WORKING:
|
||||
return std::make_unique<working_machine_filter>(value, file, indent);
|
||||
return std::make_unique<working_machine_filter>(data, value, file, indent);
|
||||
case NOT_WORKING:
|
||||
return std::make_unique<not_working_machine_filter>(value, file, indent);
|
||||
return std::make_unique<not_working_machine_filter>(data, value, file, indent);
|
||||
case MECHANICAL:
|
||||
return std::make_unique<mechanical_machine_filter>(value, file, indent);
|
||||
return std::make_unique<mechanical_machine_filter>(data, value, file, indent);
|
||||
case NOT_MECHANICAL:
|
||||
return std::make_unique<not_mechanical_machine_filter>(value, file, indent);
|
||||
return std::make_unique<not_mechanical_machine_filter>(data, value, file, indent);
|
||||
case CATEGORY:
|
||||
return std::make_unique<category_machine_filter>(value, file, indent);
|
||||
return std::make_unique<category_machine_filter>(data, value, file, indent);
|
||||
case FAVORITE:
|
||||
return std::make_unique<favorite_machine_filter>(value, file, indent);
|
||||
return std::make_unique<favorite_machine_filter>(data, value, file, indent);
|
||||
case BIOS:
|
||||
return std::make_unique<bios_machine_filter>(value, file, indent);
|
||||
return std::make_unique<bios_machine_filter>(data, value, file, indent);
|
||||
case NOT_BIOS:
|
||||
return std::make_unique<not_bios_machine_filter>(value, file, indent);
|
||||
return std::make_unique<not_bios_machine_filter>(data, value, file, indent);
|
||||
case PARENTS:
|
||||
return std::make_unique<parents_machine_filter>(value, file, indent);
|
||||
return std::make_unique<parents_machine_filter>(data, value, file, indent);
|
||||
case CLONES:
|
||||
return std::make_unique<clones_machine_filter>(value, file, indent);
|
||||
return std::make_unique<clones_machine_filter>(data, value, file, indent);
|
||||
case MANUFACTURER:
|
||||
return std::make_unique<manufacturer_machine_filter>(value, file, indent);
|
||||
return std::make_unique<manufacturer_machine_filter>(data, value, file, indent);
|
||||
case YEAR:
|
||||
return std::make_unique<year_machine_filter>(value, file, indent);
|
||||
return std::make_unique<year_machine_filter>(data, value, file, indent);
|
||||
case SAVE:
|
||||
return std::make_unique<save_machine_filter>(value, file, indent);
|
||||
return std::make_unique<save_machine_filter>(data, value, file, indent);
|
||||
case NOSAVE:
|
||||
return std::make_unique<nosave_machine_filter>(value, file, indent);
|
||||
return std::make_unique<nosave_machine_filter>(data, value, file, indent);
|
||||
case CHD:
|
||||
return std::make_unique<chd_machine_filter>(value, file, indent);
|
||||
return std::make_unique<chd_machine_filter>(data, value, file, indent);
|
||||
case NOCHD:
|
||||
return std::make_unique<nochd_machine_filter>(value, file, indent);
|
||||
return std::make_unique<nochd_machine_filter>(data, value, file, indent);
|
||||
case VERTICAL:
|
||||
return std::make_unique<vertical_machine_filter>(value, file, indent);
|
||||
return std::make_unique<vertical_machine_filter>(data, value, file, indent);
|
||||
case HORIZONTAL:
|
||||
return std::make_unique<horizontal_machine_filter>(value, file, indent);
|
||||
return std::make_unique<horizontal_machine_filter>(data, value, file, indent);
|
||||
case CUSTOM:
|
||||
return std::make_unique<custom_machine_filter>(value, file, indent);
|
||||
return std::make_unique<custom_machine_filter>(data, value, file, indent);
|
||||
case COUNT: // not valid, but needed to suppress warnings
|
||||
break;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
machine_filter::ptr machine_filter::create(emu_file &file, unsigned indent)
|
||||
machine_filter::ptr machine_filter::create(emu_file &file, machine_filter_data const &data, unsigned indent)
|
||||
{
|
||||
char buffer[MAX_CHAR_INFO];
|
||||
if (!file.gets(buffer, ARRAY_LENGTH(buffer)))
|
||||
@ -1620,7 +1687,7 @@ machine_filter::ptr machine_filter::create(emu_file &file, unsigned indent)
|
||||
for (type n = FIRST; COUNT > n; ++n)
|
||||
{
|
||||
if (key == config_name(n))
|
||||
return create(n, value.c_str(), &file, indent);
|
||||
return create(n, data, value.c_str(), &file, indent);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
@ -1731,115 +1798,22 @@ software_filter::ptr software_filter::create(emu_file &file, software_filter_dat
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// set manufacturers
|
||||
//-------------------------------------------------
|
||||
|
||||
void c_mnfct::add(std::string &&mfg)
|
||||
{
|
||||
assert(!f_mnfct_finalised.load(std::memory_order_acquire));
|
||||
|
||||
size_t const found(mfg.find('('));
|
||||
if ((found != std::string::npos) && (found > 0))
|
||||
mfg.resize(found - 1);
|
||||
|
||||
f_mnfct_tmp.emplace(std::move(mfg));
|
||||
}
|
||||
|
||||
void c_mnfct::finalise()
|
||||
{
|
||||
assert(!f_mnfct_finalised.load(std::memory_order_acquire));
|
||||
|
||||
f_mnfct_ui.reserve(f_mnfct_tmp.size());
|
||||
for (auto it = f_mnfct_tmp.begin(); f_mnfct_tmp.end() != it; it = f_mnfct_tmp.erase(it))
|
||||
f_mnfct_ui.emplace_back(*it);
|
||||
std::sort(
|
||||
f_mnfct_ui.begin(),
|
||||
f_mnfct_ui.end(),
|
||||
[] (std::string const &x, std::string const &y) { return 0 > core_stricmp(x.c_str(), y.c_str()); });
|
||||
|
||||
std::unique_lock<std::mutex> lock(f_filter_data_mutex);
|
||||
f_mnfct_finalised.store(true, std::memory_order_release);
|
||||
f_filter_data_condition.notify_all();
|
||||
}
|
||||
|
||||
std::vector<std::string> const &c_mnfct::ui()
|
||||
{
|
||||
if (!f_mnfct_finalised.load(std::memory_order_acquire))
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(f_filter_data_mutex);
|
||||
f_filter_data_condition.wait(lock, [] () { return f_mnfct_finalised.load(std::memory_order_acquire); });
|
||||
}
|
||||
|
||||
return f_mnfct_ui;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// set years
|
||||
//-------------------------------------------------
|
||||
|
||||
void c_year::add(std::string &&year)
|
||||
{
|
||||
assert(!f_year_finalised.load(std::memory_order_acquire));
|
||||
|
||||
f_year_tmp.emplace(std::move(year));
|
||||
}
|
||||
|
||||
void c_year::finalise()
|
||||
{
|
||||
assert(!f_year_finalised.load(std::memory_order_acquire));
|
||||
|
||||
f_year_ui.reserve(f_year_tmp.size());
|
||||
for (auto it = f_year_tmp.begin(); f_year_tmp.end() != it; it = f_year_tmp.erase(it))
|
||||
f_year_ui.emplace_back(*it);
|
||||
std::sort(
|
||||
f_year_ui.begin(),
|
||||
f_year_ui.end(),
|
||||
[] (std::string const &x, std::string const &y) { return 0 > core_stricmp(x.c_str(), y.c_str()); });
|
||||
|
||||
std::unique_lock<std::mutex> lock(f_filter_data_mutex);
|
||||
f_year_finalised.store(true, std::memory_order_release);
|
||||
f_filter_data_condition.notify_all();
|
||||
}
|
||||
|
||||
std::vector<std::string> const &c_year::ui()
|
||||
{
|
||||
if (!f_year_finalised.load(std::memory_order_acquire))
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(f_filter_data_mutex);
|
||||
f_filter_data_condition.wait(lock, [] () { return f_year_finalised.load(std::memory_order_acquire); });
|
||||
}
|
||||
|
||||
return f_year_ui;
|
||||
}
|
||||
|
||||
} // namesapce ui
|
||||
|
||||
|
||||
extern const char UI_VERSION_TAG[];
|
||||
const char UI_VERSION_TAG[] = "# UI INFO ";
|
||||
|
||||
// Main filters
|
||||
ui::machine_filter::type main_filters::actual = ui::machine_filter::ALL;
|
||||
std::map<ui::machine_filter::type, ui::machine_filter::ptr> main_filters::filters;
|
||||
|
||||
// Globals
|
||||
uint8_t ui_globals::rpanel = 0;
|
||||
uint8_t ui_globals::curimage_view = 0;
|
||||
uint8_t ui_globals::curdats_view = 0;
|
||||
uint8_t ui_globals::cur_sw_dats_total = 0;
|
||||
uint8_t ui_globals::curdats_total = 0;
|
||||
uint8_t ui_globals::cur_sw_dats_view = 0;
|
||||
bool ui_globals::switch_image = false;
|
||||
bool ui_globals::default_image = true;
|
||||
bool ui_globals::reset = false;
|
||||
bool ui_globals::redraw_icon = false;
|
||||
int ui_globals::visible_main_lines = 0;
|
||||
int ui_globals::visible_sw_lines = 0;
|
||||
uint16_t ui_globals::panels_status = 0;
|
||||
bool ui_globals::has_icons = false;
|
||||
|
||||
char* chartrimcarriage(char str[])
|
||||
{
|
||||
|
@ -31,7 +31,7 @@ class render_container;
|
||||
struct ui_system_info
|
||||
{
|
||||
ui_system_info() { }
|
||||
ui_system_info(game_driver const &d, int index, bool a) : driver(&d), available(a) { }
|
||||
ui_system_info(game_driver const &d, int i, bool a) : driver(&d), index(i), available(a) { }
|
||||
|
||||
game_driver const *driver = nullptr;
|
||||
int index;
|
||||
@ -95,35 +95,8 @@ struct ui_software_info
|
||||
|
||||
namespace ui {
|
||||
|
||||
class software_filter_data
|
||||
{
|
||||
public:
|
||||
std::vector<std::string> const ®ions() const { return m_regions; }
|
||||
std::vector<std::string> const &publishers() const { return m_publishers; }
|
||||
std::vector<std::string> const &years() const { return m_years; }
|
||||
std::vector<std::string> const &device_types() const { return m_device_types; }
|
||||
std::vector<std::string> const &list_names() const { return m_list_names; }
|
||||
std::vector<std::string> const &list_descriptions() const { return m_list_descriptions; }
|
||||
|
||||
// adding entries
|
||||
void add_region(std::string const &longname);
|
||||
void add_publisher(std::string const &publisher);
|
||||
void add_year(std::string const &year);
|
||||
void add_device_type(std::string const &device_type);
|
||||
void add_list(std::string const &name, std::string const &description);
|
||||
void finalise();
|
||||
|
||||
// use heuristics to extract meaningful parts from software list fields
|
||||
static std::string extract_region(std::string const &longname);
|
||||
static std::string extract_publisher(std::string const &publisher);
|
||||
|
||||
private:
|
||||
std::vector<std::string> m_regions;
|
||||
std::vector<std::string> m_publishers;
|
||||
std::vector<std::string> m_years;
|
||||
std::vector<std::string> m_device_types;
|
||||
std::vector<std::string> m_list_names, m_list_descriptions;
|
||||
};
|
||||
class machine_filter_data;
|
||||
class software_filter_data;
|
||||
|
||||
|
||||
template <class Impl, typename Entry>
|
||||
@ -201,8 +174,8 @@ public:
|
||||
virtual type get_type() const = 0;
|
||||
virtual std::string adorned_display_name(type n) const = 0;
|
||||
|
||||
static ptr create(type n) { return create(n, nullptr, nullptr, 0); }
|
||||
static ptr create(emu_file &file) { return create(file, 0); }
|
||||
static ptr create(type n, machine_filter_data const &data) { return create(n, data, nullptr, nullptr, 0); }
|
||||
static ptr create(emu_file &file, machine_filter_data const &data) { return create(file, data, 0); }
|
||||
static char const *config_name(type n);
|
||||
static char const *display_name(type n);
|
||||
|
||||
@ -212,8 +185,8 @@ public:
|
||||
protected:
|
||||
machine_filter();
|
||||
|
||||
static ptr create(type n, char const *value, emu_file *file, unsigned indent);
|
||||
static ptr create(emu_file &file, unsigned indent);
|
||||
static ptr create(type n, machine_filter_data const &data, char const *value, emu_file *file, unsigned indent);
|
||||
static ptr create(emu_file &file, machine_filter_data const &data, unsigned indent);
|
||||
};
|
||||
|
||||
DECLARE_ENUM_INCDEC_OPERATORS(machine_filter::type)
|
||||
@ -264,50 +237,82 @@ protected:
|
||||
|
||||
DECLARE_ENUM_INCDEC_OPERATORS(software_filter::type)
|
||||
|
||||
// Manufacturers
|
||||
struct c_mnfct
|
||||
{
|
||||
static void add(std::string &&mfg);
|
||||
static void finalise();
|
||||
|
||||
static std::vector<std::string> const &ui();
|
||||
class machine_filter_data
|
||||
{
|
||||
public:
|
||||
std::vector<std::string> const &manufacturers() const { return m_manufacturers; }
|
||||
std::vector<std::string> const &years() const { return m_years; }
|
||||
|
||||
// adding entries
|
||||
void add_manufacturer(std::string const &manufacturer);
|
||||
void add_year(std::string const &year);
|
||||
void finalise();
|
||||
|
||||
// use heuristics to extract meaningful parts from machine metadata
|
||||
static std::string extract_manufacturer(std::string const &manufacturer);
|
||||
|
||||
// the selected filter
|
||||
machine_filter::type get_current_filter_type() const { return m_current_filter; }
|
||||
void set_current_filter_type(machine_filter::type type) { m_current_filter = type; }
|
||||
|
||||
// managing current filters
|
||||
void set_filter(machine_filter::ptr &&filter);
|
||||
auto const &get_filters() { return m_filters; }
|
||||
machine_filter &get_filter(machine_filter::type type);
|
||||
machine_filter *get_current_filter()
|
||||
{
|
||||
auto const it(m_filters.find(m_current_filter));
|
||||
return (m_filters.end() != it) ? it->second.get() : nullptr;
|
||||
}
|
||||
std::string get_config_string() const;
|
||||
bool load_ini(emu_file &file);
|
||||
|
||||
private:
|
||||
using filter_map = std::map<machine_filter::type, machine_filter::ptr>;
|
||||
|
||||
std::vector<std::string> m_manufacturers;
|
||||
std::vector<std::string> m_years;
|
||||
|
||||
machine_filter::type m_current_filter = machine_filter::ALL;
|
||||
filter_map m_filters;
|
||||
};
|
||||
|
||||
// Years
|
||||
struct c_year
|
||||
{
|
||||
static void add(std::string &&year);
|
||||
static void finalise();
|
||||
|
||||
static std::vector<std::string> const &ui();
|
||||
class software_filter_data
|
||||
{
|
||||
public:
|
||||
std::vector<std::string> const ®ions() const { return m_regions; }
|
||||
std::vector<std::string> const &publishers() const { return m_publishers; }
|
||||
std::vector<std::string> const &years() const { return m_years; }
|
||||
std::vector<std::string> const &device_types() const { return m_device_types; }
|
||||
std::vector<std::string> const &list_names() const { return m_list_names; }
|
||||
std::vector<std::string> const &list_descriptions() const { return m_list_descriptions; }
|
||||
|
||||
// adding entries
|
||||
void add_region(std::string const &longname);
|
||||
void add_publisher(std::string const &publisher);
|
||||
void add_year(std::string const &year);
|
||||
void add_device_type(std::string const &device_type);
|
||||
void add_list(std::string const &name, std::string const &description);
|
||||
void finalise();
|
||||
|
||||
// use heuristics to extract meaningful parts from software list fields
|
||||
static std::string extract_region(std::string const &longname);
|
||||
static std::string extract_publisher(std::string const &publisher);
|
||||
|
||||
private:
|
||||
std::vector<std::string> m_regions;
|
||||
std::vector<std::string> m_publishers;
|
||||
std::vector<std::string> m_years;
|
||||
std::vector<std::string> m_device_types;
|
||||
std::vector<std::string> m_list_names, m_list_descriptions;
|
||||
};
|
||||
|
||||
} // namespace ui
|
||||
|
||||
#define MAX_CHAR_INFO 256
|
||||
|
||||
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
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
RP_FIRST = 0,
|
||||
@ -349,17 +354,10 @@ enum
|
||||
// GLOBAL CLASS
|
||||
struct ui_globals
|
||||
{
|
||||
static uint8_t curimage_view, curdats_view, curdats_total, cur_sw_dats_view, cur_sw_dats_total, rpanel;
|
||||
static bool switch_image, redraw_icon, default_image, reset;
|
||||
static uint8_t curdats_view, curdats_total, cur_sw_dats_view, cur_sw_dats_total, rpanel;
|
||||
static bool default_image, reset;
|
||||
static int visible_main_lines, visible_sw_lines;
|
||||
static uint16_t panels_status;
|
||||
static bool has_icons;
|
||||
};
|
||||
|
||||
struct main_filters
|
||||
{
|
||||
static ui::machine_filter::type actual;
|
||||
static std::map<ui::machine_filter::type, ui::machine_filter::ptr> filters;
|
||||
};
|
||||
|
||||
// GLOBAL FUNCTIONS
|
||||
|
Loading…
Reference in New Issue
Block a user