summaryrefslogtreecommitdiffstatshomepage
path: root/src/osd/modules/input/assignmenthelper.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/osd/modules/input/assignmenthelper.cpp')
-rw-r--r--src/osd/modules/input/assignmenthelper.cpp592
1 files changed, 592 insertions, 0 deletions
diff --git a/src/osd/modules/input/assignmenthelper.cpp b/src/osd/modules/input/assignmenthelper.cpp
new file mode 100644
index 00000000000..c044d4b7aa7
--- /dev/null
+++ b/src/osd/modules/input/assignmenthelper.cpp
@@ -0,0 +1,592 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+//============================================================
+//
+// assignmenthelper.cpp - input assignment setup helper
+//
+//============================================================
+
+#include "assignmenthelper.h"
+
+#include "interface/inputseq.h"
+
+#include "inpttype.h"
+
+
+namespace osd {
+
+bool joystick_assignment_helper::add_assignment(
+ input_device::assignment_vector &assignments,
+ ioport_type fieldtype,
+ input_seq_type seqtype,
+ input_item_class itemclass,
+ input_item_modifier modifier,
+ std::initializer_list<input_item_id> items)
+{
+ for (input_item_id item : items)
+ {
+ if (ITEM_ID_INVALID != item)
+ {
+ assignments.emplace_back(
+ fieldtype,
+ seqtype,
+ input_seq(input_code(DEVICE_CLASS_JOYSTICK, 0, itemclass, modifier, item)));
+ return true;
+ }
+ }
+ return false;
+}
+
+
+bool joystick_assignment_helper::add_button_assignment(
+ input_device::assignment_vector &assignments,
+ ioport_type field_type,
+ std::initializer_list<input_item_id> items)
+{
+ return add_assignment(
+ assignments,
+ field_type,
+ SEQ_TYPE_STANDARD,
+ ITEM_CLASS_SWITCH,
+ ITEM_MODIFIER_NONE,
+ items);
+}
+
+
+bool joystick_assignment_helper::add_button_pair_assignment(
+ input_device::assignment_vector &assignments,
+ ioport_type field1,
+ ioport_type field2,
+ input_item_id button1,
+ input_item_id button2)
+{
+ if ((ITEM_ID_INVALID == button1) || (ITEM_ID_INVALID == button2))
+ return false;
+
+ assignments.emplace_back(
+ field1,
+ SEQ_TYPE_STANDARD,
+ make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, button1));
+ assignments.emplace_back(
+ field2,
+ SEQ_TYPE_STANDARD,
+ make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, button2));
+ return true;
+}
+
+
+bool joystick_assignment_helper::add_axis_inc_dec_assignment(
+ input_device::assignment_vector &assignments,
+ ioport_type field_type,
+ input_item_id button_dec,
+ input_item_id button_inc)
+{
+ if ((ITEM_ID_INVALID == button_dec) || (ITEM_ID_INVALID == button_inc))
+ return false;
+
+ assignments.emplace_back(
+ field_type,
+ SEQ_TYPE_DECREMENT,
+ make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, button_dec));
+ assignments.emplace_back(
+ field_type,
+ SEQ_TYPE_INCREMENT,
+ make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, button_inc));
+ return true;
+}
+
+
+bool joystick_assignment_helper::add_axis_pair_assignment(
+ input_device::assignment_vector &assignments,
+ ioport_type field1,
+ ioport_type field2,
+ input_item_id axis)
+{
+ if (ITEM_ID_INVALID == axis)
+ return false;
+
+ assignments.emplace_back(
+ field1,
+ SEQ_TYPE_STANDARD,
+ make_code(
+ ITEM_CLASS_SWITCH,
+ (ITEM_ID_XAXIS == axis) ? ITEM_MODIFIER_LEFT : (ITEM_ID_YAXIS == axis) ? ITEM_MODIFIER_UP : ITEM_MODIFIER_NEG,
+ axis));
+ assignments.emplace_back(
+ field2,
+ SEQ_TYPE_STANDARD,
+ make_code(
+ ITEM_CLASS_SWITCH,
+ (ITEM_ID_XAXIS == axis) ? ITEM_MODIFIER_RIGHT : (ITEM_ID_YAXIS == axis) ? ITEM_MODIFIER_DOWN : ITEM_MODIFIER_POS,
+ axis));
+ return true;
+}
+
+
+bool joystick_assignment_helper::consume_button_pair(
+ input_device::assignment_vector &assignments,
+ ioport_type field1,
+ ioport_type field2,
+ input_item_id &button1,
+ input_item_id &button2)
+{
+ if (!add_button_pair_assignment(assignments, field1, field2, button1, button2))
+ return false;
+
+ button1 = ITEM_ID_INVALID;
+ button2 = ITEM_ID_INVALID;
+ return true;
+}
+
+
+bool joystick_assignment_helper::consume_trigger_pair(
+ input_device::assignment_vector &assignments,
+ ioport_type field1,
+ ioport_type field2,
+ input_item_id &axis1,
+ input_item_id &axis2)
+{
+ if ((ITEM_ID_INVALID == axis1) || (ITEM_ID_INVALID == axis2))
+ return false;
+
+ assignments.emplace_back(
+ field1,
+ SEQ_TYPE_STANDARD,
+ make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NEG, axis1));
+ assignments.emplace_back(
+ field2,
+ SEQ_TYPE_STANDARD,
+ make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NEG, axis2));
+ axis1 = ITEM_ID_INVALID;
+ axis2 = ITEM_ID_INVALID;
+ return true;
+}
+
+
+bool joystick_assignment_helper::consume_axis_pair(
+ input_device::assignment_vector &assignments,
+ ioport_type field1,
+ ioport_type field2,
+ input_item_id &axis)
+{
+ if (!add_axis_pair_assignment(assignments, field1, field2, axis))
+ return false;
+
+ axis = ITEM_ID_INVALID;
+ return true;
+}
+
+
+void joystick_assignment_helper::add_directional_assignments(
+ input_device::assignment_vector &assignments,
+ input_item_id xaxis,
+ input_item_id yaxis,
+ input_item_id leftswitch,
+ input_item_id rightswitch,
+ input_item_id upswitch,
+ input_item_id downswitch)
+{
+ // see if we have complementary pairs of directional switches
+ bool const hswitches = (ITEM_ID_INVALID != leftswitch) && (ITEM_ID_INVALID != rightswitch);
+ bool const vswitches = (ITEM_ID_INVALID != upswitch) && (ITEM_ID_INVALID != downswitch);
+
+ // use X axis if present
+ if (ITEM_ID_INVALID != xaxis)
+ {
+ // use this for horizontal axis movement
+ input_seq const xseq(make_code(ITEM_CLASS_ABSOLUTE, ITEM_MODIFIER_NONE, xaxis));
+ assignments.emplace_back(IPT_PADDLE, SEQ_TYPE_STANDARD, xseq);
+ assignments.emplace_back(IPT_POSITIONAL, SEQ_TYPE_STANDARD, xseq);
+ assignments.emplace_back(IPT_DIAL, SEQ_TYPE_STANDARD, xseq);
+ assignments.emplace_back(IPT_TRACKBALL_X, SEQ_TYPE_STANDARD, xseq);
+ assignments.emplace_back(IPT_AD_STICK_X, SEQ_TYPE_STANDARD, xseq);
+ assignments.emplace_back(IPT_LIGHTGUN_X, SEQ_TYPE_STANDARD, xseq);
+
+ // use it for the main left/right control, too
+ input_seq leftseq(make_code(ITEM_CLASS_SWITCH, (ITEM_ID_XAXIS == xaxis) ? ITEM_MODIFIER_LEFT : ITEM_MODIFIER_NEG, xaxis));
+ input_seq rightseq(make_code(ITEM_CLASS_SWITCH, (ITEM_ID_XAXIS == xaxis) ? ITEM_MODIFIER_RIGHT : ITEM_MODIFIER_POS, xaxis));
+ if (ITEM_ID_INVALID != leftswitch)
+ {
+ leftseq += input_seq::or_code;
+ leftseq += make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, leftswitch);
+ }
+ if (ITEM_ID_INVALID != rightswitch)
+ {
+ rightseq += input_seq::or_code;
+ rightseq += make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, rightswitch);
+ }
+ assignments.emplace_back(IPT_JOYSTICK_LEFT, SEQ_TYPE_STANDARD, leftseq);
+ assignments.emplace_back(IPT_JOYSTICK_RIGHT, SEQ_TYPE_STANDARD, rightseq);
+
+ // use for vertical navigation if there's no Y axis, or horizontal otherwise
+ if (ITEM_ID_INVALID != yaxis)
+ {
+ // if left/right are both present but not both up/down, they'll be taken for vertical navigation
+ if (hswitches && !vswitches)
+ {
+ leftseq.backspace();
+ if (ITEM_ID_INVALID != upswitch)
+ leftseq += make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, upswitch);
+ else
+ leftseq.backspace();
+
+ rightseq.backspace();
+ if (ITEM_ID_INVALID != downswitch)
+ rightseq += make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, downswitch);
+ else
+ rightseq.backspace();
+ }
+ assignments.emplace_back(IPT_UI_LEFT, SEQ_TYPE_STANDARD, leftseq);
+ assignments.emplace_back(IPT_UI_RIGHT, SEQ_TYPE_STANDARD, rightseq);
+ }
+ else
+ {
+ // prefer D-pad up/down for vertical navigation if present
+ if (!hswitches || vswitches)
+ {
+ while (leftseq.length() > 1)
+ leftseq.backspace();
+ if (ITEM_ID_INVALID != upswitch)
+ {
+ leftseq += input_seq::or_code;
+ leftseq += make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, upswitch);
+ }
+
+ while (rightseq.length() > 1)
+ rightseq.backspace();
+ if (ITEM_ID_INVALID != downswitch)
+ {
+ rightseq += input_seq::or_code;
+ rightseq += make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, downswitch);
+ }
+ }
+ assignments.emplace_back(IPT_UI_UP, SEQ_TYPE_STANDARD, leftseq);
+ assignments.emplace_back(IPT_UI_DOWN, SEQ_TYPE_STANDARD, rightseq);
+ }
+ }
+ else
+ {
+ // without a primary analog X axis, we still want D-pad left/right controls if possible
+ add_button_assignment(assignments, IPT_JOYSTICK_LEFT, { leftswitch });
+ add_button_assignment(assignments, IPT_JOYSTICK_RIGHT, { rightswitch });
+
+ // vertical navigation gets first pick on directional controls
+ add_button_assignment(assignments, IPT_UI_LEFT, { (hswitches && !vswitches) ? upswitch : leftswitch });
+ add_button_assignment(assignments, IPT_UI_RIGHT, { (hswitches && !vswitches) ? downswitch : rightswitch });
+ }
+
+ // use Y axis if present
+ if (ITEM_ID_INVALID != yaxis)
+ {
+ // use this for vertical axis movement
+ input_seq const yseq(make_code(ITEM_CLASS_ABSOLUTE, ITEM_MODIFIER_NONE, yaxis));
+ assignments.emplace_back(IPT_PADDLE_V, SEQ_TYPE_STANDARD, yseq);
+ assignments.emplace_back(IPT_POSITIONAL_V, SEQ_TYPE_STANDARD, yseq);
+ assignments.emplace_back(IPT_DIAL_V, SEQ_TYPE_STANDARD, yseq);
+ assignments.emplace_back(IPT_TRACKBALL_Y, SEQ_TYPE_STANDARD, yseq);
+ assignments.emplace_back(IPT_AD_STICK_Y, SEQ_TYPE_STANDARD, yseq);
+ assignments.emplace_back(IPT_LIGHTGUN_Y, SEQ_TYPE_STANDARD, yseq);
+
+ // use it for the main up/down control, too
+ input_seq upseq(make_code(ITEM_CLASS_SWITCH, (ITEM_ID_YAXIS == yaxis) ? ITEM_MODIFIER_UP : ITEM_MODIFIER_NEG, yaxis));
+ input_seq downseq(make_code(ITEM_CLASS_SWITCH, (ITEM_ID_YAXIS == yaxis) ? ITEM_MODIFIER_DOWN : ITEM_MODIFIER_POS, yaxis));
+ if (ITEM_ID_INVALID != upswitch)
+ {
+ upseq += input_seq::or_code;
+ upseq += make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, upswitch);
+ }
+ if (ITEM_ID_INVALID != downswitch)
+ {
+ downseq += input_seq::or_code;
+ downseq += make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, downswitch);
+ }
+ assignments.emplace_back(IPT_JOYSTICK_UP, SEQ_TYPE_STANDARD, upseq);
+ assignments.emplace_back(IPT_JOYSTICK_DOWN, SEQ_TYPE_STANDARD, downseq);
+
+ // if available, this is used for vertical navigation
+ if (hswitches && !vswitches)
+ {
+ if (upseq.length() > 1)
+ upseq.backspace();
+ else
+ upseq += input_seq::or_code;
+ upseq += make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, leftswitch);
+
+ if (downseq.length() > 1)
+ downseq.backspace();
+ else
+ downseq += input_seq::or_code;
+ downseq += make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, rightswitch);
+ }
+ assignments.emplace_back(IPT_UI_UP, SEQ_TYPE_STANDARD, upseq);
+ assignments.emplace_back(IPT_UI_DOWN, SEQ_TYPE_STANDARD, downseq);
+ }
+ else
+ {
+ // without a primary analog Y axis, we still want D-pad up/down controls if possible
+ add_button_assignment(assignments, IPT_JOYSTICK_UP, { upswitch });
+ add_button_assignment(assignments, IPT_JOYSTICK_DOWN, { downswitch });
+
+ // vertical navigation may be assigned to X axis if Y axis is not present
+ bool const dpadflip = (ITEM_ID_INVALID != xaxis) == (!hswitches || vswitches);
+ add_button_assignment(
+ assignments,
+ (ITEM_ID_INVALID != xaxis) ? IPT_UI_LEFT : IPT_UI_UP,
+ { dpadflip ? leftswitch : upswitch });
+ add_button_assignment(
+ assignments,
+ (ITEM_ID_INVALID != xaxis) ? IPT_UI_RIGHT : IPT_UI_DOWN,
+ { dpadflip ? rightswitch : downswitch });
+ }
+
+ // if we're missing either primary axis, fall back to D-pad for analog increment/decrement
+ if ((ITEM_ID_INVALID == xaxis) || (ITEM_ID_INVALID == yaxis))
+ {
+ if (ITEM_ID_INVALID != leftswitch)
+ {
+ input_seq const leftseq(make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, leftswitch));
+ assignments.emplace_back(IPT_PADDLE, SEQ_TYPE_DECREMENT, leftseq);
+ assignments.emplace_back(IPT_POSITIONAL, SEQ_TYPE_DECREMENT, leftseq);
+ assignments.emplace_back(IPT_DIAL, SEQ_TYPE_DECREMENT, leftseq);
+ assignments.emplace_back(IPT_TRACKBALL_X, SEQ_TYPE_DECREMENT, leftseq);
+ assignments.emplace_back(IPT_AD_STICK_X, SEQ_TYPE_DECREMENT, leftseq);
+ assignments.emplace_back(IPT_LIGHTGUN_X, SEQ_TYPE_DECREMENT, leftseq);
+ }
+ if (ITEM_ID_INVALID != rightswitch)
+ {
+ input_seq const rightseq(make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, rightswitch));
+ assignments.emplace_back(IPT_PADDLE, SEQ_TYPE_INCREMENT, rightseq);
+ assignments.emplace_back(IPT_POSITIONAL, SEQ_TYPE_INCREMENT, rightseq);
+ assignments.emplace_back(IPT_DIAL, SEQ_TYPE_INCREMENT, rightseq);
+ assignments.emplace_back(IPT_TRACKBALL_X, SEQ_TYPE_INCREMENT, rightseq);
+ assignments.emplace_back(IPT_AD_STICK_X, SEQ_TYPE_INCREMENT, rightseq);
+ assignments.emplace_back(IPT_LIGHTGUN_X, SEQ_TYPE_INCREMENT, rightseq);
+ }
+ if (ITEM_ID_INVALID != upswitch)
+ {
+ input_seq const upseq(make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, upswitch));
+ assignments.emplace_back(IPT_PADDLE_V, SEQ_TYPE_DECREMENT, upseq);
+ assignments.emplace_back(IPT_POSITIONAL_V, SEQ_TYPE_DECREMENT, upseq);
+ assignments.emplace_back(IPT_DIAL_V, SEQ_TYPE_DECREMENT, upseq);
+ assignments.emplace_back(IPT_TRACKBALL_Y, SEQ_TYPE_DECREMENT, upseq);
+ assignments.emplace_back(IPT_AD_STICK_Y, SEQ_TYPE_DECREMENT, upseq);
+ assignments.emplace_back(IPT_LIGHTGUN_Y, SEQ_TYPE_DECREMENT, upseq);
+ }
+ if (ITEM_ID_INVALID != downswitch)
+ {
+ input_seq const downseq(make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, downswitch));
+ assignments.emplace_back(IPT_PADDLE_V, SEQ_TYPE_INCREMENT, downseq);
+ assignments.emplace_back(IPT_POSITIONAL_V, SEQ_TYPE_INCREMENT, downseq);
+ assignments.emplace_back(IPT_DIAL_V, SEQ_TYPE_INCREMENT, downseq);
+ assignments.emplace_back(IPT_TRACKBALL_Y, SEQ_TYPE_INCREMENT, downseq);
+ assignments.emplace_back(IPT_AD_STICK_Y, SEQ_TYPE_INCREMENT, downseq);
+ assignments.emplace_back(IPT_LIGHTGUN_Y, SEQ_TYPE_INCREMENT, downseq);
+ }
+ }
+}
+
+
+void joystick_assignment_helper::add_twin_stick_assignments(
+ input_device::assignment_vector &assignments,
+ input_item_id leftx,
+ input_item_id lefty,
+ input_item_id rightx,
+ input_item_id righty,
+ input_item_id leftleft,
+ input_item_id leftright,
+ input_item_id leftup,
+ input_item_id leftdown,
+ input_item_id rightleft,
+ input_item_id rightright,
+ input_item_id rightup,
+ input_item_id rightdown)
+{
+ // we'll add these at the end if they aren't empty
+ input_seq leftleftseq, leftrightseq, leftupseq, leftdownseq;
+ input_seq rightleftseq, rightrightseq, rightupseq, rightdownseq;
+
+ // only use axes if there are at least two axes in the same orientation
+ bool const useaxes =
+ ((ITEM_ID_INVALID != leftx) && (ITEM_ID_INVALID != rightx)) ||
+ ((ITEM_ID_INVALID != lefty) && (ITEM_ID_INVALID != righty));
+ if (useaxes)
+ {
+ // left stick
+ if (ITEM_ID_INVALID != leftx)
+ {
+ leftleftseq += make_code(
+ ITEM_CLASS_SWITCH,
+ (ITEM_ID_XAXIS == leftx) ? ITEM_MODIFIER_LEFT : ITEM_MODIFIER_NEG,
+ leftx);
+ leftrightseq += make_code(
+ ITEM_CLASS_SWITCH,
+ (ITEM_ID_XAXIS == leftx) ? ITEM_MODIFIER_RIGHT : ITEM_MODIFIER_POS,
+ leftx);
+ }
+ if (ITEM_ID_INVALID != lefty)
+ {
+ leftupseq += make_code(
+ ITEM_CLASS_SWITCH,
+ (ITEM_ID_YAXIS == lefty) ? ITEM_MODIFIER_UP : ITEM_MODIFIER_NEG,
+ lefty);
+ leftdownseq += make_code(
+ ITEM_CLASS_SWITCH,
+ (ITEM_ID_YAXIS == lefty) ? ITEM_MODIFIER_DOWN : ITEM_MODIFIER_POS,
+ lefty);
+ }
+
+ // right stick
+ if (ITEM_ID_INVALID != rightx)
+ {
+ rightleftseq += make_code(
+ ITEM_CLASS_SWITCH,
+ (ITEM_ID_XAXIS == rightx) ? ITEM_MODIFIER_LEFT : ITEM_MODIFIER_NEG,
+ rightx);
+ rightrightseq += make_code(
+ ITEM_CLASS_SWITCH,
+ (ITEM_ID_XAXIS == rightx) ? ITEM_MODIFIER_RIGHT : ITEM_MODIFIER_POS,
+ rightx);
+ }
+ if (ITEM_ID_INVALID != righty)
+ {
+ rightupseq += make_code(
+ ITEM_CLASS_SWITCH,
+ (ITEM_ID_YAXIS == righty) ? ITEM_MODIFIER_UP : ITEM_MODIFIER_NEG,
+ righty);
+ rightdownseq += make_code(
+ ITEM_CLASS_SWITCH,
+ (ITEM_ID_YAXIS == righty) ? ITEM_MODIFIER_DOWN : ITEM_MODIFIER_POS,
+ righty);
+ }
+ }
+
+ // only use switches if we have at least one pair of matching opposing directions
+ bool const lefth = (ITEM_ID_INVALID != leftleft) && (ITEM_ID_INVALID != leftright);
+ bool const leftv = (ITEM_ID_INVALID != leftup) && (ITEM_ID_INVALID != leftdown);
+ bool const righth = (ITEM_ID_INVALID != rightleft) && (ITEM_ID_INVALID != rightright);
+ bool const rightv = (ITEM_ID_INVALID != rightup) && (ITEM_ID_INVALID != rightdown);
+ if ((lefth && righth) || (leftv && rightv))
+ {
+ // left stick
+ if (ITEM_ID_INVALID != leftleft)
+ {
+ if (!leftleftseq.empty())
+ leftleftseq += input_seq::or_code;
+ leftleftseq += make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, leftleft);
+ }
+ if (ITEM_ID_INVALID != leftright)
+ {
+ if (!leftrightseq.empty())
+ leftrightseq += input_seq::or_code;
+ leftrightseq += make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, leftright);
+ }
+ if (ITEM_ID_INVALID != leftup)
+ {
+ if (!leftupseq.empty())
+ leftupseq += input_seq::or_code;
+ leftupseq += make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, leftup);
+ }
+ if (ITEM_ID_INVALID != leftdown)
+ {
+ if (!leftdownseq.empty())
+ leftdownseq += input_seq::or_code;
+ leftdownseq += make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, leftdown);
+ }
+
+ // right stick
+ if (ITEM_ID_INVALID != rightleft)
+ {
+ if (!rightleftseq.empty())
+ rightleftseq += input_seq::or_code;
+ rightleftseq += make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, rightleft);
+ }
+ if (ITEM_ID_INVALID != rightright)
+ {
+ if (!rightrightseq.empty())
+ rightrightseq += input_seq::or_code;
+ rightrightseq += make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, rightright);
+ }
+ if (ITEM_ID_INVALID != rightup)
+ {
+ if (!rightupseq.empty())
+ rightupseq += input_seq::or_code;
+ rightupseq += make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, rightup);
+ }
+ if (ITEM_ID_INVALID != rightdown)
+ {
+ if (!rightdownseq.empty())
+ rightdownseq += input_seq::or_code;
+ rightdownseq += make_code(ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, rightdown);
+ }
+ }
+
+ // now add collected assignments
+ if (!leftleftseq.empty())
+ assignments.emplace_back(IPT_JOYSTICKLEFT_LEFT, SEQ_TYPE_STANDARD, leftleftseq);
+ if (!leftrightseq.empty())
+ assignments.emplace_back(IPT_JOYSTICKLEFT_RIGHT, SEQ_TYPE_STANDARD, leftrightseq);
+ if (!leftupseq.empty())
+ assignments.emplace_back(IPT_JOYSTICKLEFT_UP, SEQ_TYPE_STANDARD, leftupseq);
+ if (!leftdownseq.empty())
+ assignments.emplace_back(IPT_JOYSTICKLEFT_DOWN, SEQ_TYPE_STANDARD, leftdownseq);
+ if (!rightleftseq.empty())
+ assignments.emplace_back(IPT_JOYSTICKRIGHT_LEFT, SEQ_TYPE_STANDARD, rightleftseq);
+ if (!rightrightseq.empty())
+ assignments.emplace_back(IPT_JOYSTICKRIGHT_RIGHT, SEQ_TYPE_STANDARD, rightrightseq);
+ if (!rightupseq.empty())
+ assignments.emplace_back(IPT_JOYSTICKRIGHT_UP, SEQ_TYPE_STANDARD, rightupseq);
+ if (!rightdownseq.empty())
+ assignments.emplace_back(IPT_JOYSTICKRIGHT_DOWN, SEQ_TYPE_STANDARD, rightdownseq);
+}
+
+
+void joystick_assignment_helper::choose_primary_stick(
+ input_item_id (&stickaxes)[2][2],
+ input_item_id leftx,
+ input_item_id lefty,
+ input_item_id rightx,
+ input_item_id righty)
+{
+ if ((ITEM_ID_INVALID != leftx) && (ITEM_ID_INVALID != lefty))
+ {
+ // left stick has both axes, make it primary
+ stickaxes[0][0] = leftx;
+ stickaxes[0][1] = lefty;
+ stickaxes[1][0] = rightx;
+ stickaxes[1][1] = righty;
+ }
+ else if ((ITEM_ID_INVALID != rightx) && (ITEM_ID_INVALID != righty))
+ {
+ // right stick has both axes, make it primary
+ stickaxes[0][0] = rightx;
+ stickaxes[0][1] = righty;
+ stickaxes[1][0] = leftx;
+ stickaxes[1][1] = lefty;
+ }
+ else if (ITEM_ID_INVALID != leftx)
+ {
+ // degenerate case - left X and possibly right X or Y
+ stickaxes[0][0] = leftx;
+ stickaxes[0][1] = righty;
+ stickaxes[1][0] = rightx;
+ stickaxes[1][1] = ITEM_ID_INVALID;
+ }
+ else if ((ITEM_ID_INVALID != rightx) || (ITEM_ID_INVALID != lefty))
+ {
+ // degenerate case - right X and possibly left Y, or one or two Y axes
+ stickaxes[0][0] = rightx;
+ stickaxes[0][1] = lefty;
+ stickaxes[1][0] = ITEM_ID_INVALID;
+ stickaxes[1][1] = righty;
+ }
+ else
+ {
+ // degenerate case - one Y axis at most
+ stickaxes[0][0] = ITEM_ID_INVALID;
+ stickaxes[0][1] = righty;
+ stickaxes[1][0] = ITEM_ID_INVALID;
+ stickaxes[1][1] = ITEM_ID_INVALID;
+ }
+}
+
+} // namespace osd