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
This commit is contained in:
rdb 2018-09-16 15:12:17 +02:00
parent 8d8c5a546d
commit 8edc019307
19 changed files with 439 additions and 424 deletions

View File

@ -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);
}
/**

View File

@ -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;
}
}
}
}

View File

@ -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);
}
/**

View File

@ -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);
}

View File

@ -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;

View File

@ -49,7 +49,7 @@ private:
int _ff_strong;
int _ff_weak;
pvector<int> _control_indices;
pvector<int> _axis_indices;
pvector<int> _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;

View File

@ -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);
}

View File

@ -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";
}
}

View File

@ -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 &copy);
void operator = (const InputDevice &copy);
~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 &copy);
void operator = (const InputDevice &copy);
~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<InputDevice>. 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<ButtonState> Buttons;
typedef pvector<AxisState> 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<AnalogState> 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;

View File

@ -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;

View File

@ -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));
}

View File

@ -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<ButtonHandle, bool> _button_states;
pmap<InputDevice::Axis, double> _control_states;
// outputs
int _button_events_output;
int _low_battery_event_output;

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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) {

View File

@ -49,28 +49,28 @@ private:
// Indexed by report ID
pvector<BitArray> _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<Index> _indices;
int _hat_data_index;
int _hat_data_minimum;

View File

@ -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;

View File

@ -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]);
}
}
}

View File

@ -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));
}
}
}