From 8edc01930774e3190144a9433ff45e5ba4160ae5 Mon Sep 17 00:00:00 2001 From: rdb Date: Sun, 16 Sep 2018 15:12:17 +0200 Subject: [PATCH] device: overhaul InputDevice API: - Rename "controls" terminology for analog inputs to "axes" - Change some naming of accessors - Unexpose methods where they are available as properties - Add serial_number field - Put battery levels under a "battery" field --- panda/src/device/analogNode.I | 6 +- panda/src/device/analogNode.cxx | 16 +- panda/src/device/buttonNode.I | 4 +- panda/src/device/clientAnalogDevice.cxx | 2 +- panda/src/device/evdevInputDevice.cxx | 30 ++-- panda/src/device/evdevInputDevice.h | 4 +- panda/src/device/inputDevice.I | 185 ++++++++++------------ panda/src/device/inputDevice.cxx | 131 ++++++++-------- panda/src/device/inputDevice.h | 187 ++++++++++++----------- panda/src/device/inputDeviceManager.h | 3 - panda/src/device/inputDeviceNode.cxx | 18 +++ panda/src/device/inputDeviceNode.h | 14 +- panda/src/device/ioKitInputDevice.cxx | 8 +- panda/src/device/linuxJoystickDevice.cxx | 48 +++--- panda/src/device/winRawInputDevice.cxx | 20 +-- panda/src/device/winRawInputDevice.h | 12 +- panda/src/device/xInputDevice.cxx | 143 ++++++++--------- panda/src/vrpn/vrpnAnalog.cxx | 8 +- panda/src/vrpn/vrpnTracker.cxx | 24 +-- 19 files changed, 439 insertions(+), 424 deletions(-) diff --git a/panda/src/device/analogNode.I b/panda/src/device/analogNode.I index 5fd3543c07..a61ff00b43 100644 --- a/panda/src/device/analogNode.I +++ b/panda/src/device/analogNode.I @@ -35,7 +35,7 @@ is_valid() const { */ INLINE int AnalogNode:: get_num_controls() const { - return _analog->get_num_controls(); + return _analog->get_num_axes(); } /** @@ -45,7 +45,7 @@ get_num_controls() const { */ INLINE double AnalogNode:: get_control_state(int index) const { - return _analog->get_control_state(index); + return _analog->get_axis_value(index); } /** @@ -54,7 +54,7 @@ get_control_state(int index) const { */ INLINE bool AnalogNode:: is_control_known(int index) const { - return _analog->is_control_known(index); + return _analog->is_axis_known(index); } /** diff --git a/panda/src/device/analogNode.cxx b/panda/src/device/analogNode.cxx index fffdadd579..6f9b42811c 100644 --- a/panda/src/device/analogNode.cxx +++ b/panda/src/device/analogNode.cxx @@ -81,7 +81,7 @@ write(std::ostream &out, int indent_level) const { DataNode::write(out, indent_level); if (_analog != nullptr) { - _analog->write_controls(out, indent_level + 2); + _analog->write_axes(out, indent_level + 2); } } @@ -101,12 +101,14 @@ do_transmit_data(DataGraphTraverser *, const DataNodeTransmit &, LPoint2 out(0.0f, 0.0f); for (int i = 0; i < max_outputs; i++) { - if (_outputs[i]._index >= 0 && - _analog->is_control_known(_outputs[i]._index)) { - if (_outputs[i]._flip) { - out[i] = -_analog->get_control_state(_outputs[i]._index); - } else { - out[i] = _analog->get_control_state(_outputs[i]._index); + if (_outputs[i]._index >= 0) { + InputDevice::AxisState state = _analog->get_axis(_outputs[i]._index); + if (state.known) { + if (_outputs[i]._flip) { + out[i] = -state.value; + } else { + out[i] = state.value; + } } } } diff --git a/panda/src/device/buttonNode.I b/panda/src/device/buttonNode.I index 1debd87ff7..013f66e41d 100644 --- a/panda/src/device/buttonNode.I +++ b/panda/src/device/buttonNode.I @@ -43,7 +43,7 @@ get_num_buttons() const { */ INLINE void ButtonNode:: set_button_map(int index, ButtonHandle button) { - _device->set_button_map(index, button); + _device->map_button(index, button); } /** @@ -62,7 +62,7 @@ get_button_map(int index) const { */ INLINE bool ButtonNode:: get_button_state(int index) const { - return _device->get_button_state(index); + return _device->is_button_pressed(index); } /** diff --git a/panda/src/device/clientAnalogDevice.cxx b/panda/src/device/clientAnalogDevice.cxx index 71fadfeb99..f9eef0f884 100644 --- a/panda/src/device/clientAnalogDevice.cxx +++ b/panda/src/device/clientAnalogDevice.cxx @@ -23,5 +23,5 @@ TypeHandle ClientAnalogDevice::_type_handle; void ClientAnalogDevice:: write(std::ostream &out, int indent_level) const { indent(out, indent_level) << get_type() << " " << get_name() << ":\n"; - write_controls(out, indent_level + 2); + write_axes(out, indent_level + 2); } diff --git a/panda/src/device/evdevInputDevice.cxx b/panda/src/device/evdevInputDevice.cxx index 72085f1ed9..4fdd451cd5 100644 --- a/panda/src/device/evdevInputDevice.cxx +++ b/panda/src/device/evdevInputDevice.cxx @@ -392,10 +392,10 @@ init_device() { } if (test_bit(i, states)) { - button.state = S_down; + button._state = S_down; all_values_zero = false; } else { - button.state = S_up; + button._state = S_up; } if (button.handle == GamepadButton::dpad_left()) { emulate_dpad = false; @@ -415,7 +415,7 @@ init_device() { } if (has_axes) { - _control_indices.resize(num_bits, -1); + _axis_indices.resize(num_bits, -1); for (int i = 0; i < num_bits; ++i) { if (test_bit(i, axes)) { @@ -545,12 +545,12 @@ init_device() { std::swap(absinfo.maximum, absinfo.minimum); } if (axis == Axis::throttle && (quirks & QB_centered_throttle) != 0) { - index = add_control(axis, absinfo.maximum, absinfo.minimum, true); + index = add_axis(axis, absinfo.maximum, absinfo.minimum, true); } else { - index = add_control(axis, absinfo.minimum, absinfo.maximum); + index = add_axis(axis, absinfo.minimum, absinfo.maximum); } - control_changed(index, absinfo.value); - _control_indices[i] = index; + axis_changed(index, absinfo.value); + _axis_indices[i] = index; if (absinfo.value != 0) { all_values_zero = false; @@ -583,9 +583,9 @@ init_device() { if (_ltrigger_code >= 0 && _rtrigger_code >= 0 && !have_analog_triggers) { // Emulate analog triggers. - _ltrigger_control = (int)_controls.size(); - add_control(Axis::left_trigger, 0, 1, false); - add_control(Axis::right_trigger, 0, 1, false); + _ltrigger_axis = (int)_axes.size(); + add_axis(Axis::left_trigger, 0, 1, false); + add_axis(Axis::right_trigger, 0, 1, false); } else { _ltrigger_code = -1; _rtrigger_code = -1; @@ -709,10 +709,10 @@ process_events() { button_changed(_dpad_up_button, events[i].value < 0); button_changed(_dpad_up_button+1, events[i].value > 0); } - nassertd(code >= 0 && (size_t)code < _control_indices.size()) break; - index = _control_indices[code]; + nassertd(code >= 0 && (size_t)code < _axis_indices.size()) break; + index = _axis_indices[code]; if (index >= 0) { - control_changed(index, events[i].value); + axis_changed(index, events[i].value); } break; @@ -723,9 +723,9 @@ process_events() { button_changed(index, events[i].value != 0); } if (code == _ltrigger_code) { - control_changed(_ltrigger_control, events[i].value); + axis_changed(_ltrigger_axis, events[i].value); } else if (code == _rtrigger_code) { - control_changed(_ltrigger_control + 1, events[i].value); + axis_changed(_ltrigger_axis + 1, events[i].value); } break; diff --git a/panda/src/device/evdevInputDevice.h b/panda/src/device/evdevInputDevice.h index d82ba5f980..239ba78616 100644 --- a/panda/src/device/evdevInputDevice.h +++ b/panda/src/device/evdevInputDevice.h @@ -49,7 +49,7 @@ private: int _ff_strong; int _ff_weak; - pvector _control_indices; + pvector _axis_indices; pvector _button_indices; // These are used for D-pad emulation. @@ -59,7 +59,7 @@ private: int _dpad_up_button; // This is used for axis emulation. - int _ltrigger_control; + int _ltrigger_axis; int _ltrigger_code; int _rtrigger_code; diff --git a/panda/src/device/inputDevice.I b/panda/src/device/inputDevice.I index a8eb5a127b..bcddc5cf52 100644 --- a/panda/src/device/inputDevice.I +++ b/panda/src/device/inputDevice.I @@ -24,9 +24,7 @@ InputDevice() : _product_id(0), _is_connected(false), _event_sequence(0), - _enable_pointer_events(false), - _battery_level(-1), - _max_battery_level(-1) + _enable_pointer_events(false) { _button_events = new ButtonEventList; } @@ -50,6 +48,16 @@ get_manufacturer() const { return _manufacturer; } +/** + * Returns a string containing the serial number of the device, if this + * information is known. + */ +INLINE std::string InputDevice:: +get_serial_number() const { + LightMutexHolder holder(_lock); + return _serial_number; +} + /** * Returns a string containing the USB vendor ID of the device, if this * information is known. @@ -160,23 +168,12 @@ get_tracker() const { /** * Returns a rough indication of the battery level, ranging from 0 (completely - * empty battery) to the number reported by get_max_battery_level(), which - * represents a full battery. If this information is not known, returns -1. + * empty battery) to the indicated max_level value. */ -INLINE short InputDevice:: -get_battery_level() const { +INLINE InputDevice::BatteryData InputDevice:: +get_battery() const { LightMutexHolder holder(_lock); - return _battery_level; -} - -/** - * Returns the maximum value that may be reported by get_battery_level(), - * representing a full battery. Returns -1 if no battery information is known. - */ -INLINE short InputDevice:: -get_max_battery_level() const { - LightMutexHolder holder(_lock); - return _max_battery_level; + return _battery_data; } /** @@ -202,7 +199,7 @@ get_num_buttons() const { * generate ButtonEvents when the buttons change state. */ INLINE void InputDevice:: -set_button_map(size_t index, ButtonHandle button) { +map_button(size_t index, ButtonHandle button) { LightMutexHolder holder(_lock); if (index >= _buttons.size()) { _buttons.resize(index + 1, ButtonState()); @@ -213,7 +210,7 @@ set_button_map(size_t index, ButtonHandle button) { /** * Returns the ButtonHandle that was previously associated with the given index - * number by a call to set_button_map(), or ButtonHandle::none() if no button + * number by a call to map_button(), or ButtonHandle::none() if no button * was associated. */ INLINE ButtonHandle InputDevice:: @@ -230,9 +227,9 @@ get_button_map(size_t index) const { * currently known to be down, or false if it is up or unknown. */ INLINE bool InputDevice:: -get_button_state(size_t index) const { +is_button_pressed(size_t index) const { if (index < _buttons.size()) { - return (_buttons[index].state == S_down); + return (_buttons[index]._state == S_down); } else { return false; } @@ -245,14 +242,14 @@ get_button_state(size_t index) const { INLINE bool InputDevice:: is_button_known(size_t index) const { if (index < _buttons.size()) { - return _buttons[index].state != S_unknown; + return _buttons[index]._state != S_unknown; } else { return false; } } /** - * Returns the ButtonState that is set at the given index, or throw an assection + * Returns the ButtonState that is set at the given index, or throw an assert * if the index was not found in the list. */ INLINE InputDevice::ButtonState InputDevice:: @@ -261,13 +258,13 @@ get_button(size_t index) const { return _buttons[index]; } else { device_cat.error() - << "Index " << index << " was not found in the controls list\n"; + << "Index " << index << " was not found in the axes list\n"; return ButtonState(); } } /** - * Returns the first ButtonState found with the given axis, or throw an assection + * Returns the first ButtonState found with the given axis, or throw an assert * if the button handle was not found in the list. */ INLINE InputDevice::ButtonState InputDevice:: @@ -278,103 +275,89 @@ find_button(ButtonHandle handle) const { } } device_cat.error() - << "Handle " << handle.get_name() << " was not found in the controls list\n"; + << "Handle " << handle.get_name() << " was not found in the axes list\n"; return ButtonState(); } /** - * Returns the number of analog controls known to the InputDevice. This number - * may change as more controls are discovered. + * Returns the number of analog axes known to the InputDevice. This number + * may change as more axes are discovered. */ INLINE size_t InputDevice:: -get_num_controls() const { - return _controls.size(); +get_num_axes() const { + return _axes.size(); } /** - * Associates the indicated Axis with the control of the indicated index + * Associates the indicated Axis with the axis of the indicated index * number. Pass Axis::none to turn off any association. * * It is not necessary to call this if you simply want to query the state of - * the various controls by index number. + * the various axes by index number. */ INLINE void InputDevice:: -set_control_map(size_t index, InputDevice::Axis axis) { +map_axis(size_t index, InputDevice::Axis axis) { LightMutexHolder holder(_lock); - if (index >= _controls.size()) { - _controls.resize(index + 1, AnalogState()); + if (index >= _axes.size()) { + _axes.resize(index + 1, AxisState()); } - _controls[index].axis = axis; + _axes[index].axis = axis; } /** - * Returns the Axis that was previously associated with the given index - * number by a call to set_control_map(), or Axis::none if no control was - * associated. - */ -INLINE InputDevice::Axis InputDevice:: -get_control_map(size_t index) const { - if (index < _controls.size()) { - return _controls[index].axis; - } else { - return Axis::none; - } -} - -/** - * Returns the current position of indicated analog control (identified by its - * index number), or 0.0 if the control is unknown. The normal range of a - * single control is -1.0 to 1.0. + * Returns the current position of indicated analog axis (identified by its + * index number), or 0.0 if the axis is unknown. The normal range of a + * single axis is -1.0 to 1.0. */ INLINE double InputDevice:: -get_control_state(size_t index) const { - if (index < _controls.size()) { - return _controls[index].state; +get_axis_value(size_t index) const { + if (index < _axes.size()) { + return _axes[index].value; } else { return 0.0; } } /** - * Returns the AnalogAxis that is set at the given index, or throw an assection + * Returns the axis state that is set at the given index, or throw an assert * if the index was not found in the list. */ -INLINE InputDevice::AnalogState InputDevice:: -get_control(size_t index) const { - if (index < _controls.size()) { - return _controls[index]; +INLINE InputDevice::AxisState InputDevice:: +get_axis(size_t index) const { + if (index < _axes.size()) { + return _axes[index]; } else { device_cat.error() - << "Index " << index<< " was not found in the controls list\n"; - return AnalogState(); + << "Index " << index << " was not found in the axes list\n"; + return AxisState(); } } /** - * Returns the first AnalogAxis found with the given axis, or throw an assection + * Returns the first AnalogAxis found with the given axis, or throw an assert * if the axis was not found in the list. */ -INLINE InputDevice::AnalogState InputDevice:: -find_control(InputDevice::Axis axis) const { - for (size_t i = 0; i < _controls.size(); ++i) { - if (_controls[i].axis == axis) { - return _controls[i]; +INLINE InputDevice::AxisState InputDevice:: +find_axis(InputDevice::Axis axis) const { + for (size_t i = 0; i < _axes.size(); ++i) { + if (_axes[i].axis == axis) { + return _axes[i]; } } device_cat.error() - << "Axis " << axis << " was not found in the controls list\n"; - return AnalogState(); + << "Axis " << axis << " was not found in the axes list\n"; + return AxisState(); } /** - * Returns true if the state of the indicated analog control is known, or false - * if we have never heard anything about this particular control. + * Returns true if the state of the indicated analog axis is known, or false + * if we have never heard anything about this particular axis. */ INLINE bool InputDevice:: -is_control_known(size_t index) const { - if (index < _controls.size()) { - return _controls[index].known; +is_axis_known(size_t index) const { + if (index < _axes.size()) { + return _axes[index].known; } else { return false; } @@ -382,8 +365,8 @@ is_control_known(size_t index) const { /** * Sets the strength of the vibration effect, if supported. The values are - * clamped to 0-1 range. The first value controls the low-frequency rumble - * motor, whereas the second controls the high-frequency motor, if present. + * clamped to 0-1 range. The first value axes the low-frequency rumble + * motor, whereas the second axes the high-frequency motor, if present. */ INLINE void InputDevice:: set_vibration(double strong, double weak) { @@ -420,36 +403,26 @@ set_connected(bool connected) { _is_connected = connected; } -/** - * - */ -INLINE bool InputDevice:: -operator == (const InputDevice &) const { - return true; -} - -/** - * - */ -INLINE bool InputDevice:: -operator != (const InputDevice &) const { - return false; -} - -/** - * - */ -INLINE bool InputDevice:: -operator < (const InputDevice &) const { - return false; -} - /** * */ INLINE InputDevice::ButtonState:: ButtonState(ButtonHandle handle) : - handle(handle), - state(S_unknown) -{ + handle(handle) { +} + +/** + * True if the button state is currently known. + */ +ALWAYS_INLINE bool InputDevice::ButtonState:: +is_known() const { + return (_state != S_unknown); +} + +/** + * True if the button is currently known to be pressed. + */ +ALWAYS_INLINE bool InputDevice::ButtonState:: +is_pressed() const { + return (_state == S_down); } diff --git a/panda/src/device/inputDevice.cxx b/panda/src/device/inputDevice.cxx index e24cd9a0df..aedfeb8222 100644 --- a/panda/src/device/inputDevice.cxx +++ b/panda/src/device/inputDevice.cxx @@ -32,8 +32,6 @@ InputDevice(const std::string &name, DeviceClass dev_class, int flags) : _is_connected(true), _event_sequence(0), _enable_pointer_events(false), - _battery_level(-1), - _max_battery_level(-1), _lock("InputDevice") { _button_events = new ButtonEventList; @@ -119,13 +117,22 @@ get_pointer_events() { return result; } - /** - * Called by the implementation to add a new known control. + * Called by the implementation to add a new known button. */ int InputDevice:: -add_control(Axis axis, int minimum, int maximum, bool centered) { - AnalogState state; +add_button(ButtonHandle button) { + int index = (int)_buttons.size(); + _buttons.push_back(ButtonState(button)); + return index; +} + +/** + * Called by the implementation to add a new known axis. + */ +int InputDevice:: +add_axis(Axis axis, int minimum, int maximum, bool centered) { + AxisState state; state.axis = axis; if (centered) { // Centered, eg. for sticks. @@ -136,17 +143,17 @@ add_control(Axis axis, int minimum, int maximum, bool centered) { state._scale = 1.0 / maximum; state._bias = 0.0; } - int index = (int)_controls.size(); - _controls.push_back(state); + int index = (int)_axes.size(); + _axes.push_back(state); return index; } /** - * Called by the implementation to add a new known control. This version - * tries to guess whether the control is centered or not. + * Called by the implementation to add a new known axis. This version tries + * to guess whether the axis is centered or not. */ int InputDevice:: -add_control(Axis axis, int minimum, int maximum) { +add_axis(Axis axis, int minimum, int maximum) { bool centered = (minimum < 0) || axis == Axis::x || axis == Axis::y @@ -160,7 +167,7 @@ add_control(Axis axis, int minimum, int maximum) { || axis == Axis::right_y || axis == Axis::wheel || axis == Axis::rudder; - return add_control(axis, minimum, maximum, centered); + return add_axis(axis, minimum, maximum, centered); } /** @@ -246,10 +253,10 @@ button_changed(int index, bool down) { } State new_state = down ? S_down : S_up; - if (_buttons[index].state == new_state) { + if (_buttons[index]._state == new_state) { return; } - _buttons[index].state = new_state; + _buttons[index]._state = new_state; ButtonHandle handle = _buttons[index].handle; @@ -272,65 +279,67 @@ button_changed(int index, bool down) { /** * Sets the state of the indicated analog index. The caller should ensure that * the lock is held while this call is made. This should be a number in the - * range -1.0 to 1.0, representing the current position of the control within - * its total range of movement. + * range -1.0 to 1.0, representing the current position of the axis within its + * total range of movement. */ void InputDevice:: -set_control_state(int index, double state) { - nassertv(_lock.debug_is_locked()); +set_axis_value(int index, double value) { + LightMutexHolder holder(_lock); + nassertv(index >= 0); - if (index >= (int)_controls.size()) { - _controls.resize(index + 1, AnalogState()); + if ((size_t)index >= _axes.size()) { + _axes.resize((size_t)index + 1u, AxisState()); } - if (device_cat.is_spam() && _controls[index].state != state) { + if (device_cat.is_spam() && _axes[index].value != value) { device_cat.spam() - << "Changed control " << index; + << "Changed axis " << index; - if (_controls[index].axis != Axis::none) { - device_cat.spam(false) << " (" << _controls[index].axis << ")"; + if (_axes[index].axis != Axis::none) { + device_cat.spam(false) << " (" << _axes[index].axis << ")"; } - device_cat.spam(false) << " to " << state << "\n"; + device_cat.spam(false) << " to " << value << "\n"; } - _controls[index].state = state; - _controls[index].known = true; + _axes[index].value = value; + _axes[index].known = true; } /** - * Like set_control_state, but instead passes a raw, unscaled value. + * Called by the implementation during do_poll to indicate that the indicated + * axis has received a new raw value. Assumes the lock is held. */ void InputDevice:: -control_changed(int index, int state) { +axis_changed(int index, int state) { nassertv(_lock.debug_is_locked()); nassertv(index >= 0); - if (index >= (int)_controls.size()) { - _controls.resize(index + 1, AnalogState()); + if ((size_t)index >= _axes.size()) { + _axes.resize((size_t)index + 1u, AxisState()); } - double new_state = fma((double)state, _controls[index]._scale, _controls[index]._bias); + double value = fma((double)state, _axes[index]._scale, _axes[index]._bias); - if (device_cat.is_spam() && _controls[index].state != new_state) { + if (device_cat.is_spam() && !IS_NEARLY_EQUAL(_axes[index].value, value)) { device_cat.spam() - << "Changed control " << index; + << "Changed axis " << index; - if (_controls[index].axis != Axis::none) { - device_cat.spam(false) << " (" << _controls[index].axis << ")"; + if (_axes[index].axis != Axis::none) { + device_cat.spam(false) << " (" << _axes[index].axis << ")"; } - device_cat.spam(false) << " to " << new_state << " (raw value " << state << ")\n"; + device_cat.spam(false) << " to " << value << " (raw value " << state << ")\n"; } - _controls[index].state = new_state; - _controls[index].known = true; + _axes[index].value = value; + _axes[index].known = true; } /** * Records that a tracker movement has taken place. */ void InputDevice:: -set_tracker(const LPoint3 &pos, const LOrientation &orient, double time) { +tracker_changed(const LPoint3 &pos, const LOrientation &orient, double time) { nassertv(_lock.debug_is_locked()); _tracker_data.set_pos(pos); @@ -364,11 +373,9 @@ output(std::ostream &out) const { } } - if (_controls.size() > 0) { - out << ", " << _controls.size() << " control"; - if (_controls.size() != 1) { - out.put('s'); - } + if (_axes.size() > 0) { + out << ", " << _axes.size() << " ax" + << (_axes.size() != 1 ? 'e' : 'i') << 's'; } if (_flags & IDF_has_pointer) { @@ -386,13 +393,13 @@ output(std::ostream &out) const { if (_flags & IDF_has_battery) { out << ", battery"; - if (_battery_level > 0 && _max_battery_level > 0) { + if (_battery_data.level > 0 && _battery_data.max_level > 0) { out << " ["; short i = 0; - for (; i < _battery_level; ++i) { + for (; i < _battery_data.level; ++i) { out << '='; } - for (; i < _max_battery_level; ++i) { + for (; i < _battery_data.max_level; ++i) { out << ' '; } out << ']'; @@ -411,13 +418,13 @@ output_buttons(std::ostream &out) const { Buttons::const_iterator bi; for (bi = _buttons.begin(); bi != _buttons.end(); ++bi) { const ButtonState &state = (*bi); - if (state.state != S_unknown) { + if (state.is_known()) { if (any_buttons) { out << ", "; } any_buttons = true; out << (int)(bi - _buttons.begin()) << "="; - if (state.state == S_up) { + if (state._state == S_up) { out << "up"; } else { out << "down"; @@ -439,7 +446,7 @@ write_buttons(std::ostream &out, int indent_level) const { Buttons::const_iterator bi; for (bi = _buttons.begin(); bi != _buttons.end(); ++bi) { const ButtonState &state = (*bi); - if (state.state != S_unknown) { + if (state.is_known()) { any_buttons = true; indent(out, indent_level) @@ -449,7 +456,7 @@ write_buttons(std::ostream &out, int indent_level) const { out << "(" << state.handle << ") "; } - if (state.state == S_up) { + if (state._state == S_up) { out << "up"; } else { out << "down"; @@ -465,27 +472,27 @@ write_buttons(std::ostream &out, int indent_level) const { } /** - * Writes a multi-line description of the current analog control states. + * Writes a multi-line description of the current analog axis states. */ void InputDevice:: -write_controls(std::ostream &out, int indent_level) const { +write_axes(std::ostream &out, int indent_level) const { LightMutexHolder holder(_lock); - bool any_controls = false; - Controls::const_iterator ai; - for (ai = _controls.begin(); ai != _controls.end(); ++ai) { - const AnalogState &state = (*ai); + bool any_axis = false; + Axes::const_iterator ai; + for (ai = _axes.begin(); ai != _axes.end(); ++ai) { + const AxisState &state = (*ai); if (state.known) { - any_controls = true; + any_axis = true; indent(out, indent_level) - << (int)(ai - _controls.begin()) << ". " << state.state << "\n"; + << (int)(ai - _axes.begin()) << ". " << state.value << "\n"; } } - if (!any_controls) { + if (!any_axis) { indent(out, indent_level) - << "(no known analog controls)\n"; + << "(no known analog axes)\n"; } } diff --git a/panda/src/device/inputDevice.h b/panda/src/device/inputDevice.h index 77b42b43c0..7e4d4f623b 100644 --- a/panda/src/device/inputDevice.h +++ b/panda/src/device/inputDevice.h @@ -33,12 +33,12 @@ typedef MouseData PointerData; /** * This is a structure representing a single input device. Input devices may - * have zero or more buttons, pointers, or controls associated with them, and + * have zero or more buttons, pointers, or axes associated with them, and * optionally a motion tracker. * * These devices are brought under a common interface because there is such a * large range of devices out there that may support any number of these types - * of controls, we couldn't even begin to cover them with type-specific + * of axes, we couldn't even begin to cover them with type-specific * subclasses. * * Use the various has_() and get_num_() methods to determine information about @@ -85,16 +85,6 @@ PUBLISHED: DC_COUNT, }; -protected: - InputDevice(const std::string &name, DeviceClass dev_class, int flags); - -public: - InputDevice(); - InputDevice(const InputDevice ©); - void operator = (const InputDevice ©); - ~InputDevice(); - -PUBLISHED: enum class Axis { none, @@ -126,19 +116,94 @@ PUBLISHED: brake, }; + enum State { + S_unknown, + S_up, + S_down + }; + + class ButtonState { + public: + constexpr ButtonState() = default; + INLINE ButtonState(ButtonHandle handle); + ALWAYS_INLINE bool is_known() const; + ALWAYS_INLINE bool is_pressed() const; + + PUBLISHED: + MAKE_PROPERTY(known, is_known); + MAKE_PROPERTY(pressed, is_pressed); + + ButtonHandle handle = ButtonHandle::none(); + + public: + State _state = S_unknown; + }; + + class AxisState { + public: + constexpr AxisState() = default; + + PUBLISHED: + Axis axis = Axis::none; + double value = 0.0; + bool known = false; + + public: + double _scale = 1.0; + double _bias = 0.0; + }; + + class BatteryData { + PUBLISHED: + // Ranges from 0 through max_level. + short level = -1; + + // Maximum value of 'level' field. + short max_level = -1; + }; + +protected: + InputDevice(const std::string &name, DeviceClass dev_class, int flags); + +public: + InputDevice(); + InputDevice(const InputDevice ©); + void operator = (const InputDevice ©); + ~InputDevice(); + INLINE std::string get_name() const; INLINE std::string get_manufacturer() const; + INLINE std::string get_serial_number() const; INLINE unsigned short get_vendor_id() const; INLINE unsigned short get_product_id() const; INLINE bool is_connected() const; INLINE DeviceClass get_device_class() const; + INLINE PointerData get_pointer() const; + INLINE TrackerData get_tracker() const; + INLINE BatteryData get_battery() const; + + INLINE size_t get_num_buttons() const; + INLINE ButtonHandle get_button_map(size_t index) const; + INLINE bool is_button_pressed(size_t index) const; + INLINE bool is_button_known(size_t index) const; + INLINE ButtonState get_button(size_t index) const; + + INLINE size_t get_num_axes() const; + INLINE double get_axis_value(size_t index) const; + INLINE bool is_axis_known(size_t index) const; + INLINE AxisState get_axis(size_t index) const; + +PUBLISHED: // The human-readable name of this input device. MAKE_PROPERTY(name, get_name); // The device's manufacturer, or the empty string if not known. MAKE_PROPERTY(manufacturer, get_manufacturer); + // The device's serial number, or the empty string if not known. + MAKE_PROPERTY(serial_number, get_serial_number); + // USB vendor ID of the device, or 0 if not known. MAKE_PROPERTY(vendor_id, get_vendor_id); @@ -159,24 +224,22 @@ PUBLISHED: INLINE bool has_vibration() const; INLINE bool has_battery() const; - INLINE PointerData get_pointer() const; - INLINE TrackerData get_tracker() const; + // Getters for the various types of device data. + MAKE_PROPERTY2(pointer, has_pointer, get_pointer); + MAKE_PROPERTY2(tracker, has_tracker, get_tracker); + MAKE_PROPERTY2(battery, has_battery, get_battery); - INLINE short get_battery_level() const; - INLINE short get_max_battery_level() const; + // Make device buttons and axes iterable + MAKE_SEQ_PROPERTY(buttons, get_num_buttons, get_button); + MAKE_SEQ_PROPERTY(axes, get_num_axes, get_axis); - INLINE size_t get_num_buttons() const; - INLINE void set_button_map(size_t index, ButtonHandle button); - INLINE ButtonHandle get_button_map(size_t index) const; - INLINE bool get_button_state(size_t index) const; - INLINE bool is_button_known(size_t index) const; - - INLINE size_t get_num_controls() const; - INLINE void set_control_map(size_t index, Axis axis); - INLINE Axis get_control_map(size_t index) const; - INLINE double get_control_state(size_t index) const; - INLINE bool is_control_known(size_t index) const; + // Associate buttons/axes with symbolic handles. + INLINE void map_button(size_t index, ButtonHandle handle); + INLINE void map_axis(size_t index, Axis axis); + INLINE ButtonState find_button(ButtonHandle handle) const; + INLINE AxisState find_axis(Axis axis) const; + // Enable rumble force-feedback effects INLINE void set_vibration(double strong, double weak); INLINE void enable_pointer_events(); @@ -194,19 +257,20 @@ PUBLISHED: static std::string format_axis(Axis axis); protected: - // Called during the constructor to add new controls or buttons - int add_control(Axis axis, int minimum, int maximum, bool centered); - int add_control(Axis axis, int minimum, int maximum); + // Called during the constructor to add new axes or buttons + int add_button(ButtonHandle handle); + int add_axis(Axis axis, int minimum, int maximum, bool centered); + int add_axis(Axis axis, int minimum, int maximum); void set_pointer(bool inwin, double x, double y, double time); void set_pointer_out_of_window(double time); void pointer_moved(double x, double y, double time); void button_changed(int index, bool down); - void control_changed(int index, int value); - void set_control_state(int index, double state); + void axis_changed(int index, int value); + void set_axis_value(int index, double state); - void set_tracker(const LPoint3 &pos, const LOrientation &orient, double time); + void tracker_changed(const LPoint3 &pos, const LOrientation &orient, double time); virtual void do_set_vibration(double low, double high); virtual void do_poll(); @@ -214,16 +278,9 @@ protected: public: INLINE void set_connected(bool connected); - // We need these methods to make VC++ happy when we try to - // instantiate a pvector. They don't do - // anything useful. - INLINE bool operator == (const InputDevice &other) const; - INLINE bool operator != (const InputDevice &other) const; - INLINE bool operator < (const InputDevice &other) const; - void output_buttons(std::ostream &out) const; void write_buttons(std::ostream &out, int indent_level) const; - void write_controls(std::ostream &out, int indent_level) const; + void write_axes(std::ostream &out, int indent_level) const; protected: enum InputDeviceFlags { @@ -263,56 +320,14 @@ protected: PT(PointerEventList) _pointer_events; PUBLISHED: - enum State { - S_unknown, - S_up, - S_down - }; - - class ButtonState { - public: - constexpr ButtonState() = default; - INLINE ButtonState(ButtonHandle handle); - - PUBLISHED: - ButtonHandle handle = ButtonHandle::none(); - State state = S_unknown; - }; typedef pvector Buttons; + typedef pvector Axes; Buttons _buttons; + Axes _axes; - class AnalogState { - public: - constexpr AnalogState() = default; - - PUBLISHED: - Axis axis = Axis::none; - double state = 0.0; - bool known = false; - - public: - double _scale = 1.0; - double _bias = 0.0; - }; - typedef pvector Controls; - Controls _controls; - - short _battery_level; - short _max_battery_level; - + BatteryData _battery_data; TrackerData _tracker_data; - - INLINE ButtonState get_button(size_t index) const; - INLINE ButtonState find_button(ButtonHandle handle) const; - - INLINE AnalogState get_control(size_t index) const; - INLINE AnalogState find_control(Axis axis) const; - - // Make device buttons and controls iterable - MAKE_SEQ_PROPERTY(buttons, get_num_buttons, get_button); - MAKE_SEQ_PROPERTY(controls, get_num_controls, get_control); - public: static TypeHandle get_class_type() { return _type_handle; diff --git a/panda/src/device/inputDeviceManager.h b/panda/src/device/inputDeviceManager.h index e231032a34..9cfadf2845 100644 --- a/panda/src/device/inputDeviceManager.h +++ b/panda/src/device/inputDeviceManager.h @@ -46,9 +46,6 @@ PUBLISHED: INLINE static InputDeviceManager *get_global_ptr(); - // The set of all currently connected devices. - MAKE_PROPERTY(devices, get_devices); - protected: LightMutex _lock; diff --git a/panda/src/device/inputDeviceNode.cxx b/panda/src/device/inputDeviceNode.cxx index 0f22cbe7f2..712d377562 100644 --- a/panda/src/device/inputDeviceNode.cxx +++ b/panda/src/device/inputDeviceNode.cxx @@ -54,9 +54,27 @@ get_device() const { void InputDeviceNode:: do_transmit_data(DataGraphTraverser *, const DataNodeTransmit &, DataNodeTransmit &output) { + + if (_device == nullptr && !_device->is_connected()) { + return; + } + + _device->poll(); + // get all button events of the device and forward them to the data graph if (_device->has_button_event()) { PT(ButtonEventList) bel = _device->get_button_events(); + + // Register the current state for each button. + for (int i = 0; i < bel->get_num_events(); ++i) { + const ButtonEvent &event = bel->get_event(i); + if (event._type == ButtonEvent::T_down) { + _button_states[event._button] = true; + } else if (event._type == ButtonEvent::T_down) { + _button_states[event._button] = false; + } + } + output.set_data(_button_events_output, EventParameter(bel)); } diff --git a/panda/src/device/inputDeviceNode.h b/panda/src/device/inputDeviceNode.h index 659ed5bf71..8e0d20e96a 100644 --- a/panda/src/device/inputDeviceNode.h +++ b/panda/src/device/inputDeviceNode.h @@ -21,17 +21,22 @@ #include "linmath_events.h" /** - * Reads the controler data sent from the InputDeviceManager, and - * transmits it down the data graph. - * + * Reads the controller data sent from the InputDeviceManager, and transmits + * it down the data graph. * + * This is intended to only be accessed from the app thread. */ class EXPCL_PANDA_DEVICE InputDeviceNode : public DataNode { PUBLISHED: InputDeviceNode(InputDevice *device, const std::string &name); + +public: void set_device(InputDevice *device); PT(InputDevice) get_device() const; +PUBLISHED: + MAKE_PROPERTY(device, get_device, set_device); + protected: // Inherited from DataNode virtual void do_transmit_data(DataGraphTraverser *trav, @@ -39,6 +44,9 @@ protected: DataNodeTransmit &output); private: + pmap _button_states; + pmap _control_states; + // outputs int _button_events_output; int _low_battery_event_output; diff --git a/panda/src/device/ioKitInputDevice.cxx b/panda/src/device/ioKitInputDevice.cxx index 0f0078404b..b3505e084f 100644 --- a/panda/src/device/ioKitInputDevice.cxx +++ b/panda/src/device/ioKitInputDevice.cxx @@ -287,14 +287,14 @@ parse_element(IOHIDElementRef element) { int max = IOHIDElementGetLogicalMax(element); if (_vendor_id == 0x044f && _product_id == 0xb108 && axis == Axis::throttle) { // T.Flight Hotas X throttle is reversed and can go backwards. - add_control(axis, max, min, true); + add_axis(axis, max, min, true); } else if (axis == Axis::yaw || axis == Axis::rudder || axis == Axis::left_y || axis == Axis::right_y || (_device_class == DC_3d_mouse && (axis == Axis::y || axis == Axis::z || axis == Axis::roll))) { // We'd like to reverse the Y axis to match the XInput behavior. // We also reverse yaw to obey the right-hand rule. - add_control(axis, max, min); + add_axis(axis, max, min); } else { - add_control(axis, min, max); + add_axis(axis, min, max); } _analog_elements.push_back(element); @@ -734,7 +734,7 @@ do_poll() { IOHIDValueRef value_ref; if (IOHIDDeviceGetValue(_device, _analog_elements[i], &value_ref) == kIOReturnSuccess) { int value = IOHIDValueGetIntegerValue(value_ref); - control_changed(i, value); + axis_changed(i, value); } } diff --git a/panda/src/device/linuxJoystickDevice.cxx b/panda/src/device/linuxJoystickDevice.cxx index e0f4d90348..ccdd29d553 100644 --- a/panda/src/device/linuxJoystickDevice.cxx +++ b/panda/src/device/linuxJoystickDevice.cxx @@ -121,7 +121,7 @@ open_device() { ioctl(_fd, JSIOCGBUTTONS, &num_buttons); _buttons.resize(num_buttons); - _controls.resize(num_axes); + _axes.resize(num_axes); if (num_buttons > 0) { uint16_t btnmap[512]; @@ -225,11 +225,11 @@ open_device() { _dpad_x_axis = i; _dpad_left_button = (int)_buttons.size(); if (_device_class == DC_gamepad) { - _buttons.push_back(ButtonState(GamepadButton::dpad_left())); - _buttons.push_back(ButtonState(GamepadButton::dpad_right())); + add_button(GamepadButton::dpad_left()); + add_button(GamepadButton::dpad_right()); } else { - _buttons.push_back(ButtonState(GamepadButton::hat_left())); - _buttons.push_back(ButtonState(GamepadButton::hat_right())); + add_button(GamepadButton::hat_left()); + add_button(GamepadButton::hat_right()); } axis = Axis::none; } @@ -241,11 +241,11 @@ open_device() { _dpad_y_axis = i; _dpad_up_button = (int)_buttons.size(); if (_device_class == DC_gamepad) { - _buttons.push_back(ButtonState(GamepadButton::dpad_up())); - _buttons.push_back(ButtonState(GamepadButton::dpad_down())); + add_button(GamepadButton::dpad_up()); + add_button(GamepadButton::dpad_down()); } else { - _buttons.push_back(ButtonState(GamepadButton::hat_up())); - _buttons.push_back(ButtonState(GamepadButton::hat_down())); + add_button(GamepadButton::hat_up()); + add_button(GamepadButton::hat_down()); } axis = Axis::none; } @@ -259,28 +259,28 @@ open_device() { axis = Axis::none; break; } - _controls[i].axis = axis; + _axes[i].axis = axis; if (axis == Axis::left_trigger || axis == Axis::right_trigger) { // We'd like to use 0.0 to indicate the resting position. - _controls[i]._scale = 1.0 / 65534.0; - _controls[i]._bias = 0.5; + _axes[i]._scale = 1.0 / 65534.0; + _axes[i]._bias = 0.5; have_analog_triggers = true; } else if (axis == Axis::left_y || axis == Axis::right_y || axis == Axis::y) { - _controls[i]._scale = 1.0 / -32767.0; - _controls[i]._bias = 0.0; + _axes[i]._scale = 1.0 / -32767.0; + _axes[i]._bias = 0.0; } else { - _controls[i]._scale = 1.0 / 32767.0; - _controls[i]._bias = 0.0; + _axes[i]._scale = 1.0 / 32767.0; + _axes[i]._bias = 0.0; } } } if (_ltrigger_button >= 0 && _rtrigger_button >= 0 && !have_analog_triggers) { // Emulate analog triggers. - _ltrigger_control = (int)_controls.size(); - add_control(Axis::left_trigger, 0, 1, false); - add_control(Axis::right_trigger, 0, 1, false); + _ltrigger_control = (int)_axes.size(); + add_axis(Axis::left_trigger, 0, 1, false); + add_axis(Axis::right_trigger, 0, 1, false); } else { _ltrigger_button = -1; _rtrigger_button = -1; @@ -343,8 +343,8 @@ open_device() { // are all 0, which indicates that the driver hasn't received any data for // this gamepad yet (which means it hasn't been plugged in for this session) if (strncmp(name, "Xbox 360 Wireless Receiver", 26) == 0) { - for (const auto &control : _controls) { - if (control.state != 0.0) { + for (const auto &control : _axes) { + if (control.value != 0.0) { _is_connected = true; return true; } @@ -398,9 +398,9 @@ process_events() { if (events[i].type & JS_EVENT_BUTTON) { if (index == _ltrigger_button) { - control_changed(_ltrigger_control, events[i].value); + axis_changed(_ltrigger_control, events[i].value); } else if (index == _rtrigger_button) { - control_changed(_ltrigger_control + 1, events[i].value); + axis_changed(_ltrigger_control + 1, events[i].value); } button_changed(index, (events[i].value != 0)); @@ -413,7 +413,7 @@ process_events() { button_changed(_dpad_up_button+1, events[i].value > 1000); } - control_changed(index, events[i].value); + axis_changed(index, events[i].value); } } diff --git a/panda/src/device/winRawInputDevice.cxx b/panda/src/device/winRawInputDevice.cxx index d61ad04d6e..7aa520a1fe 100644 --- a/panda/src/device/winRawInputDevice.cxx +++ b/panda/src/device/winRawInputDevice.cxx @@ -362,11 +362,11 @@ on_arrival(HANDLE handle, const RID_DEVICE_INFO &info, std::string name) { gamepad_buttons = gamepad_buttons_snes; } - // Prepare a mapping of data indices to button/control indices. + // Prepare a mapping of data indices to button/axis indices. _indices.resize(caps.NumberInputDataIndices); _buttons.clear(); - _controls.clear(); + _axes.clear(); USHORT num_button_caps = caps.NumberInputButtonCaps; PHIDP_BUTTON_CAPS button_caps = (PHIDP_BUTTON_CAPS)alloca(num_button_caps * sizeof(HIDP_BUTTON_CAPS)); @@ -553,17 +553,17 @@ on_arrival(HANDLE handle, const RID_DEVICE_INFO &info, std::string name) { break; } - int control_index; + int axis_index; if (_vendor_id == 0x044f && _product_id == 0xb108 && axis == Axis::throttle) { // T.Flight Hotas X throttle is reversed and can go backwards. - control_index = add_control(axis, cap.LogicalMax, cap.LogicalMin, true); + axis_index = add_axis(axis, cap.LogicalMax, cap.LogicalMin, true); } else if (!is_signed) { // All axes on the weird XInput-style mappings go from -1 to 1 - control_index = add_control(axis, cap.LogicalMin, cap.LogicalMax, true); + axis_index = add_axis(axis, cap.LogicalMin, cap.LogicalMax, true); } else { - control_index = add_control(axis, cap.LogicalMin, cap.LogicalMax); + axis_index = add_axis(axis, cap.LogicalMin, cap.LogicalMax); } - _indices[data_index] = Index::control(control_index, is_signed); + _indices[data_index] = Index::axis(axis_index, is_signed); } } @@ -635,11 +635,11 @@ on_input(PRAWINPUT input) { for (ULONG di = 0; di < count; ++di) { if (data[di].DataIndex != _hat_data_index) { const Index &idx = _indices[data[di].DataIndex]; - if (idx._control >= 0) { + if (idx._axis >= 0) { if (idx._signed) { - control_changed(idx._control, (SHORT)data[di].RawValue); + axis_changed(idx._axis, (SHORT)data[di].RawValue); } else { - control_changed(idx._control, data[di].RawValue); + axis_changed(idx._axis, data[di].RawValue); } } if (idx._button >= 0) { diff --git a/panda/src/device/winRawInputDevice.h b/panda/src/device/winRawInputDevice.h index 95ddc59cc5..c5cba8c615 100644 --- a/panda/src/device/winRawInputDevice.h +++ b/panda/src/device/winRawInputDevice.h @@ -49,28 +49,28 @@ private: // Indexed by report ID pvector _report_buttons; - // Either a button index or a control index. + // Either a button index or a axis index. struct Index { - Index() : _button(-1), _control(-1) {} + Index() : _button(-1), _axis(-1) {} static Index button(int index) { Index idx; idx._button = index; return idx; } - static Index control(int index, bool is_signed=true) { + static Index axis(int index, bool is_signed=true) { Index idx; - idx._control = index; + idx._axis = index; idx._signed = is_signed; return idx; } int _button; - int _control; + int _axis; bool _signed; }; - // Maps a "data index" to either button index or control index. + // Maps a "data index" to either button index or axis index. pvector _indices; int _hat_data_index; int _hat_data_minimum; diff --git a/panda/src/device/xInputDevice.cxx b/panda/src/device/xInputDevice.cxx index 680bbd26dd..40cb56959c 100644 --- a/panda/src/device/xInputDevice.cxx +++ b/panda/src/device/xInputDevice.cxx @@ -126,7 +126,7 @@ XInputDevice(DWORD user_index) : nassertv(user_index >= 0 && user_index < XUSER_MAX_COUNT); - _controls.resize(6); + _axes.resize(6); _buttons.resize(16); } @@ -301,6 +301,7 @@ init_xinput() { /** * Initializes the device. Called when the device was just connected. + * Assumes either the lock is held or this is called from the constructor. */ void XInputDevice:: init_device(const XINPUT_CAPABILITIES_EX &caps, const XINPUT_STATE &state) { @@ -315,81 +316,81 @@ init_device(const XINPUT_CAPABILITIES_EX &caps, const XINPUT_STATE &state) { default: case XINPUT_DEVSUBTYPE_GAMEPAD: _device_class = DC_gamepad; - set_control_map(0, Axis::left_trigger); - set_control_map(1, Axis::right_trigger); - set_control_map(2, Axis::left_x); - set_control_map(3, Axis::left_y); - set_control_map(4, Axis::right_x); - set_control_map(5, Axis::right_y); + _axes[0].axis = Axis::left_trigger; + _axes[1].axis = Axis::right_trigger; + _axes[2].axis = Axis::left_x; + _axes[3].axis = Axis::left_y; + _axes[4].axis = Axis::right_x; + _axes[5].axis = Axis::right_y; break; case XINPUT_DEVSUBTYPE_WHEEL: _device_class = DC_steering_wheel; - set_control_map(0, Axis::brake); - set_control_map(1, Axis::accelerator); - set_control_map(2, Axis::wheel); - set_control_map(3, Axis::none); - set_control_map(4, Axis::none); - set_control_map(5, Axis::none); + _axes[0].axis = Axis::brake; + _axes[1].axis = Axis::accelerator; + _axes[2].axis = Axis::wheel; + _axes[3].axis = Axis::none; + _axes[4].axis = Axis::none; + _axes[5].axis = Axis::none; break; case XINPUT_DEVSUBTYPE_FLIGHT_STICK: _device_class = DC_flight_stick; - set_control_map(0, Axis::yaw); - set_control_map(1, Axis::throttle); - set_control_map(2, Axis::roll); - set_control_map(3, Axis::pitch); - set_control_map(4, Axis::none); - set_control_map(5, Axis::none); + _axes[0].axis = Axis::yaw; + _axes[1].axis = Axis::throttle; + _axes[2].axis = Axis::roll; + _axes[3].axis = Axis::pitch; + _axes[4].axis = Axis::none; + _axes[5].axis = Axis::none; break; case XINPUT_DEVSUBTYPE_DANCE_PAD: _device_class = DC_dance_pad; - set_control_map(0, Axis::none); - set_control_map(1, Axis::none); - set_control_map(2, Axis::none); - set_control_map(3, Axis::none); - set_control_map(4, Axis::none); - set_control_map(5, Axis::none); + _axes[0].axis = Axis::none; + _axes[1].axis = Axis::none; + _axes[2].axis = Axis::none; + _axes[3].axis = Axis::none; + _axes[4].axis = Axis::none; + _axes[5].axis = Axis::none; break; } - _controls[0]._scale = 1.0 / 255.0; - _controls[1]._scale = 1.0 / 255.0; - _controls[2]._scale = 1.0 / 32767.5; - _controls[3]._scale = 1.0 / 32767.5; - _controls[4]._scale = 1.0 / 32767.5; - _controls[5]._scale = 1.0 / 32767.5; + _axes[0]._scale = 1.0 / 255.0; + _axes[1]._scale = 1.0 / 255.0; + _axes[2]._scale = 1.0 / 32767.5; + _axes[3]._scale = 1.0 / 32767.5; + _axes[4]._scale = 1.0 / 32767.5; + _axes[5]._scale = 1.0 / 32767.5; - _controls[2]._bias = 0.5 / 32767.5; - _controls[3]._bias = 0.5 / 32767.5; - _controls[4]._bias = 0.5 / 32767.5; - _controls[5]._bias = 0.5 / 32767.5; + _axes[2]._bias = 0.5 / 32767.5; + _axes[3]._bias = 0.5 / 32767.5; + _axes[4]._bias = 0.5 / 32767.5; + _axes[5]._bias = 0.5 / 32767.5; if (caps.Flags & XINPUT_CAPS_NO_NAVIGATION) { - set_button_map(0, ButtonHandle::none()); - set_button_map(1, ButtonHandle::none()); - set_button_map(2, ButtonHandle::none()); - set_button_map(3, ButtonHandle::none()); - set_button_map(4, ButtonHandle::none()); - set_button_map(5, ButtonHandle::none()); + _buttons[0].handle = ButtonHandle::none(); + _buttons[1].handle = ButtonHandle::none(); + _buttons[2].handle = ButtonHandle::none(); + _buttons[3].handle = ButtonHandle::none(); + _buttons[4].handle = ButtonHandle::none(); + _buttons[5].handle = ButtonHandle::none(); } else { - set_button_map(0, GamepadButton::dpad_up()); - set_button_map(1, GamepadButton::dpad_down()); - set_button_map(2, GamepadButton::dpad_left()); - set_button_map(3, GamepadButton::dpad_right()); - set_button_map(4, GamepadButton::start()); - set_button_map(5, GamepadButton::back()); + _buttons[0].handle = GamepadButton::dpad_up(); + _buttons[1].handle = GamepadButton::dpad_down(); + _buttons[2].handle = GamepadButton::dpad_left(); + _buttons[3].handle = GamepadButton::dpad_right(); + _buttons[4].handle = GamepadButton::start(); + _buttons[5].handle = GamepadButton::back(); } - set_button_map(6, GamepadButton::lstick()); - set_button_map(7, GamepadButton::rstick()); - set_button_map(8, GamepadButton::lshoulder()); - set_button_map(9, GamepadButton::rshoulder()); - set_button_map(10, GamepadButton::guide()); - set_button_map(11, GamepadButton::face_a()); - set_button_map(12, GamepadButton::face_b()); - set_button_map(13, GamepadButton::face_x()); - set_button_map(14, GamepadButton::face_y()); + _buttons[6].handle = GamepadButton::lstick(); + _buttons[7].handle = GamepadButton::rstick(); + _buttons[8].handle = GamepadButton::lshoulder(); + _buttons[9].handle = GamepadButton::rshoulder(); + _buttons[10].handle = GamepadButton::guide(); + _buttons[11].handle = GamepadButton::face_a(); + _buttons[12].handle = GamepadButton::face_b(); + _buttons[13].handle = GamepadButton::face_x(); + _buttons[14].handle = GamepadButton::face_y(); if (caps.Vibration.wLeftMotorSpeed != 0 || caps.Vibration.wRightMotorSpeed != 0) { @@ -403,8 +404,8 @@ init_device(const XINPUT_CAPABILITIES_EX &caps, const XINPUT_STATE &state) { batt.BatteryType != BATTERY_TYPE_WIRED) { // This device has a battery. Report the battery level. _flags |= IDF_has_battery; - _battery_level = batt.BatteryLevel; - _max_battery_level = BATTERY_LEVEL_FULL; + _battery_data.level = batt.BatteryLevel; + _battery_data.max_level = BATTERY_LEVEL_FULL; } } } @@ -413,7 +414,7 @@ init_device(const XINPUT_CAPABILITIES_EX &caps, const XINPUT_STATE &state) { WORD mask = 1; for (int i = 0; i < 16; ++i) { // Set the state without triggering a button event. - _buttons[i].state = (buttons & mask) ? S_down : S_up; + _buttons[i]._state = (buttons & mask) ? S_down : S_up; mask <<= 1; if (i == 10) { // XInput skips 0x0800. @@ -421,12 +422,12 @@ init_device(const XINPUT_CAPABILITIES_EX &caps, const XINPUT_STATE &state) { } } - control_changed(0, state.Gamepad.bLeftTrigger); - control_changed(1, state.Gamepad.bRightTrigger); - control_changed(2, state.Gamepad.sThumbLX); - control_changed(3, state.Gamepad.sThumbLY); - control_changed(4, state.Gamepad.sThumbRX); - control_changed(5, state.Gamepad.sThumbRY); + axis_changed(0, state.Gamepad.bLeftTrigger); + axis_changed(1, state.Gamepad.bRightTrigger); + axis_changed(2, state.Gamepad.sThumbLX); + axis_changed(3, state.Gamepad.sThumbLY); + axis_changed(4, state.Gamepad.sThumbRX); + axis_changed(5, state.Gamepad.sThumbRY); _last_buttons = buttons; _last_packet = state.dwPacketNumber; @@ -491,12 +492,12 @@ do_poll() { } } - control_changed(0, state.Gamepad.bLeftTrigger); - control_changed(1, state.Gamepad.bRightTrigger); - control_changed(2, state.Gamepad.sThumbLX); - control_changed(3, state.Gamepad.sThumbLY); - control_changed(4, state.Gamepad.sThumbRX); - control_changed(5, state.Gamepad.sThumbRY); + axis_changed(0, state.Gamepad.bLeftTrigger); + axis_changed(1, state.Gamepad.bRightTrigger); + axis_changed(2, state.Gamepad.sThumbLX); + axis_changed(3, state.Gamepad.sThumbLY); + axis_changed(4, state.Gamepad.sThumbRX); + axis_changed(5, state.Gamepad.sThumbRY); _last_buttons = state.Gamepad.wButtons; _last_packet = state.dwPacketNumber; diff --git a/panda/src/vrpn/vrpnAnalog.cxx b/panda/src/vrpn/vrpnAnalog.cxx index c24beabb48..2745aab75e 100644 --- a/panda/src/vrpn/vrpnAnalog.cxx +++ b/panda/src/vrpn/vrpnAnalog.cxx @@ -100,13 +100,7 @@ vrpn_analog_callback(void *userdata, const vrpn_ANALOGCB info) { for (di = self->_devices.begin(); di != self->_devices.end(); ++di) { VrpnAnalogDevice *device = (*di); for (int i = 0; i < info.num_channel; i++) { - if (vrpn_cat.is_debug()) { - if (device->get_control_state(i) != info.channel[i]) { - vrpn_cat.debug() - << *self << " got analog " << i << " = " << info.channel[i] << "\n"; - } - } - device->set_control_state(i, info.channel[i]); + device->set_axis_value(i, info.channel[i]); } } } diff --git a/panda/src/vrpn/vrpnTracker.cxx b/panda/src/vrpn/vrpnTracker.cxx index b42f4f5336..e1b08e2a72 100644 --- a/panda/src/vrpn/vrpnTracker.cxx +++ b/panda/src/vrpn/vrpnTracker.cxx @@ -107,10 +107,10 @@ vrpn_position_callback(void *userdata, const vrpn_TRACKERCB info) { VrpnTrackerDevice *device = (*di); if (device->get_sensor() == info.sensor && device->get_data_type() == VrpnTrackerDevice::DT_position) { - device->set_tracker(LPoint3(info.pos[0], info.pos[1], info.pos[2]), - LOrientation(info.quat[3], info.quat[0], - info.quat[1], info.quat[2]), - VrpnClient::convert_to_secs(info.msg_time)); + device->tracker_changed(LPoint3(info.pos[0], info.pos[1], info.pos[2]), + LOrientation(info.quat[3], info.quat[0], + info.quat[1], info.quat[2]), + VrpnClient::convert_to_secs(info.msg_time)); } } } @@ -132,10 +132,10 @@ vrpn_velocity_callback(void *userdata, const vrpn_TRACKERVELCB info) { VrpnTrackerDevice *device = (*di); if (device->get_sensor() == info.sensor && device->get_data_type() == VrpnTrackerDevice::DT_velocity) { - device->set_tracker(LPoint3(info.vel[0], info.vel[1], info.vel[2]), - LOrientation(info.vel_quat[3], info.vel_quat[0], - info.vel_quat[1], info.vel_quat[2]), - VrpnClient::convert_to_secs(info.msg_time)); + device->tracker_changed(LPoint3(info.vel[0], info.vel[1], info.vel[2]), + LOrientation(info.vel_quat[3], info.vel_quat[0], + info.vel_quat[1], info.vel_quat[2]), + VrpnClient::convert_to_secs(info.msg_time)); } } } @@ -157,10 +157,10 @@ vrpn_acceleration_callback(void *userdata, const vrpn_TRACKERACCCB info) { VrpnTrackerDevice *device = (*di); if (device->get_sensor() == info.sensor && device->get_data_type() == VrpnTrackerDevice::DT_acceleration) { - device->set_tracker(LPoint3(info.acc[0], info.acc[1], info.acc[2]), - LOrientation(info.acc_quat[3], info.acc_quat[0], - info.acc_quat[1], info.acc_quat[2]), - VrpnClient::convert_to_secs(info.msg_time)); + device->tracker_changed(LPoint3(info.acc[0], info.acc[1], info.acc[2]), + LOrientation(info.acc_quat[3], info.acc_quat[0], + info.acc_quat[1], info.acc_quat[2]), + VrpnClient::convert_to_secs(info.msg_time)); } } }