16 #if defined(_MSC_VER) && _MSC_VER < 1700 17 #define fma(a, b, c) ((a) * (b) + (c)) 26 InputDevice(
const std::string &name, DeviceClass dev_class) :
28 _device_class(dev_class),
61 return !_button_events.is_null() && _button_events->get_num_events() > 0;
72 swap(_button_events, result);
84 return _pointer_events !=
nullptr && !_pointer_events->empty();
92 get_pointer_events() {
95 swap(_pointer_events, result);
104 int index = (int)_buttons.size();
105 _buttons.push_back(ButtonState(button));
113 add_axis(Axis axis,
int minimum,
int maximum,
bool centered) {
118 state._scale = 2.0 / (maximum - minimum);
119 state._bias = (maximum + minimum) / (
double)(minimum - maximum);
122 state._scale = 1.0 / maximum;
125 int index = (int)_axes.size();
126 _axes.push_back(state);
135 add_axis(Axis axis,
int minimum,
int maximum) {
136 bool centered = (minimum < 0)
141 || axis == Axis::pitch
142 || axis == Axis::roll
143 || axis == Axis::left_x
144 || axis == Axis::left_y
145 || axis == Axis::right_x
146 || axis == Axis::right_y
147 || axis == Axis::wheel
148 || axis == Axis::rudder;
149 return add_axis(axis, minimum, maximum, centered);
156 add_pointer(
PointerType type,
int id,
bool primary) {
163 int index = (int)_pointers.size();
164 if (_num_pointers == _pointers.size()) {
165 _pointers.push_back(data);
167 _pointers[index] = data;
179 remove_pointer(
int id) {
183 for (i = 0; i < _pointers.size(); ++i) {
184 if (_pointers[i]._id ==
id) {
189 if (i < _pointers.size()) {
190 if (_pointers[i]._pressure != 0.0) {
191 _pointers[i]._pressure = 0.0;
193 if (_enable_pointer_events) {
194 int seq = _event_sequence++;
196 _pointer_events->add_event(_pointers[i], seq, time);
201 if (i != _pointers.size() - 1) {
202 _pointers[i] = _pointers.back();
217 for (
size_t i = 0; i < _pointers.size(); ++i) {
218 if (_pointers[i]._id == data._id) {
224 if (ptr ==
nullptr) {
225 _pointers.push_back(data);
226 ptr = &_pointers.back();
229 if (_enable_pointer_events) {
230 int seq = _event_sequence++;
231 _pointer_events->add_event(*ptr, seq, time);
239 pointer_moved(
int id,
double x,
double y,
double time) {
243 for (
size_t i = 0; i < _pointers.size(); ++i) {
244 if (_pointers[i]._id ==
id) {
246 _pointers[i]._xpos = x;
247 _pointers[i]._ypos = y;
251 nassertv_always(ptr !=
nullptr);
253 if (device_cat.is_spam() && (x != 0 || y != 0)) {
255 <<
"Pointer " <<
id <<
" moved by " << x <<
" x " << y <<
"\n";
258 if (_enable_pointer_events) {
259 int seq = _event_sequence++;
260 _pointer_events->add_event(ptr->_in_window,
274 button_changed(
int index,
bool down) {
276 nassertv(index >= 0);
277 if (index >= (
int)_buttons.size()) {
278 _buttons.resize(index + 1, ButtonState());
281 State new_state = down ? S_down : S_up;
282 if (_buttons[index]._state == new_state) {
285 _buttons[index]._state = new_state;
289 if (device_cat.is_spam()) {
291 <<
"Changed button " << index;
293 if (handle != ButtonHandle::none()) {
294 device_cat.spam(
false) <<
" (" << handle <<
")";
297 device_cat.spam(
false) <<
" to " << (down ?
"down" :
"up") <<
"\n";
300 if (handle != ButtonHandle::none()) {
301 _button_events->add_event(
ButtonEvent(handle, down ? ButtonEvent::T_down : ButtonEvent::T_up));
312 set_axis_value(
int index,
double value) {
315 nassertv(index >= 0);
316 if ((
size_t)index >= _axes.size()) {
317 _axes.resize((
size_t)index + 1u, AxisState());
320 if (device_cat.is_spam() && _axes[index].value != value) {
322 <<
"Changed axis " << index;
324 if (_axes[index].axis != Axis::none) {
325 device_cat.spam(
false) <<
" (" << _axes[index].axis <<
")";
328 device_cat.spam(
false) <<
" to " << value <<
"\n";
331 _axes[index].value = value;
332 _axes[index].known =
true;
340 axis_changed(
int index,
int state) {
342 nassertv(index >= 0);
343 if ((
size_t)index >= _axes.size()) {
344 _axes.resize((
size_t)index + 1u, AxisState());
347 double value = fma((
double)state, _axes[index]._scale, _axes[index]._bias);
349 if (device_cat.is_spam() && !IS_NEARLY_EQUAL(_axes[index].value, value)) {
351 <<
"Changed axis " << index;
353 if (_axes[index].axis != Axis::none) {
354 device_cat.spam(
false) <<
" (" << _axes[index].axis <<
")";
357 device_cat.spam(
false) <<
" to " << value <<
" (raw value " << state <<
")\n";
360 _axes[index].value = value;
361 _axes[index].known =
true;
368 tracker_changed(
const LPoint3 &pos,
const LOrientation &orient,
double time) {
383 out << _name <<
" (";
385 if (!_is_connected) {
391 if (_device_class != DeviceClass::unknown) {
392 out <<
", " << _device_class;
395 if (_buttons.size() > 0) {
396 out <<
", " << _buttons.size() <<
" button";
397 if (_buttons.size() != 1) {
402 if (_axes.size() > 0) {
403 out <<
", " << _axes.size() <<
" ax" 404 << (_axes.size() != 1 ?
'e' :
'i') <<
's';
407 if (_features & (1 << (
unsigned int)Feature::pointer)) {
410 if (_features & (1 << (
unsigned int)Feature::keyboard)) {
413 if (_features & (1 << (
unsigned int)Feature::tracker)) {
416 if (_features & (1 << (
unsigned int)Feature::vibration)) {
417 out <<
", vibration";
419 if (_features & (1 << (
unsigned int)Feature::battery)) {
422 if (_battery_data.level > 0 && _battery_data.max_level > 0) {
425 for (; i < _battery_data.level; ++i) {
428 for (; i < _battery_data.max_level; ++i) {
443 bool any_buttons =
false;
444 Buttons::const_iterator bi;
445 for (bi = _buttons.begin(); bi != _buttons.end(); ++bi) {
452 out << (int)(bi - _buttons.begin()) <<
"=";
453 if (state._state == S_up) {
462 out <<
"no known buttons";
471 bool any_buttons =
false;
472 Buttons::const_iterator bi;
473 for (bi = _buttons.begin(); bi != _buttons.end(); ++bi) {
479 << (int)(bi - _buttons.begin()) <<
". ";
481 if (state.handle != ButtonHandle::none()) {
482 out <<
"(" << state.handle <<
") ";
485 if (state._state == S_up) {
496 <<
"(no known buttons)\n";
507 bool any_axis =
false;
508 Axes::const_iterator ai;
509 for (ai = _axes.begin(); ai != _axes.end(); ++ai) {
515 << (int)(ai - _axes.begin()) <<
". " << state.value <<
"\n";
521 <<
"(no known analog axes)\n";
531 do_set_vibration(
double strong,
double weak) {
549 case InputDevice::DeviceClass::unknown:
552 case InputDevice::DeviceClass::virtual_device:
553 return "virtual_device";
555 case InputDevice::DeviceClass::keyboard:
558 case InputDevice::DeviceClass::mouse:
561 case InputDevice::DeviceClass::touch:
564 case InputDevice::DeviceClass::gamepad:
567 case InputDevice::DeviceClass::flight_stick:
568 return "flight_stick";
570 case InputDevice::DeviceClass::steering_wheel:
571 return "steering_wheel";
573 case InputDevice::DeviceClass::dance_pad:
576 case InputDevice::DeviceClass::hmd:
579 case InputDevice::DeviceClass::spatial_mouse:
580 return "spatial_mouse";
582 return "**invalid**";
591 case InputDevice::Axis::none:
594 case InputDevice::Axis::x:
597 case InputDevice::Axis::y:
600 case InputDevice::Axis::z:
603 case InputDevice::Axis::yaw:
606 case InputDevice::Axis::pitch:
609 case InputDevice::Axis::roll:
612 case InputDevice::Axis::left_x:
615 case InputDevice::Axis::left_y:
618 case InputDevice::Axis::left_trigger:
619 return "left_trigger";
621 case InputDevice::Axis::right_x:
624 case InputDevice::Axis::right_y:
627 case InputDevice::Axis::right_trigger:
628 return "right_trigger";
633 case InputDevice::Axis::throttle:
636 case InputDevice::Axis::rudder:
639 case InputDevice::Axis::wheel:
642 case InputDevice::Axis::accelerator:
643 return "accelerator";
645 case InputDevice::Axis::brake:
648 return "**invalid**";
652 operator << (std::ostream &out, InputDevice::DeviceClass dc) {
658 operator << (std::ostream &out, InputDevice::Axis axis) {
static ClockObject * get_global_clock()
Returns a pointer to the global ClockObject.
bool debug_is_locked() const
Returns true if the current thread has locked the LightMutex, false otherwise.
Records a set of pointer events that happened recently.
PointerType
Contains the types of pointer device.
get_frame_time
Returns the time in seconds as of the last time tick() was called (typically, this will be as of the ...
std::ostream & indent(std::ostream &out, int indent_level)
A handy function for doing text formatting.
Similar to MutexHolder, but for a light mutex.
Holds the data that might be generated by a 2-d pointer input device, such as the mouse in the Graphi...
set_time
Indicates the time at which the position information (pos and orient) are effective.
TypeHandle is the identifier used to differentiate C++ class types.
set_pos
Indicates the current position of the tracker sensor in space.
set_orient
Indicates the current orientation of the tracker sensor in space.