Merge pull request #884 from ajrhacker/ioport_field

Ioport refactoring and cleanups (nw)
This commit is contained in:
Miodrag Milanović 2016-05-19 07:30:09 +02:00
commit 209e4f8de7
12 changed files with 116 additions and 80 deletions

View File

@ -96,7 +96,6 @@
#include "xmlfile.h"
#include "profiler.h"
#include "ui/uimain.h"
#include "uiinput.h"
#include "osdepend.h"
@ -1516,7 +1515,7 @@ ioport_field::~ioport_field()
//-------------------------------------------------
// name - return the field name for a given input
// field
// field (this must never return nullptr)
//-------------------------------------------------
const char *ioport_field::name() const
@ -1583,22 +1582,28 @@ const input_seq &ioport_field::defseq(input_seq_type seqtype) const
ioport_type_class ioport_field::type_class() const
{
// inputs associated with specific players
ioport_group group = manager().type_group(m_type, m_player);
if (group >= IPG_PLAYER1 && group <= IPG_PLAYER8)
if (group >= IPG_PLAYER1 && group <= IPG_PLAYER10)
return INPUT_CLASS_CONTROLLER;
// keys (names derived from character codes)
if (m_type == IPT_KEYPAD || m_type == IPT_KEYBOARD)
return INPUT_CLASS_KEYBOARD;
// configuration settings (specific names required)
if (m_type == IPT_CONFIG)
return INPUT_CLASS_CONFIG;
// DIP switches (specific names required)
if (m_type == IPT_DIPSWITCH)
return INPUT_CLASS_DIPSWITCH;
// miscellaneous non-player inputs (named and user-mappable)
if (group == IPG_OTHER || (group == IPG_INVALID && m_name != nullptr))
return INPUT_CLASS_MISC;
// internal inputs (these may be anonymous)
return INPUT_CLASS_INTERNAL;
}
@ -1843,7 +1848,7 @@ void ioport_field::select_next_setting()
// digital field
//-------------------------------------------------
void ioport_field::frame_update(ioport_value &result, bool mouse_down)
void ioport_field::frame_update(ioport_value &result)
{
// skip if not enabled
if (!enabled())
@ -1861,7 +1866,7 @@ void ioport_field::frame_update(ioport_value &result, bool mouse_down)
return;
// if the state changed, look for switch down/switch up
bool curstate = mouse_down || machine().input().seq_pressed(seq()) || m_digital_value;
bool curstate = m_digital_value || machine().input().seq_pressed(seq());
if (m_live->autofire && !machine().ioport().get_autofire_toggle())
{
if (curstate)
@ -1928,7 +1933,7 @@ void ioport_field::frame_update(ioport_value &result, bool mouse_down)
curstate = false;
// additional logic to restrict digital joysticks
if (curstate && !m_digital_value && !mouse_down && m_live->joystick != nullptr && m_way != 16 && !machine().options().joystick_contradictory())
if (curstate && !m_digital_value && m_live->joystick != nullptr && m_way != 16 && !machine().options().joystick_contradictory())
{
UINT8 mask = (m_way == 4) ? m_live->joystick->current4way() : m_live->joystick->current();
if (!(mask & (1 << m_live->joydir)))
@ -2273,14 +2278,14 @@ void ioport_port::write(ioport_value data, ioport_value mem_mask)
// frame_update - once/frame update
//-------------------------------------------------
void ioport_port::frame_update(ioport_field *mouse_field)
void ioport_port::frame_update()
{
// start with 0 values for the digital bits
m_live->digital = 0;
// now loop back and modify based on the inputs
for (ioport_field &field : fields())
field.frame_update(m_live->digital, &field == mouse_field);
field.frame_update(m_live->digital);
// hook for MESS's natural keyboard support
manager().natkeyboard().frame_update(*this, m_live->digital);
@ -2372,6 +2377,24 @@ void ioport_port::init_live_state()
}
//-------------------------------------------------
// update_defvalue - force an update to the input
// port values based on current conditions
//-------------------------------------------------
void ioport_port::update_defvalue(bool flush_defaults)
{
// only clear on the first pass
if (flush_defaults)
m_live->defvalue = 0;
// recompute the default value for the entire port
for (ioport_field &field : m_fieldlist)
if (field.enabled())
m_live->defvalue = (m_live->defvalue & ~field.mask()) | (field.live().value & field.mask());
}
//**************************************************************************
// I/O PORT LIVE STATE
@ -2648,10 +2671,10 @@ const char *ioport_manager::type_name(ioport_type type, UINT8 player)
{
// if we have a machine, use the live state and quick lookup
input_type_entry *entry = m_type_to_entry[type][player];
if (entry != nullptr)
if (entry != nullptr && entry->name() != nullptr)
return entry->name();
// if we find nothing, return an invalid group
// if we find nothing, return a default string (not a null pointer)
return "???";
}
@ -2795,32 +2818,6 @@ bool ioport_manager::crosshair_position(int player, float &x, float &y)
}
//-------------------------------------------------
// update_defaults - force an update to the input
// port values based on current conditions
//-------------------------------------------------
void ioport_manager::update_defaults()
{
// two passes to catch conditionals properly
for (int loopnum = 0; loopnum < 2; loopnum++)
{
// loop over all input ports
for (ioport_port &port : m_portlist)
{
// only clear on the first pass
if (loopnum == 0)
port.live().defvalue = 0;
// first compute the default value for the entire port
for (ioport_field &field : port.fields())
if (field.enabled())
port.live().defvalue = (port.live().defvalue & ~field.mask()) | (field.live().value & field.mask());
}
}
}
//-------------------------------------------------
// frame_update - core logic for per-frame input
// port updating
@ -2873,31 +2870,16 @@ g_profiler.start(PROFILER_INPUT);
joystick.frame_update();
// compute default values for all the ports
update_defaults();
// perform mouse hit testing
INT32 mouse_target_x, mouse_target_y;
bool mouse_button;
render_target *mouse_target = machine().ui_input().find_mouse(&mouse_target_x, &mouse_target_y, &mouse_button);
// if the button is pressed, map the point and determine what was hit
ioport_field *mouse_field = nullptr;
if (mouse_button && mouse_target != nullptr)
{
ioport_port *port = nullptr;
ioport_value mask;
float x, y;
if (mouse_target->map_point_input(mouse_target_x, mouse_target_y, port, mask, x, y))
{
if (port != nullptr)
mouse_field = port->field(mask);
}
}
// two passes to catch conditionals properly
for (ioport_port &port : m_portlist)
port.update_defvalue(true);
for (ioport_port &port : m_portlist)
port.update_defvalue(false);
// loop over all input ports
for (ioport_port &port : m_portlist)
{
port.frame_update(mouse_field);
port.frame_update();
// handle playback/record
playback_port(port);

View File

@ -1117,6 +1117,7 @@ public:
ioport_condition &condition() { return m_condition; }
ioport_type type() const { return m_type; }
UINT8 player() const { return m_player; }
bool digital_value() const { return m_digital_value; }
void set_value(ioport_value value);
bool unused() const { return ((m_flags & FIELD_FLAG_UNUSED) != 0); }
@ -1171,7 +1172,7 @@ public:
void select_next_setting();
void crosshair_position(float &x, float &y, bool &gotx, bool &goty);
void init_live_state(analog_field *analog);
void frame_update(ioport_value &result, bool mouse_down);
void frame_update(ioport_value &result);
void reduce_mask(ioport_value bits_to_remove) { m_mask &= ~bits_to_remove; }
// user-controllable settings for a field
@ -1308,8 +1309,9 @@ public:
// other operations
ioport_field *field(ioport_value mask) const;
void collapse_fields(std::string &errorbuf);
void frame_update(ioport_field *mouse_field);
void frame_update();
void init_live_state();
void update_defvalue(bool flush_defaults);
private:
void insert_field(ioport_field &newfield, ioport_value &disallowedbits, std::string &errorbuf);
@ -1516,7 +1518,6 @@ private:
ioport_port *port(const char *tag) const { return m_portlist.find(tag); }
void exit();
input_seq_type token_to_seq_type(const char *string);
void update_defaults();
void load_config(config_type cfg_type, xml_data_node *parentnode);
void load_remap_table(xml_data_node *parentnode);

View File

@ -203,7 +203,7 @@ void running_machine::start()
// allocate a soft_reset timer
m_soft_reset_timer = m_scheduler.timer_alloc(timer_expired_delegate(FUNC(running_machine::soft_reset), this));
// intialize UI input
// initialize UI input
m_ui_input = make_unique_clear<ui_input_manager>(*this);
// init the osd layer

View File

@ -25,17 +25,18 @@ enum
//**************************************************************************
// NETWORK MANAGER
// UI INPUT MANAGER
//**************************************************************************
//-------------------------------------------------
// network_manager - constructor
// ui_input_manager - constructor
//-------------------------------------------------
ui_input_manager::ui_input_manager(running_machine &machine)
: m_machine(machine),
m_current_mouse_target(nullptr),
m_current_mouse_down(false),
m_current_mouse_field(nullptr),
m_events_start(0),
m_events_end(0)
{
@ -68,6 +69,22 @@ void ui_input_manager::frame_update()
if (!pressed || m_seqpressed[code] != SEQ_PRESSED_RESET)
m_seqpressed[code] = pressed;
}
// perform mouse hit testing
ioport_field *mouse_field = m_current_mouse_down ? find_mouse_field() : nullptr;
if (m_current_mouse_field != mouse_field)
{
// clear the old field if there was one
if (m_current_mouse_field != nullptr)
m_current_mouse_field->set_value(0);
// set the new field if it exists and isn't already being pressed
if (mouse_field != nullptr && !mouse_field->digital_value())
mouse_field->set_value(1);
// update internal state
m_current_mouse_field = mouse_field;
}
}
@ -166,7 +183,7 @@ void ui_input_manager::reset()
location of the mouse
-------------------------------------------------*/
render_target *ui_input_manager::find_mouse(INT32 *x, INT32 *y, bool *button)
render_target *ui_input_manager::find_mouse(INT32 *x, INT32 *y, bool *button) const
{
if (x != nullptr)
*x = m_current_mouse_x;
@ -178,6 +195,29 @@ render_target *ui_input_manager::find_mouse(INT32 *x, INT32 *y, bool *button)
}
/*-------------------------------------------------
find_mouse_field - retrieves the input field
the mouse is currently pointing at
-------------------------------------------------*/
ioport_field *ui_input_manager::find_mouse_field() const
{
// map the point and determine what was hit
if (m_current_mouse_target != nullptr)
{
ioport_port *port = nullptr;
ioport_value mask;
float x, y;
if (m_current_mouse_target->map_point_input(m_current_mouse_x, m_current_mouse_y, port, mask, x, y))
{
if (port != nullptr)
return port->field(mask);
}
}
return nullptr;
}
/***************************************************************************
USER INTERFACE SEQUENCE READING

View File

@ -12,8 +12,6 @@
#ifndef __UIINPUT_H__
#define __UIINPUT_H__
#include "render.h"
/***************************************************************************
CONSTANTS
@ -25,6 +23,8 @@
TYPE DEFINITIONS
***************************************************************************/
class render_target;
enum ui_event_type
{
UI_EVENT_NONE,
@ -71,7 +71,8 @@ public:
void reset();
/* retrieves the current location of the mouse */
render_target *find_mouse(INT32 *x, INT32 *y, bool *button);
render_target *find_mouse(INT32 *x, INT32 *y, bool *button) const;
ioport_field *find_mouse_field() const;
/* return TRUE if a key down for the given user interface sequence is detected */
bool pressed(int code);
@ -110,6 +111,7 @@ private:
INT32 m_current_mouse_x;
INT32 m_current_mouse_y;
bool m_current_mouse_down;
ioport_field * m_current_mouse_field;
/* popped states; ring buffer of ui_events */
ui_event m_events[EVENT_QUEUE_SIZE];

View File

@ -872,14 +872,22 @@ void validity_checker::validate_inputs()
// verify dip switches
if (field.type() == IPT_DIPSWITCH)
{
// dip switch fields must have a name
if (field.name() == nullptr)
osd_printf_error("DIP switch has a nullptr name\n");
// dip switch fields must have a specific name
if (field.specific_name() == nullptr)
osd_printf_error("DIP switch has no specific name\n");
// verify the settings list
validate_dip_settings(field);
}
// verify config settings
if (field.type() == IPT_CONFIG)
{
// config fields must have a specific name
if (field.specific_name() == nullptr)
osd_printf_error("Config switch has no specific name\n");
}
// verify names
const char *name = field.specific_name();
if (name != nullptr)

View File

@ -664,7 +664,7 @@ luabridge::LuaRef lua_engine::l_ioports_port_get_fields(const ioport_port *i)
luabridge::LuaRef f_table = luabridge::LuaRef::newTable(L);
for (ioport_field &field : p->fields()) {
if(field.name())
if (field.type_class() != INPUT_CLASS_INTERNAL)
f_table[field.name()] = &field;
}
@ -1985,7 +1985,7 @@ void lua_engine::update_machine()
{
for (ioport_field &field : port.fields())
{
if (field.name())
if (field.type_class() != INPUT_CLASS_INTERNAL)
{
push(m_lua_state, &field, tname_ioport);
lua_setfield(m_lua_state, -2, field.name());
@ -2214,7 +2214,7 @@ void lua_engine::initialize()
.addProperty ("sensitivity", &ioport_field::sensitivity)
.addProperty ("way", &ioport_field::way)
.addProperty ("is_analog", &ioport_field::is_analog)
.addProperty ("is_digitial_joystick", &ioport_field::is_digital_joystick)
.addProperty ("is_digital_joystick", &ioport_field::is_digital_joystick)
.addProperty ("enabled", &ioport_field::enabled)
.addProperty ("unused", &ioport_field::unused)
.addProperty ("cocktail", &ioport_field::cocktail)

View File

@ -263,7 +263,7 @@ void ui_menu_autofire::populate()
bool is_first_button = true;
for (ioport_field &field : port.fields())
{
if ((field.name()) && ((field.type() >= IPT_BUTTON1 && field.type() <= IPT_BUTTON16))) // IPT_BUTTON1 + 15)))
if (field.type() >= IPT_BUTTON1 && field.type() <= IPT_BUTTON16)
{
menu_items++;
ioport_field::user_settings settings;

View File

@ -167,20 +167,19 @@ void ui_menu_input_specific::populate()
port_count++;
for (ioport_field &field : port.fields())
{
const char *name = field.name();
ioport_type_class type_class = field.type_class();
/* add if we match the group and we have a valid name */
if (name != nullptr && field.enabled() &&
((field.type() == IPT_OTHER && field.name() != nullptr) || machine().ioport().type_group(field.type(), field.player()) != IPG_INVALID))
if (field.enabled() && (type_class == INPUT_CLASS_CONTROLLER || type_class == INPUT_CLASS_MISC))
{
input_seq_type seqtype;
UINT32 sortorder;
/* determine the sorting order */
if (field.type() >= IPT_START1 && field.type() < IPT_ANALOG_LAST)
if (type_class == INPUT_CLASS_CONTROLLER)
{
sortorder = (field.type() << 2) | (field.player() << 12);
if (strcmp(field.device().tag(), ":"))
if (field.device().owner() != nullptr)
sortorder |= (port_count & 0xfff) * 0x10000;
}
else
@ -200,7 +199,7 @@ void ui_menu_input_specific::populate()
item->defseq = &field.defseq(seqtype);
item->sortorder = sortorder + suborder[seqtype];
item->type = field.is_analog() ? (INPUT_TYPE_ANALOG + seqtype) : INPUT_TYPE_DIGITAL;
item->name = name;
item->name = field.name();
item->owner_name = field.device().tag();
item->next = itemlist;
itemlist = item;

View File

@ -4,6 +4,7 @@
#include "emu.h"
#include "imgui/imgui.h"
#include "render.h"
#include "uiinput.h"
#include "debug/debugvw.h"

View File

@ -28,6 +28,7 @@
#include "emu.h"
#include "emuopts.h"
#include "render.h"
#include "ui/uimain.h"
// OSD headers

View File

@ -25,6 +25,8 @@
// TYPE DEFINITIONS
//============================================================
class render_target;
// forward of SDL_DisplayMode not possible (typedef struct) - define wrapper
class SDL_DM_Wrapper;