summaryrefslogtreecommitdiffstatshomepage
path: root/src/frontend
diff options
context:
space:
mode:
author Vas Crabb <vas@vastheman.com>2019-11-16 02:21:45 +1100
committer Vas Crabb <vas@vastheman.com>2019-11-16 02:21:45 +1100
commit85eeea5d57762ad516a9be394bd167920b142ab0 (patch)
tree19bd7d5de466d34e1e0c6f64acd0fe10a0d3be2f /src/frontend
parent35f40a8200ec3c27351f0ff9f8f8721361c16dff (diff)
Display emulated analog input values on the anaolg controls menu screen
Diffstat (limited to 'src/frontend')
-rw-r--r--src/frontend/mame/ui/analogipt.cpp298
-rw-r--r--src/frontend/mame/ui/analogipt.h77
-rw-r--r--src/frontend/mame/ui/inputmap.cpp196
-rw-r--r--src/frontend/mame/ui/inputmap.h31
-rw-r--r--src/frontend/mame/ui/mainmenu.cpp1
5 files changed, 380 insertions, 223 deletions
diff --git a/src/frontend/mame/ui/analogipt.cpp b/src/frontend/mame/ui/analogipt.cpp
new file mode 100644
index 00000000000..c21faca9af6
--- /dev/null
+++ b/src/frontend/mame/ui/analogipt.cpp
@@ -0,0 +1,298 @@
+// license:BSD-3-Clause
+// copyright-holders:Nicola Salmoria, Aaron Giles, Nathan Woods
+/*********************************************************************
+
+ ui/analogipt.cpp
+
+ Analog inputs menu.
+
+*********************************************************************/
+
+#include "emu.h"
+#include "ui/analogipt.h"
+
+#include <algorithm>
+
+
+namespace ui {
+
+inline menu_analog::item_data::item_data(ioport_field &f, int t)
+ : field(f)
+ , type(t)
+ , min((ANALOG_ITEM_SENSITIVITY == t) ? 1 : 0)
+ , max((ANALOG_ITEM_REVERSE == t) ? 1 : 255)
+ , cur(-1)
+ , defvalue(
+ (ANALOG_ITEM_KEYSPEED == t) ? f.delta() :
+ (ANALOG_ITEM_CENTERSPEED == t) ? f.centerdelta() :
+ (ANALOG_ITEM_REVERSE == t) ? f.analog_reverse() :
+ (ANALOG_ITEM_SENSITIVITY == t) ? f.sensitivity() :
+ -1)
+{
+}
+
+
+inline menu_analog::field_data::field_data(ioport_field &f)
+ : field(f)
+ , range(f.maxval() - f.minval())
+{
+}
+
+
+menu_analog::menu_analog(mame_ui_manager &mui, render_container &container)
+ : menu(mui, container)
+ , m_item_data()
+ , m_field_data()
+ , m_visible_fields(0U)
+{
+}
+
+
+menu_analog::~menu_analog()
+{
+}
+
+
+void menu_analog::custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2)
+{
+ // work out how much space to use for field names
+ float const extrawidth(0.4f + (ui().box_lr_border() * 2.0f) + (ui().get_line_height() * machine().render().ui_aspect()));
+ float const nameavail(1.0f - (ui().box_lr_border() * 2.0f) - extrawidth);
+ float namewidth(0.0f);
+ for (field_data &data : m_field_data)
+ namewidth = (std::min)((std::max)(ui().get_string_width(data.field.get().name()), namewidth), nameavail);
+
+ // make a box
+ float const boxleft((1.0f - namewidth - extrawidth) / 2.0f);
+ float const boxright(boxleft + namewidth + extrawidth);
+ ui().draw_outlined_box(container(), boxleft, y2 + ui().box_tb_border(), boxright, y2 + bottom, ui().colors().background_color());
+
+ // show live fields
+ namewidth += ui().get_line_height() * machine().render().ui_aspect();
+ unsigned line(0U);
+ float const nameleft(boxleft + ui().box_lr_border());
+ float const indleft(nameleft + namewidth);
+ float const indright(indleft + 0.4f);
+ ioport_field *const selfield(selectedref ? &reinterpret_cast<item_data *>(selectedref)->field.get() : nullptr);
+ for (field_data &data : m_field_data)
+ {
+ bool const selected(&data.field.get() == selfield);
+ rgb_t const fgcolor(selected ? ui().colors().selected_color() : ui().colors().text_color());
+ float const liney(y2 + (ui().box_tb_border() * 2.0f) + (ui().get_line_height() * line));
+ ui().draw_text_full(
+ container(),
+ data.field.get().name(),
+ nameleft, liney, namewidth, ui::text_layout::CENTER, ui::text_layout::TRUNCATE,
+ mame_ui_manager::NORMAL, fgcolor, ui().colors().text_bg_color());
+
+ ioport_value cur(0U);
+ data.field.get().live().analog->read(cur);
+ cur -= data.field.get().minval();
+ float fill(float(cur) / data.range);
+ if (data.field.get().analog_reverse())
+ fill = 1.0f - fill;
+
+ float const indtop(liney + (ui().get_line_height() * 0.2f));
+ float const indbottom(liney + (ui().get_line_height() * 0.8f));
+ container().add_rect(indleft, indtop, indleft + (fill * 0.4f), indbottom, fgcolor, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+ container().add_line(indleft, indtop, indright, indtop, UI_LINE_WIDTH, fgcolor, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+ container().add_line(indright, indtop, indright, indbottom, UI_LINE_WIDTH, fgcolor, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+ container().add_line(indright, indbottom, indleft, indbottom, UI_LINE_WIDTH, fgcolor, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+ container().add_line(indleft, indbottom, indleft, indtop, UI_LINE_WIDTH, fgcolor, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+
+ // TODO: ensure field being configured is visible
+ if (++line >= m_visible_fields)
+ break;
+ }
+}
+
+
+void menu_analog::handle()
+{
+ // process the menu
+ event const *const menu_event(process(PROCESS_LR_REPEAT));
+
+ // handle events
+ if (menu_event && menu_event->itemref)
+ {
+ item_data &data(*reinterpret_cast<item_data *>(menu_event->itemref));
+ int newval(data.cur);
+
+ switch (menu_event->iptkey)
+ {
+ // if selected, reset to default value
+ case IPT_UI_SELECT:
+ newval = data.defvalue;
+ break;
+
+ // left decrements
+ case IPT_UI_LEFT:
+ newval -= machine().input().code_pressed(KEYCODE_LSHIFT) ? 10 : 1;
+ break;
+
+ // right increments
+ case IPT_UI_RIGHT:
+ newval += machine().input().code_pressed(KEYCODE_LSHIFT) ? 10 : 1;
+ break;
+ }
+
+ // clamp to range
+ if (newval < data.min)
+ newval = data.min;
+ if (newval > data.max)
+ newval = data.max;
+
+ // if things changed, update
+ if (newval != data.cur)
+ {
+ ioport_field::user_settings settings;
+
+ // get the settings and set the new value
+ data.field.get().get_user_settings(settings);
+ switch (data.type)
+ {
+ case ANALOG_ITEM_KEYSPEED: settings.delta = newval; break;
+ case ANALOG_ITEM_CENTERSPEED: settings.centerdelta = newval; break;
+ case ANALOG_ITEM_REVERSE: settings.reverse = newval; break;
+ case ANALOG_ITEM_SENSITIVITY: settings.sensitivity = newval; break;
+ }
+ data.field.get().set_user_settings(settings);
+
+ // rebuild the menu
+ reset(reset_options::REMEMBER_POSITION);
+ }
+ }
+}
+
+
+void menu_analog::populate(float &customtop, float &custombottom)
+{
+ // loop over input ports
+ if (m_item_data.empty())
+ find_fields();
+
+ device_t *prev_owner(nullptr);
+ bool first_entry(true);
+ ioport_field *field(nullptr);
+ ioport_field::user_settings settings;
+
+ // add the items
+ std::string text;
+ std::string subtext;
+ for (item_data &data : m_item_data)
+ {
+ // get the user settings
+ if (&data.field.get() != field)
+ {
+ field = &data.field.get();
+ field->get_user_settings(settings);
+
+ if (&field->device() != prev_owner)
+ {
+ prev_owner = &field->device();
+ if (first_entry)
+ first_entry = false;
+ else
+ item_append(menu_item_type::SEPARATOR);
+ item_append(string_format("[root%s]", prev_owner->tag()), "", 0, nullptr);
+ }
+ }
+
+ // determine the properties of this item
+ switch (data.type)
+ {
+ default:
+ case ANALOG_ITEM_KEYSPEED:
+ text = string_format("%s Digital Speed", field->name());
+ subtext = string_format("%d", settings.delta);
+ data.cur = settings.delta;
+ break;
+
+ case ANALOG_ITEM_CENTERSPEED:
+ text = string_format("%s Autocenter Speed", field->name());
+ subtext = string_format("%d", settings.centerdelta);
+ data.cur = settings.centerdelta;
+ break;
+
+ case ANALOG_ITEM_REVERSE:
+ text = string_format("%s Reverse", field->name());
+ subtext.assign(settings.reverse ? "On" : "Off");
+ data.cur = settings.reverse;
+ break;
+
+ case ANALOG_ITEM_SENSITIVITY:
+ text = string_format("%s Sensitivity", field->name());
+ subtext = string_format("%d", settings.sensitivity);
+ data.cur = settings.sensitivity;
+ break;
+ }
+
+ // put on arrows
+ uint32_t flags = 0;
+ if (data.cur > data.min)
+ flags |= FLAG_LEFT_ARROW;
+ if (data.cur < data.max)
+ flags |= FLAG_RIGHT_ARROW;
+
+ // append a menu item
+ item_append(std::move(text), std::move(subtext), flags, &data);
+ }
+
+ // space for live display
+ custombottom = (ui().get_line_height() * m_visible_fields) + (ui().box_tb_border() * 3.0f);
+}
+
+
+void menu_analog::find_fields()
+{
+ // collect analog fields
+ for (auto &port : machine().ioport().ports())
+ {
+ for (ioport_field &field : port.second->fields())
+ {
+ if (field.is_analog() && field.enabled())
+ {
+ // based on the type, determine if we enable autocenter
+ bool use_autocenter = false;
+ switch (field.type())
+ {
+ case IPT_POSITIONAL:
+ case IPT_POSITIONAL_V:
+ use_autocenter = !field.analog_wraps();
+ break;
+
+ case IPT_AD_STICK_X:
+ case IPT_AD_STICK_Y:
+ case IPT_AD_STICK_Z:
+ case IPT_PADDLE:
+ case IPT_PADDLE_V:
+ case IPT_PEDAL:
+ case IPT_PEDAL2:
+ case IPT_PEDAL3:
+ use_autocenter = true;
+ break;
+
+ default:
+ break;
+ }
+
+ // iterate over types
+ for (int type = 0; type < ANALOG_ITEM_COUNT; type++)
+ {
+ if ((ANALOG_ITEM_CENTERSPEED != type) || use_autocenter)
+ m_item_data.emplace_back(field, type);
+ }
+
+ m_field_data.emplace_back(field);
+ }
+ }
+ }
+
+ // restrict live display to 40% height plus borders
+ if ((ui().get_line_height() * m_field_data.size()) > 0.4f)
+ m_visible_fields = unsigned(0.4f / ui().get_line_height());
+ else
+ m_visible_fields = m_field_data.size();
+}
+
+} // namespace ui
diff --git a/src/frontend/mame/ui/analogipt.h b/src/frontend/mame/ui/analogipt.h
new file mode 100644
index 00000000000..b71cc095cc0
--- /dev/null
+++ b/src/frontend/mame/ui/analogipt.h
@@ -0,0 +1,77 @@
+// license:BSD-3-Clause
+// copyright-holders:Nicola Salmoria, Aaron Giles, Nathan Woods
+/***************************************************************************
+
+ ui/analogipt.h
+
+ Analog inputs menu.
+
+***************************************************************************/
+
+#ifndef MAME_FRONTEND_UI_ANALOGIPT_H
+#define MAME_FRONTEND_UI_ANALOGIPT_H
+
+#pragma once
+
+#include "ui/menu.h"
+
+#include <functional>
+#include <vector>
+
+
+namespace ui {
+
+class menu_analog : public menu
+{
+public:
+ menu_analog(mame_ui_manager &mui, render_container &container);
+ virtual ~menu_analog() override;
+
+protected:
+ virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override;
+
+private:
+ enum
+ {
+ ANALOG_ITEM_KEYSPEED = 0,
+ ANALOG_ITEM_CENTERSPEED,
+ ANALOG_ITEM_REVERSE,
+ ANALOG_ITEM_SENSITIVITY,
+ ANALOG_ITEM_COUNT
+ };
+
+ struct item_data
+ {
+ item_data(ioport_field &f, int t);
+
+ std::reference_wrapper<ioport_field> field;
+ int type;
+ int min, max;
+ int cur;
+ int defvalue;
+ };
+
+ struct field_data
+ {
+ field_data(ioport_field &f);
+
+ std::reference_wrapper<ioport_field> field;
+ float range;
+ };
+
+ using item_data_vector = std::vector<item_data>;
+ using field_data_vector = std::vector<field_data>;
+
+ virtual void populate(float &customtop, float &custombottom) override;
+ virtual void handle() override;
+
+ void find_fields();
+
+ item_data_vector m_item_data;
+ field_data_vector m_field_data;
+ unsigned m_visible_fields;
+};
+
+} // namespace ui
+
+#endif // MAME_FRONTEND_UI_ANALOGIPT_H
diff --git a/src/frontend/mame/ui/inputmap.cpp b/src/frontend/mame/ui/inputmap.cpp
index eb90215520e..cc91e92766e 100644
--- a/src/frontend/mame/ui/inputmap.cpp
+++ b/src/frontend/mame/ui/inputmap.cpp
@@ -9,16 +9,16 @@
*********************************************************************/
#include "emu.h"
+#include "ui/inputmap.h"
#include "uiinput.h"
#include "ui/ui.h"
-#include "ui/menu.h"
-#include "ui/inputmap.h"
#include <algorithm>
namespace ui {
+
/***************************************************************************
CONSTANTS
***************************************************************************/
@@ -740,196 +740,4 @@ void menu_settings_dip_switches::custom_render_one(float x1, float y1, float x2,
}
}
-
-/*-------------------------------------------------
- menu_analog - handle the analog settings menu
--------------------------------------------------*/
-
-void menu_analog::handle()
-{
- /* process the menu */
- const event *menu_event = process(PROCESS_LR_REPEAT);
-
- /* handle events */
- if (menu_event != nullptr && menu_event->itemref != nullptr)
- {
- analog_item_data *data = (analog_item_data *)menu_event->itemref;
- int newval = data->cur;
-
- switch (menu_event->iptkey)
- {
- /* if selected, reset to default value */
- case IPT_UI_SELECT:
- newval = data->defvalue;
- break;
-
- /* left decrements */
- case IPT_UI_LEFT:
- newval -= machine().input().code_pressed(KEYCODE_LSHIFT) ? 10 : 1;
- break;
-
- /* right increments */
- case IPT_UI_RIGHT:
- newval += machine().input().code_pressed(KEYCODE_LSHIFT) ? 10 : 1;
- break;
- }
-
- /* clamp to range */
- if (newval < data->min)
- newval = data->min;
- if (newval > data->max)
- newval = data->max;
-
- /* if things changed, update */
- if (newval != data->cur)
- {
- ioport_field::user_settings settings;
-
- /* get the settings and set the new value */
- data->field->get_user_settings(settings);
- switch (data->type)
- {
- case ANALOG_ITEM_KEYSPEED: settings.delta = newval; break;
- case ANALOG_ITEM_CENTERSPEED: settings.centerdelta = newval; break;
- case ANALOG_ITEM_REVERSE: settings.reverse = newval; break;
- case ANALOG_ITEM_SENSITIVITY: settings.sensitivity = newval; break;
- }
- data->field->set_user_settings(settings);
-
- /* rebuild the menu */
- reset(reset_options::REMEMBER_POSITION);
- }
- }
-}
-
-
-/*-------------------------------------------------
- menu_analog_populate - populate the analog
- settings menu
--------------------------------------------------*/
-
-menu_analog::menu_analog(mame_ui_manager &mui, render_container &container) : menu(mui, container)
-{
-}
-
-void menu_analog::populate(float &customtop, float &custombottom)
-{
- std::string prev_owner;
- bool first_entry = true;
-
- /* loop over input ports and add the items */
- for (auto &port : machine().ioport().ports())
- for (ioport_field &field : port.second->fields())
- if (field.is_analog() && field.enabled())
- {
- ioport_field::user_settings settings;
- int use_autocenter = false;
- int type;
-
- /* based on the type, determine if we enable autocenter */
- switch (field.type())
- {
- case IPT_POSITIONAL:
- case IPT_POSITIONAL_V:
- if (field.analog_wraps())
- break;
-
- case IPT_AD_STICK_X:
- case IPT_AD_STICK_Y:
- case IPT_AD_STICK_Z:
- case IPT_PADDLE:
- case IPT_PADDLE_V:
- case IPT_PEDAL:
- case IPT_PEDAL2:
- case IPT_PEDAL3:
- use_autocenter = true;
- break;
-
- default:
- break;
- }
-
- /* get the user settings */
- field.get_user_settings(settings);
-
- /* iterate over types */
- for (type = 0; type < ANALOG_ITEM_COUNT; type++)
- if (type != ANALOG_ITEM_CENTERSPEED || use_autocenter)
- {
- analog_item_data *data;
- uint32_t flags = 0;
- std::string text;
- std::string subtext;
- if (strcmp(field.device().tag(), prev_owner.c_str()) != 0)
- {
- if (first_entry)
- first_entry = false;
- else
- item_append(menu_item_type::SEPARATOR);
- item_append(string_format("[root%s]", field.device().tag()), "", 0, nullptr);
- prev_owner.assign(field.device().tag());
- }
-
- /* allocate a data item for tracking what this menu item refers to */
- data = (analog_item_data *)m_pool_alloc(sizeof(*data));
- data->field = &field;
- data->type = type;
-
- /* determine the properties of this item */
- switch (type)
- {
- default:
- case ANALOG_ITEM_KEYSPEED:
- text = string_format("%s Digital Speed", field.name());
- subtext = string_format("%d", settings.delta);
- data->min = 0;
- data->max = 255;
- data->cur = settings.delta;
- data->defvalue = field.delta();
- break;
-
- case ANALOG_ITEM_CENTERSPEED:
- text = string_format("%s Autocenter Speed", field.name());
- subtext = string_format("%d", settings.centerdelta);
- data->min = 0;
- data->max = 255;
- data->cur = settings.centerdelta;
- data->defvalue = field.centerdelta();
- break;
-
- case ANALOG_ITEM_REVERSE:
- text = string_format("%s Reverse", field.name());
- subtext.assign(settings.reverse ? "On" : "Off");
- data->min = 0;
- data->max = 1;
- data->cur = settings.reverse;
- data->defvalue = field.analog_reverse();
- break;
-
- case ANALOG_ITEM_SENSITIVITY:
- text = string_format("%s Sensitivity", field.name());
- subtext = string_format("%d", settings.sensitivity);
- data->min = 1;
- data->max = 255;
- data->cur = settings.sensitivity;
- data->defvalue = field.sensitivity();
- break;
- }
-
- /* put on arrows */
- if (data->cur > data->min)
- flags |= FLAG_LEFT_ARROW;
- if (data->cur < data->max)
- flags |= FLAG_RIGHT_ARROW;
-
- /* append a menu item */
- item_append(std::move(text), std::move(subtext), flags, data);
- }
- }
-}
-
-menu_analog::~menu_analog()
-{
-}
-
} // namespace ui
diff --git a/src/frontend/mame/ui/inputmap.h b/src/frontend/mame/ui/inputmap.h
index a37a297a2f8..d0ffc4ec12c 100644
--- a/src/frontend/mame/ui/inputmap.h
+++ b/src/frontend/mame/ui/inputmap.h
@@ -17,6 +17,7 @@
namespace ui {
+
class menu_input_groups : public menu
{
public:
@@ -144,34 +145,6 @@ public:
virtual ~menu_settings_driver_config();
};
-class menu_analog : public menu
-{
-public:
- menu_analog(mame_ui_manager &mui, render_container &container);
- virtual ~menu_analog() override;
-
-private:
- enum {
- ANALOG_ITEM_KEYSPEED = 0,
- ANALOG_ITEM_CENTERSPEED,
- ANALOG_ITEM_REVERSE,
- ANALOG_ITEM_SENSITIVITY,
- ANALOG_ITEM_COUNT
- };
-
- /* internal analog menu item data */
- struct analog_item_data {
- ioport_field *field;
- int type;
- int min, max;
- int cur;
- int defvalue;
- };
-
- virtual void populate(float &customtop, float &custombottom) override;
- virtual void handle() override;
-};
-
} // namespace ui
-#endif /* MAME_FRONTEND_UI_INPUTMAP_H */
+#endif // MAME_FRONTEND_UI_INPUTMAP_H
diff --git a/src/frontend/mame/ui/mainmenu.cpp b/src/frontend/mame/ui/mainmenu.cpp
index b9befd90991..10cbced036d 100644
--- a/src/frontend/mame/ui/mainmenu.cpp
+++ b/src/frontend/mame/ui/mainmenu.cpp
@@ -11,6 +11,7 @@
#include "emu.h"
#include "ui/mainmenu.h"
+#include "ui/analogipt.h"
#include "ui/barcode.h"
#include "ui/cheatopt.h"
#include "ui/datmenu.h"