summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author AJR <ajrhacker@users.noreply.github.com>2019-05-24 09:11:58 -0400
committer AJR <ajrhacker@users.noreply.github.com>2019-05-24 09:20:32 -0400
commit3e4fb49d5e3d2362d32552b20e50ff865a757114 (patch)
tree4cb2c7e86593f30800832119090ee2167e85a98c
parent6c42709c107fe5f0bc74efd426ec7ae2e55560dc (diff)
Improve sorting of items for machine input menu. Inputs of the same type are sorted by name, and keyboard keys are sorted by their assigned character codes (if any).
-rw-r--r--src/frontend/mame/ui/inputmap.cpp123
-rw-r--r--src/frontend/mame/ui/inputmap.h6
2 files changed, 76 insertions, 53 deletions
diff --git a/src/frontend/mame/ui/inputmap.cpp b/src/frontend/mame/ui/inputmap.cpp
index 2259abc0a03..4009223408b 100644
--- a/src/frontend/mame/ui/inputmap.cpp
+++ b/src/frontend/mame/ui/inputmap.cpp
@@ -94,7 +94,6 @@ void menu_input_general::populate(float &customtop, float &custombottom)
{
input_item_data *itemlist = nullptr;
int suborder[SEQ_TYPE_TOTAL];
- int sortorder = 1;
/* create a mini lookup table for sort order based on sequence type */
suborder[SEQ_TYPE_STANDARD] = 0;
@@ -110,7 +109,6 @@ void menu_input_general::populate(float &customtop, float &custombottom)
input_seq_type seqtype;
/* loop over all sequence types */
- sortorder++;
for (seqtype = SEQ_TYPE_STANDARD; seqtype < SEQ_TYPE_TOTAL; ++seqtype)
{
/* build an entry for the standard sequence */
@@ -122,7 +120,7 @@ void menu_input_general::populate(float &customtop, float &custombottom)
item->seqtype = seqtype;
item->seq = machine().ioport().type_seq(entry.type(), entry.player(), seqtype);
item->defseq = &entry.defseq(seqtype);
- item->sortorder = sortorder * 4 + suborder[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();
@@ -136,8 +134,20 @@ void menu_input_general::populate(float &customtop, float &custombottom)
}
}
- /* sort and populate the menu in a standard fashion */
- populate_and_sort(itemlist);
+
+ // 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;
+
+ // populate the menu in a standard fashion
+ populate_sorted(std::move(itemarray));
}
menu_input_general::~menu_input_general()
@@ -175,21 +185,8 @@ void menu_input_specific::populate(float &customtop, float &custombottom)
/* 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))
{
- input_seq_type seqtype;
- uint32_t sortorder;
-
- /* determine the sorting order */
- if (type_class == INPUT_CLASS_CONTROLLER)
- {
- sortorder = (field.type() << 2) | (field.player() << 12);
- if (field.device().owner() != nullptr)
- sortorder |= (port_count & 0xfff) * 0x10000;
- }
- else
- sortorder = field.type() | 0xf000;
-
/* loop over all sequence types */
- for (seqtype = SEQ_TYPE_STANDARD; seqtype < SEQ_TYPE_TOTAL; ++seqtype)
+ for (input_seq_type seqtype = SEQ_TYPE_STANDARD; seqtype < SEQ_TYPE_TOTAL; ++seqtype)
{
/* build an entry for the standard sequence */
input_item_data *item = (input_item_data *)m_pool_alloc(sizeof(*item));
@@ -200,7 +197,7 @@ void menu_input_specific::populate(float &customtop, float &custombottom)
pollingitem = item;
item->seq = field.seq(seqtype);
item->defseq = &field.defseq(seqtype);
- item->sortorder = sortorder + suborder[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();
@@ -216,8 +213,50 @@ void menu_input_specific::populate(float &customtop, float &custombottom)
}
}
- /* sort and populate the menu in a standard fashion */
- populate_and_sort(itemlist);
+ // 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;
+ });
+
+ // populate the menu in a standard fashion
+ populate_sorted(std::move(itemarray));
}
menu_input_specific::~menu_input_specific()
@@ -227,8 +266,9 @@ menu_input_specific::~menu_input_specific()
/*-------------------------------------------------
menu_input - display a menu for inputs
-------------------------------------------------*/
-menu_input::menu_input(mame_ui_manager &mui, render_container &container) : menu(mui, container), last_sortorder(0), record_next(false)
+menu_input::menu_input(mame_ui_manager &mui, render_container &container) : menu(mui, container), record_next(false)
{
+ lastitem = nullptr;
pollingitem = nullptr;
pollingref = nullptr;
pollingseq = SEQ_TYPE_STANDARD;
@@ -296,7 +336,7 @@ void menu_input::handle()
/* an item was selected: begin polling */
case IPT_UI_SELECT:
pollingitem = item;
- last_sortorder = item->sortorder;
+ lastitem = item;
starting_seq = item->seq;
machine().input().seq_poll_start((item->type == INPUT_TYPE_ANALOG) ? ITEM_CLASS_ABSOLUTE : ITEM_CLASS_SWITCH, record_next ? &item->seq : nullptr);
invalidate = true;
@@ -311,9 +351,9 @@ void menu_input::handle()
}
/* if the selection changed, reset the "record next" flag */
- if (item->sortorder != last_sortorder)
+ if (item != lastitem)
record_next = false;
- last_sortorder = item->sortorder;
+ lastitem = item;
}
/* if the sequence changed, update it */
@@ -354,17 +394,15 @@ void menu_input_specific::update_input(struct input_item_data *seqchangeditem)
}
-/*-------------------------------------------------
- menu_input_populate_and_sort - take a list
- of input_item_data objects and build up the
- menu from them
--------------------------------------------------*/
+//-------------------------------------------------
+// populate_sorted - take a sorted list of
+// input_item_data objects and build up the
+// menu from them
+//-------------------------------------------------
-void menu_input::populate_and_sort(input_item_data *itemlist)
+void menu_input::populate_sorted(std::vector<input_item_data *> &&itemarray)
{
const char *nameformat[INPUT_TYPE_TOTAL] = { nullptr };
- input_item_data *item;
- int numitems = 0, curitem;
std::string subtext;
std::string prev_owner;
bool first_entry = true;
@@ -375,27 +413,12 @@ void menu_input::populate_and_sort(input_item_data *itemlist)
nameformat[INPUT_TYPE_ANALOG_INC] = "%s Analog Inc";
nameformat[INPUT_TYPE_ANALOG_DEC] = "%s Analog Dec";
- /* first count the number of items */
- for (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);
- for (item = itemlist, curitem = 0; 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) {
- return i1->sortorder < i2->sortorder;
- });
-
/* build the menu */
- for (curitem = 0; curitem < numitems; curitem++)
+ for (input_item_data *item : itemarray)
{
uint32_t flags = 0;
/* generate the name of the item itself, based off the base name and the type */
- item = itemarray[curitem];
assert(nameformat[item->type] != nullptr);
if (item->owner_name && strcmp(item->owner_name, prev_owner.c_str()) != 0)
diff --git a/src/frontend/mame/ui/inputmap.h b/src/frontend/mame/ui/inputmap.h
index d63ecbd3d84..eaa0eaa76f1 100644
--- a/src/frontend/mame/ui/inputmap.h
+++ b/src/frontend/mame/ui/inputmap.h
@@ -53,12 +53,12 @@ protected:
const input_seq * defseq; /* pointer to the default sequence */
const char * name; /* pointer to the base name of the item */
const char * owner_name; /* pointer to the name of the owner of the item */
- uint32_t sortorder; /* sorting information */
+ ioport_group group; /* group type */
uint8_t type; /* type of port */
bool is_optional; /* true if this input is considered optional */
};
- void populate_and_sort(struct input_item_data *itemlist);
+ void populate_sorted(std::vector<input_item_data *> &&itemarray);
void toggle_none_default(input_seq &selected_seq, input_seq &original_seq, const input_seq &selected_defseq);
const void * pollingref;
@@ -66,7 +66,7 @@ protected:
input_item_data * pollingitem;
private:
- uint32_t last_sortorder;
+ input_item_data * lastitem;
bool record_next;
input_seq starting_seq;