summaryrefslogtreecommitdiffstatshomepage
path: root/src/frontend/mame/ui/confswitch.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/frontend/mame/ui/confswitch.cpp')
-rw-r--r--src/frontend/mame/ui/confswitch.cpp299
1 files changed, 213 insertions, 86 deletions
diff --git a/src/frontend/mame/ui/confswitch.cpp b/src/frontend/mame/ui/confswitch.cpp
index 4f0ec775260..f2f8a241d98 100644
--- a/src/frontend/mame/ui/confswitch.cpp
+++ b/src/frontend/mame/ui/confswitch.cpp
@@ -11,6 +11,8 @@
#include "emu.h"
#include "ui/confswitch.h"
+#include "uiinput.h"
+
#include <algorithm>
#include <cstring>
@@ -51,6 +53,7 @@ menu_confswitch::switch_group_descriptor::switch_group_descriptor(ioport_field c
, mask(0U)
, state(0U)
{
+ std::fill(std::begin(toggles), std::end(toggles), toggle{ nullptr, 0U });
}
@@ -62,7 +65,7 @@ inline bool menu_confswitch::switch_group_descriptor::matches(ioport_field const
inline unsigned menu_confswitch::switch_group_descriptor::switch_count() const noexcept
{
- return (sizeof(mask) * 8) - count_leading_zeros(mask);
+ return (sizeof(mask) * 8) - count_leading_zeros_32(mask);
}
@@ -81,7 +84,14 @@ menu_confswitch::~menu_confswitch()
}
-void menu_confswitch::populate(float &customtop, float &custombottom)
+void menu_confswitch::menu_activated()
+{
+ // switches can have input assignments, and scripts are a thing
+ reset(reset_options::REMEMBER_REF);
+}
+
+
+void menu_confswitch::populate()
{
// locate relevant fields if necessary
if (m_fields.empty())
@@ -94,7 +104,6 @@ void menu_confswitch::populate(float &customtop, float &custombottom)
// loop over input ports and set up the current values
device_t *prev_owner(nullptr);
- bool first_entry(true);
for (field_descriptor &desc : m_fields)
{
ioport_field &field(desc.field);
@@ -106,11 +115,10 @@ void menu_confswitch::populate(float &customtop, float &custombottom)
if (&field.device() != prev_owner)
{
prev_owner = &field.device();
- if (first_entry)
- first_entry = false;
+ if (prev_owner->owner())
+ item_append(string_format(_("%1$s [root%2$s]"), prev_owner->type().fullname(), prev_owner->tag()), FLAG_UI_HEADING | FLAG_DISABLE, nullptr);
else
- item_append(menu_item_type::SEPARATOR);
- item_append(string_format("[root%s]", prev_owner->tag()), 0, nullptr);
+ item_append(string_format(_("[root%1$s]"), prev_owner->tag()), FLAG_UI_HEADING | FLAG_DISABLE, nullptr);
}
// set the left/right flags appropriately
@@ -146,8 +154,10 @@ void menu_confswitch::populate(float &customtop, float &custombottom)
++m_active_switch_groups;
// apply the bits
- group.mask |= uint32_t(1) << (loc.number() - 1);
ioport_value const mask(accummask & ~(accummask - 1));
+ group.toggles[loc.number() - 1].field = &field;
+ group.toggles[loc.number() - 1].mask = mask;
+ group.mask |= uint32_t(1) << (loc.number() - 1);
if (((settings.value & mask) && !loc.inverted()) || (!(settings.value & mask) && loc.inverted()))
group.state |= uint32_t(1) << (loc.number() - 1);
@@ -159,61 +169,117 @@ void menu_confswitch::populate(float &customtop, float &custombottom)
}
item_append(menu_item_type::SEPARATOR);
- item_append(_("Reset"), 0, (void *)1);
+ item_append(_("Reset System"), 0, (void *)1);
}
-void menu_confswitch::handle()
+bool menu_confswitch::handle(event const *ev)
{
- // process the menu
- event const *const menu_event(process(0));
+ if (!ev || !ev->itemref)
+ return false;
- // handle events
- if (menu_event && menu_event->itemref)
+ if (IPT_CUSTOM == ev->iptkey)
{
- if (uintptr_t(menu_event->itemref) == 1U)
- {
- // reset
- if (menu_event->iptkey == IPT_UI_SELECT)
- machine().schedule_hard_reset();
- }
- else
- {
- // actual settings
- ioport_field &field(*reinterpret_cast<ioport_field *>(menu_event->itemref));
- bool changed(false);
+ // clicked a switch
+ reset(reset_options::REMEMBER_REF);
+ return true;
+ }
+
+ if (uintptr_t(ev->itemref) == 1U)
+ {
+ // reset
+ if (ev->iptkey == IPT_UI_SELECT)
+ machine().schedule_hard_reset();
+ }
+ else
+ {
+ // actual settings
+ ioport_field &field(*reinterpret_cast<ioport_field *>(ev->itemref));
+ bool changed(false);
- switch (menu_event->iptkey)
+ switch (ev->iptkey)
+ {
+ // left goes to previous setting
+ case IPT_UI_LEFT:
+ field.select_previous_setting();
+ changed = true;
+ break;
+
+ // right goes to next setting
+ case IPT_UI_SELECT:
+ case IPT_UI_RIGHT:
+ field.select_next_setting();
+ changed = true;
+ break;
+
+ // if cleared, reset to default value
+ case IPT_UI_CLEAR:
{
- // if selected, reset to default value
- case IPT_UI_SELECT:
+ ioport_field::user_settings settings;
+ field.get_user_settings(settings);
+ if (field.defvalue() != settings.value)
{
- ioport_field::user_settings settings;
- field.get_user_settings(settings);
settings.value = field.defvalue();
field.set_user_settings(settings);
+ changed = true;
}
- changed = true;
- break;
-
- // left goes to previous setting
- case IPT_UI_LEFT:
- field.select_previous_setting();
- changed = true;
- break;
+ }
+ break;
- // right goes to next setting
- case IPT_UI_RIGHT:
- field.select_next_setting();
- changed = true;
- break;
+ // trick to get previous group - depend on headings having null reference
+ case IPT_UI_PREV_GROUP:
+ {
+ auto current = selected_index();
+ bool found_break = false;
+ while (0 < current)
+ {
+ if (!found_break)
+ {
+ if (!item(--current).ref())
+ found_break = true;
+ }
+ else if (!item(current - 1).ref())
+ {
+ set_selected_index(current);
+ set_top_line(current - 1);
+ return true;
+ }
+ else
+ {
+ --current;
+ }
+ }
}
+ break;
- // if anything changed, rebuild the menu, trying to stay on the same field
- if (changed)
- reset(reset_options::REMEMBER_REF);
+ // trick to get next group - depend on special item references
+ case IPT_UI_NEXT_GROUP:
+ {
+ auto current = selected_index();
+ while (item_count() > ++current)
+ {
+ if (!item(current).ref())
+ {
+ if ((item_count() > (current + 1)) && (uintptr_t(item(current + 1).ref()) != 1))
+ {
+ set_selected_index(current + 1);
+ set_top_line(current);
+ return true;
+ }
+ break;
+ }
+ }
+ }
+ break;
}
+
+ // if anything changed, rebuild the menu, trying to stay on the same field
+ if (changed)
+ reset(reset_options::REMEMBER_REF);
}
+
+ // changing settings triggers an item rebuild because it can affect whether things are enabled
+ return false;
}
@@ -254,8 +320,14 @@ void menu_confswitch::find_fields()
menu_settings_dip_switches::menu_settings_dip_switches(mame_ui_manager &mui, render_container &container)
: menu_confswitch(mui, container, IPT_DIPSWITCH)
+ , m_switch_group_y()
, m_visible_switch_groups(0U)
+ , m_single_width(0.0f)
+ , m_nub_width(0.0f)
+ , m_first_nub(0.0f)
+ , m_clickable_height(0.0f)
{
+ set_heading(_("DIP Switches"));
}
@@ -264,17 +336,27 @@ menu_settings_dip_switches::~menu_settings_dip_switches()
}
-void menu_settings_dip_switches::custom_render(void *selectedref, float top, float bottom, float x1, float y1, float x2, float y2)
+void menu_settings_dip_switches::recompute_metrics(uint32_t width, uint32_t height, float aspect)
{
- // catch if no diploc has to be drawn
+ menu_confswitch::recompute_metrics(width, height, aspect);
+
+ set_custom_space(
+ 0.0f,
+ m_visible_switch_groups
+ ? ((m_visible_switch_groups * (DIP_SWITCH_HEIGHT * line_height())) + ((m_visible_switch_groups - 1) * (DIP_SWITCH_SPACING * line_height())) + (tb_border() * 3.0f))
+ : 0.0f);
+}
+
+
+void menu_settings_dip_switches::custom_render(uint32_t flags, void *selectedref, float top, float bottom, float x1, float y1, float x2, float y2)
+{
+ // catch if no DIP locations have to be drawn
if (!m_visible_switch_groups)
return;
// calculate optimal width
- float const aspect(machine().render().ui_aspect(&container()));
- float const lineheight(ui().get_line_height());
- float const singlewidth(lineheight * SINGLE_TOGGLE_SWITCH_FIELD_WIDTH * aspect);
- float const maxwidth(1.0f - (ui().box_lr_border() * 2.0f * aspect));
+ float const maxwidth(1.0f - (lr_border() * 2.0f));
+ m_single_width = (line_height() * SINGLE_TOGGLE_SWITCH_FIELD_WIDTH * x_aspect());
float width(0.0f);
unsigned maxswitches(0U);
for (switch_group_descriptor const &group : switch_groups())
@@ -282,31 +364,34 @@ void menu_settings_dip_switches::custom_render(void *selectedref, float top, flo
if (group.mask)
{
maxswitches = (std::max)(group.switch_count(), maxswitches);
- float const namewidth(ui().get_string_width(group.name));
- float const switchwidth(singlewidth * maxswitches);
- width = (std::min)((std::max)(namewidth + switchwidth + (lineheight * aspect), width), maxwidth);
+ float const namewidth(get_string_width(group.name));
+ float const switchwidth(m_single_width * maxswitches);
+ width = (std::min)((std::max)(namewidth + switchwidth + (line_height() * x_aspect()), width), maxwidth);
}
}
// draw extra menu area
- float const boxwidth((std::max)(width + (ui().box_lr_border() * 2.0f * aspect), x2 - x1));
- float const boxleft((1.0f - boxwidth) / 2.0f);
- ui().draw_outlined_box(container(), boxleft, y2 + ui().box_tb_border(), boxleft + boxwidth, y2 + bottom, ui().colors().background_color());
+ float const boxwidth((std::max)(width + (lr_border() * 2.0f), x2 - x1));
+ float const boxleft((1.0f - boxwidth) * 0.5f);
+ ui().draw_outlined_box(container(), boxleft, y2 + tb_border(), boxleft + boxwidth, y2 + bottom, ui().colors().background_color());
// calculate centred layout
- float const nameleft((1.0f - width) / 2.0f);
- float const switchleft(nameleft + width - (singlewidth * maxswitches));
- float const namewidth(width - (singlewidth * maxswitches) - (lineheight * aspect));
+ float const nameleft((1.0f - width) * 0.5f);
+ float const switchleft(nameleft + width - (m_single_width * maxswitches));
+ float const namewidth(width - (m_single_width * maxswitches) - (line_height() * x_aspect()));
// iterate over switch groups
ioport_field *const field((uintptr_t(selectedref) != 1U) ? reinterpret_cast<ioport_field *>(selectedref) : nullptr);
- float const nubheight(lineheight * SINGLE_TOGGLE_SWITCH_HEIGHT);
- float const nubwidth(lineheight * SINGLE_TOGGLE_SWITCH_WIDTH * aspect);
- float const ygap(lineheight * ((DIP_SWITCH_HEIGHT / 2) - SINGLE_TOGGLE_SWITCH_HEIGHT) / 2);
- float const xgap((singlewidth + (UI_LINE_WIDTH / 2) - nubwidth) / 2);
+ float const nubheight(line_height() * SINGLE_TOGGLE_SWITCH_HEIGHT);
+ m_nub_width = line_height() * SINGLE_TOGGLE_SWITCH_WIDTH * x_aspect();
+ float const ygap(line_height() * ((DIP_SWITCH_HEIGHT * 0.5f) - SINGLE_TOGGLE_SWITCH_HEIGHT) * 0.5f);
+ float const xgap((m_single_width + (UI_LINE_WIDTH * 0.5f) - m_nub_width) * 0.5f);
+ m_first_nub = switchleft + xgap;
+ m_clickable_height = (line_height() * DIP_SWITCH_HEIGHT) - (ygap * 2.0f);
unsigned line(0U);
- for (switch_group_descriptor const &group : switch_groups())
+ for (unsigned n = 0; switch_groups().size() > n; ++n)
{
+ switch_group_descriptor const &group(switch_groups()[n]);
if (group.mask)
{
// determine the mask of selected bits
@@ -319,47 +404,47 @@ void menu_settings_dip_switches::custom_render(void *selectedref, float top, flo
}
// draw the name
- float const liney(y2 + (ui().box_tb_border() * 2.0f) + (lineheight * (DIP_SWITCH_HEIGHT + DIP_SWITCH_SPACING) * line));
- ui().draw_text_full(
- container(),
+ float const liney(y2 + (tb_border() * 2.0f) + (line_height() * (DIP_SWITCH_HEIGHT + DIP_SWITCH_SPACING) * line));
+ draw_text_normal(
group.name,
- nameleft, liney + (lineheight * (DIP_SWITCH_HEIGHT - 1.0f) / 2.0f), namewidth,
- ui::text_layout::RIGHT, ui::text_layout::NEVER,
- mame_ui_manager::NORMAL, ui().colors().text_color(), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+ nameleft, liney + (line_height() * (DIP_SWITCH_HEIGHT - 1.0f) / 2.0f), namewidth,
+ text_layout::text_justify::RIGHT, text_layout::word_wrapping::NEVER,
+ ui().colors().text_color());
// draw the group outline
- float const switchbottom(liney + (DIP_SWITCH_HEIGHT * lineheight));
+ float const switchbottom(liney + (DIP_SWITCH_HEIGHT * line_height()));
unsigned const cnt(group.switch_count());
ui().draw_outlined_box(
container(),
- switchleft, liney, switchleft + (singlewidth * cnt), switchbottom,
+ switchleft, liney, switchleft + (m_single_width * cnt), switchbottom,
ui().colors().background_color());
for (unsigned i = 1; cnt > i; ++i)
{
container().add_line(
- switchleft + (singlewidth * i), liney, switchleft + (singlewidth * i), switchbottom,
+ switchleft + (m_single_width * i), liney, switchleft + (m_single_width * i), switchbottom,
UI_LINE_WIDTH, ui().colors().text_color(), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
}
// compute top and bottom for on and off positions
float const yoff(liney + UI_LINE_WIDTH + ygap);
float const yon(switchbottom - UI_LINE_WIDTH - ygap - nubheight);
+ m_switch_group_y[n] = yoff;
// draw the switch nubs
for (unsigned toggle = 0; cnt > toggle; ++toggle)
{
- float const nubleft(switchleft + (singlewidth * toggle) + xgap);
+ float const nubleft(switchleft + (m_single_width * toggle) + xgap);
if (BIT(group.mask, toggle))
{
float const nubtop(BIT(group.state, toggle) ? yon : yoff);
container().add_rect(
- nubleft, nubtop, nubleft + nubwidth, nubtop + nubheight,
+ nubleft, nubtop, nubleft + m_nub_width, nubtop + nubheight,
BIT(selectedmask, toggle) ? ui().colors().dipsw_color() : ui().colors().text_color(), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
}
else
{
container().add_rect(
- nubleft, yoff, nubleft + nubwidth, yon + nubheight,
+ nubleft, yoff, nubleft + m_nub_width, yon + nubheight,
ui().colors().unavailable_color(), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
}
}
@@ -372,27 +457,69 @@ void menu_settings_dip_switches::custom_render(void *selectedref, float top, flo
}
-void menu_settings_dip_switches::populate(float &customtop, float &custombottom)
+std::tuple<int, bool, bool> menu_settings_dip_switches::custom_pointer_updated(bool changed, ui_event const &uievt)
+{
+ if (!m_visible_switch_groups || !(uievt.pointer_pressed & 0x01) || (uievt.pointer_buttons & ~u32(0x01)))
+ return std::make_tuple(IPT_INVALID, false, false);
+
+ auto const [cx, y] = pointer_location();
+ if (cx < m_first_nub)
+ return std::make_tuple(IPT_INVALID, false, false);
+
+ float const x(cx - m_first_nub);
+ for (unsigned n = 0U, line = 0U; (switch_groups().size() > n) && (m_visible_switch_groups > line); ++n)
+ {
+ switch_group_descriptor const &group(switch_groups()[n]);
+ if (group.mask)
+ {
+ ++line;
+ if ((y >= m_switch_group_y[n]) && (y < (m_switch_group_y[n] + m_clickable_height)))
+ {
+ unsigned const cnt(group.switch_count());
+ for (unsigned i = 0U; cnt > i; ++i)
+ {
+ if (BIT(group.mask, i))
+ {
+ float const xstart(float(i) * m_single_width);
+ if ((x >= xstart) && (x < (xstart + m_nub_width)))
+ {
+ ioport_field::user_settings settings;
+ group.toggles[i].field->get_user_settings(settings);
+ settings.value ^= group.toggles[i].mask;
+ group.toggles[i].field->set_user_settings(settings);
+ return std::make_tuple(IPT_CUSTOM, true, true);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return std::make_tuple(IPT_INVALID, false, false);
+}
+
+
+void menu_settings_dip_switches::populate()
{
// let the base class add items
- menu_confswitch::populate(customtop, custombottom);
+ menu_confswitch::populate();
// use up to about 70% of height for DIP switch display
if (active_switch_groups())
{
- float const lineheight(ui().get_line_height());
- float const groupheight(DIP_SWITCH_HEIGHT * lineheight);
- float const groupspacing(DIP_SWITCH_SPACING * lineheight);
+ m_switch_group_y.resize(switch_groups().size());
+ float const groupheight(DIP_SWITCH_HEIGHT * line_height());
+ float const groupspacing(DIP_SWITCH_SPACING * line_height());
if ((active_switch_groups() * (groupheight + groupspacing)) > 0.7f)
m_visible_switch_groups = unsigned(0.7f / (groupheight + groupspacing));
else
m_visible_switch_groups = active_switch_groups();
- custombottom = (m_visible_switch_groups * groupheight) + ((m_visible_switch_groups - 1) * groupspacing) + (ui().box_tb_border() * 3.0f);
+ set_custom_space(0.0f, (m_visible_switch_groups * groupheight) + ((m_visible_switch_groups - 1) * groupspacing) + (tb_border() * 3.0f));
}
else
{
m_visible_switch_groups = 0U;
- custombottom = 0.0f;
+ set_custom_space(0.0f, 0.0f);
}
}
@@ -404,11 +531,11 @@ void menu_settings_dip_switches::populate(float &customtop, float &custombottom)
menu_settings_machine_config::menu_settings_machine_config(mame_ui_manager &mui, render_container &container) : menu_confswitch(mui, container, IPT_CONFIG)
{
+ set_heading(_("Machine Configuration"));
}
menu_settings_machine_config::~menu_settings_machine_config()
{
}
-
} // namespace ui