summaryrefslogtreecommitdiffstats
path: root/src/frontend/mame/ui/inputmap.cpp
diff options
context:
space:
mode:
author Vas Crabb <vas@vastheman.com>2019-11-17 04:01:22 +1100
committer Vas Crabb <vas@vastheman.com>2019-11-17 04:01:22 +1100
commit7880de4d3252e1b6cae07363d8d5f0f8d8a8c2cb (patch)
tree30cad6bf3d974674c5fdd1b09bf2b7826cc1756d /src/frontend/mame/ui/inputmap.cpp
parent0dc8480a2823542ee50b62be47e1d8fd611ff513 (diff)
UI cleanup:
* Make input mapping menus more efficient - most of the properties of a field won't change * Get rid of the pool allocator in base menu class - it was encouraging bad design
Diffstat (limited to 'src/frontend/mame/ui/inputmap.cpp')
-rw-r--r--src/frontend/mame/ui/inputmap.cpp261
1 files changed, 127 insertions, 134 deletions
diff --git a/src/frontend/mame/ui/inputmap.cpp b/src/frontend/mame/ui/inputmap.cpp
index 182a2201d83..6d7c1b138a1 100644
--- a/src/frontend/mame/ui/inputmap.cpp
+++ b/src/frontend/mame/ui/inputmap.cpp
@@ -66,63 +66,57 @@ void menu_input_groups::handle()
input menu
-------------------------------------------------*/
-menu_input_general::menu_input_general(mame_ui_manager &mui, render_container &container, int _group) : menu_input(mui, container)
+menu_input_general::menu_input_general(mame_ui_manager &mui, render_container &container, int _group)
+ : menu_input(mui, container)
+ , group(_group)
{
- group = _group;
}
void menu_input_general::populate(float &customtop, float &custombottom)
{
- input_item_data *itemlist = nullptr;
-
- /* iterate over the input ports and add menu items */
- for (input_type_entry &entry : machine().ioport().types())
+ if (data.empty())
+ {
+ assert(!pollingitem);
- /* add if we match the group and we have a valid name */
- if (entry.group() == group && entry.name() != nullptr && entry.name()[0] != 0)
+ // iterate over the input ports and add menu items
+ for (input_type_entry &entry : machine().ioport().types())
{
- input_seq_type seqtype;
-
- /* loop over all sequence types */
- for (seqtype = SEQ_TYPE_STANDARD; seqtype < SEQ_TYPE_TOTAL; ++seqtype)
+ // add if we match the group and we have a valid name
+ if ((entry.group() == group) && entry.name() && entry.name()[0])
{
- /* build an entry for the standard sequence */
- input_item_data *item = (input_item_data *)m_pool_alloc(sizeof(*item));
- memset(item, 0, sizeof(*item));
- item->ref = &entry;
- if(pollingitem && pollingref == &entry && pollingseq == seqtype)
- pollingitem = item;
- item->seqtype = seqtype;
- item->seq = machine().ioport().type_seq(entry.type(), entry.player(), seqtype);
- item->defseq = &entry.defseq(seqtype);
- item->group = entry.group();
- item->type = ioport_manager::type_is_analog(entry.type()) ? (INPUT_TYPE_ANALOG + seqtype) : INPUT_TYPE_DIGITAL;
- item->is_optional = false;
- item->name = entry.name();
- item->owner_name = nullptr;
- item->next = itemlist;
- itemlist = item;
-
- /* stop after one, unless we're analog */
- if (item->type == INPUT_TYPE_DIGITAL)
- break;
+ // loop over all sequence types
+ for (input_seq_type seqtype = SEQ_TYPE_STANDARD; seqtype < SEQ_TYPE_TOTAL; ++seqtype)
+ {
+ // build an entry for the standard sequence
+ input_item_data &item(*data.emplace(data.end()));
+ item.ref = &entry;
+ item.seqtype = seqtype;
+ item.seq = machine().ioport().type_seq(entry.type(), entry.player(), seqtype);
+ item.defseq = &entry.defseq(seqtype);
+ item.group = entry.group();
+ item.type = ioport_manager::type_is_analog(entry.type()) ? (INPUT_TYPE_ANALOG + seqtype) : INPUT_TYPE_DIGITAL;
+ item.is_optional = false;
+ item.name = entry.name();
+ item.owner_name = nullptr;
+
+ // stop after one, unless we're analog
+ if (item.type == INPUT_TYPE_DIGITAL)
+ break;
+ }
}
}
-
-
- // first count the number of items
- int numitems = 0;
- for (input_item_data const *item = itemlist; item != nullptr; item = item->next)
- numitems++;
-
- // now allocate an array of items and fill it up
- std::vector<input_item_data *> itemarray(numitems);
- int curitem = numitems;
- for (input_item_data *item = itemlist; item != nullptr; item = item->next)
- itemarray[--curitem] = item;
+ }
+ else
+ {
+ for (input_item_data &item : data)
+ {
+ const input_type_entry &entry(*reinterpret_cast<const input_type_entry *>(item.ref));
+ item.seq = machine().ioport().type_seq(entry.type(), entry.player(), item.seqtype);
+ }
+ }
// populate the menu in a standard fashion
- populate_sorted(std::move(itemarray));
+ populate_sorted();
}
menu_input_general::~menu_input_general()
@@ -140,90 +134,89 @@ menu_input_specific::menu_input_specific(mame_ui_manager &mui, render_container
void menu_input_specific::populate(float &customtop, float &custombottom)
{
- input_item_data *itemlist = nullptr;
-
- /* iterate over the input ports and add menu items */
- for (auto &port : machine().ioport().ports())
+ if (data.empty())
{
- for (ioport_field &field : port.second->fields())
- {
- ioport_type_class type_class = field.type_class();
+ assert(!pollingitem);
- /* add if we match the group and we have a valid name */
- if (field.enabled() && (type_class == INPUT_CLASS_CONTROLLER || type_class == INPUT_CLASS_MISC || type_class == INPUT_CLASS_KEYBOARD))
+ // iterate over the input ports and add menu items
+ for (auto &port : machine().ioport().ports())
+ {
+ for (ioport_field &field : port.second->fields())
{
- /* loop over all sequence types */
- for (input_seq_type seqtype = SEQ_TYPE_STANDARD; seqtype < SEQ_TYPE_TOTAL; ++seqtype)
+ const ioport_type_class type_class = field.type_class();
+
+ // add if it's enabled and it's a system-specific class
+ if (field.enabled() && (type_class == INPUT_CLASS_CONTROLLER || type_class == INPUT_CLASS_MISC || type_class == INPUT_CLASS_KEYBOARD))
{
- /* build an entry for the standard sequence */
- input_item_data *item = (input_item_data *)m_pool_alloc(sizeof(*item));
- memset(item, 0, sizeof(*item));
- item->ref = &field;
- item->seqtype = seqtype;
- if(pollingitem && pollingref == item->ref && pollingseq == seqtype)
- pollingitem = item;
- item->seq = field.seq(seqtype);
- item->defseq = &field.defseq(seqtype);
- item->group = machine().ioport().type_group(field.type(), field.player());
- item->type = field.is_analog() ? (INPUT_TYPE_ANALOG + seqtype) : INPUT_TYPE_DIGITAL;
- item->is_optional = field.optional();
- item->name = field.name();
- item->owner_name = field.device().tag();
- item->next = itemlist;
- itemlist = item;
-
- /* stop after one, unless we're analog */
- if (item->type == INPUT_TYPE_DIGITAL)
- break;
+ // loop over all sequence types
+ for (input_seq_type seqtype = SEQ_TYPE_STANDARD; seqtype < SEQ_TYPE_TOTAL; ++seqtype)
+ {
+ // build an entry for the standard sequence
+ input_item_data &item(*data.emplace(data.end()));
+ item.ref = &field;
+ item.seqtype = seqtype;
+ item.seq = field.seq(seqtype);
+ item.defseq = &field.defseq(seqtype);
+ item.group = machine().ioport().type_group(field.type(), field.player());
+ item.type = field.is_analog() ? (INPUT_TYPE_ANALOG + seqtype) : INPUT_TYPE_DIGITAL;
+ item.is_optional = field.optional();
+ item.name = field.name();
+ item.owner_name = field.device().tag();
+
+ // stop after one, unless we're analog
+ if (item.type == INPUT_TYPE_DIGITAL)
+ break;
+ }
}
}
}
- }
- // first count the number of items
- int numitems = 0;
- for (input_item_data const *item = itemlist; item != nullptr; item = item->next)
- numitems++;
-
- // now allocate an array of items and fill it up
- std::vector<input_item_data *> itemarray(numitems);
- int curitem = 0;
- for (input_item_data *item = itemlist; item != nullptr; item = item->next)
- itemarray[curitem++] = item;
-
- // sort it
- std::sort(itemarray.begin(), itemarray.end(), [](const input_item_data *i1, const input_item_data *i2) {
- int cmp = strcmp(i1->owner_name, i2->owner_name);
- if (cmp < 0)
- return true;
- if (cmp > 0)
- return false;
- if (i1->group < i2->group)
- return true;
- if (i1->group > i2->group)
- return false;
- const ioport_field &field1 = *reinterpret_cast<const ioport_field *>(i1->ref);
- const ioport_field &field2 = *reinterpret_cast<const ioport_field *>(i2->ref);
- if (field1.type() < field2.type())
- return true;
- if (field1.type() > field2.type())
- return false;
- std::vector<char32_t> codes1 = field1.keyboard_codes(0);
- std::vector<char32_t> codes2 = field2.keyboard_codes(0);
- if (!codes1.empty() && (codes2.empty() || codes1[0] < codes2[0]))
- return true;
- if (!codes2.empty() && (codes1.empty() || codes1[0] > codes2[0]))
- return false;
- cmp = strcmp(i1->name, i2->name);
- if (cmp < 0)
- return true;
- if (cmp > 0)
- return false;
- return i1->type < i2->type;
- });
+ // sort it
+ std::sort(
+ data.begin(),
+ data.end(),
+ [] (const input_item_data &i1, const input_item_data &i2)
+ {
+ int cmp = strcmp(i1.owner_name, i2.owner_name);
+ if (cmp < 0)
+ return true;
+ if (cmp > 0)
+ return false;
+ if (i1.group < i2.group)
+ return true;
+ if (i1.group > i2.group)
+ return false;
+ const ioport_field &field1 = *reinterpret_cast<const ioport_field *>(i1.ref);
+ const ioport_field &field2 = *reinterpret_cast<const ioport_field *>(i2.ref);
+ if (field1.type() < field2.type())
+ return true;
+ if (field1.type() > field2.type())
+ return false;
+ std::vector<char32_t> codes1 = field1.keyboard_codes(0);
+ std::vector<char32_t> codes2 = field2.keyboard_codes(0);
+ if (!codes1.empty() && (codes2.empty() || codes1[0] < codes2[0]))
+ return true;
+ if (!codes2.empty() && (codes1.empty() || codes1[0] > codes2[0]))
+ return false;
+ cmp = strcmp(i1.name, i2.name);
+ if (cmp < 0)
+ return true;
+ if (cmp > 0)
+ return false;
+ return i1.type < i2.type;
+ });
+ }
+ else
+ {
+ for (input_item_data &item : data)
+ {
+ const ioport_field &field(*reinterpret_cast<const ioport_field *>(item.ref));
+ item.seq = field.seq(item.seqtype);
+ }
+ }
// populate the menu in a standard fashion
- populate_sorted(std::move(itemarray));
+ populate_sorted();
}
menu_input_specific::~menu_input_specific()
@@ -367,43 +360,43 @@ void menu_input_specific::update_input(struct input_item_data *seqchangeditem)
// menu from them
//-------------------------------------------------
-void menu_input::populate_sorted(std::vector<input_item_data *> &&itemarray)
+void menu_input::populate_sorted()
{
const char *nameformat[INPUT_TYPE_TOTAL] = { nullptr };
std::string subtext;
std::string prev_owner;
bool first_entry = true;
- /* create a mini lookup table for name format based on type */
+ // create a mini lookup table for name format based on type
nameformat[INPUT_TYPE_DIGITAL] = "%s";
nameformat[INPUT_TYPE_ANALOG] = "%s Analog";
nameformat[INPUT_TYPE_ANALOG_INC] = "%s Analog Inc";
nameformat[INPUT_TYPE_ANALOG_DEC] = "%s Analog Dec";
- /* build the menu */
- for (input_item_data *item : itemarray)
+ // build the menu
+ for (input_item_data &item : data)
{
uint32_t flags = 0;
- /* generate the name of the item itself, based off the base name and the type */
- assert(nameformat[item->type] != nullptr);
+ // generate the name of the item itself, based off the base name and the type
+ assert(nameformat[item.type] != nullptr);
- if (item->owner_name && strcmp(item->owner_name, prev_owner.c_str()) != 0)
+ if (item.owner_name && strcmp(item.owner_name, prev_owner.c_str()) != 0)
{
if (first_entry)
first_entry = false;
else
item_append(menu_item_type::SEPARATOR);
- item_append(string_format("[root%s]", item->owner_name), "", 0, nullptr);
- prev_owner.assign(item->owner_name);
+ item_append(string_format("[root%s]", item.owner_name), "", 0, nullptr);
+ prev_owner.assign(item.owner_name);
}
- std::string text = string_format(nameformat[item->type], item->name);
- if (item->is_optional)
+ std::string text = string_format(nameformat[item.type], item.name);
+ if (item.is_optional)
text = "(" + text + ")";
/* if we're polling this item, use some spaces with left/right arrows */
- if (pollingref == item->ref && pollingseq == item->seqtype)
+ if (pollingref == item.ref && pollingseq == item.seqtype)
{
subtext.assign(" ");
flags |= FLAG_LEFT_ARROW | FLAG_RIGHT_ARROW;
@@ -412,12 +405,12 @@ void menu_input::populate_sorted(std::vector<input_item_data *> &&itemarray)
/* otherwise, generate the sequence name and invert it if different from the default */
else
{
- subtext = machine().input().seq_name(item->seq);
- flags |= (item->seq != *item->defseq) ? FLAG_INVERT : 0;
+ subtext = machine().input().seq_name(item.seq);
+ flags |= (item.seq != *item.defseq) ? FLAG_INVERT : 0;
}
/* add the item */
- item_append(text, subtext, flags, item);
+ item_append(text, subtext, flags, &item);
}
}