Panda3D
inputDevice.h
Go to the documentation of this file.
1 /**
2  * PANDA 3D SOFTWARE
3  * Copyright (c) Carnegie Mellon University. All rights reserved.
4  *
5  * All use of this software is subject to the terms of the revised BSD
6  * license. You should have received a copy of this license along
7  * with this source code in a file named "LICENSE."
8  *
9  * @file inputDevice.h
10  * @author rdb
11  * @date 2015-12-11
12  */
13 
14 #ifndef INPUTDEVICE_H
15 #define INPUTDEVICE_H
16 
17 #include "pandabase.h"
18 
19 #include "buttonEvent.h"
20 #include "buttonEventList.h"
21 #include "pointerEvent.h"
22 #include "pointerEventList.h"
23 #include "pointerData.h"
24 #include "trackerData.h"
25 #include "clockObject.h"
26 
27 #include "pdeque.h"
28 #include "pvector.h"
29 #include "lightMutex.h"
30 #include "lightMutexHolder.h"
31 
32 /**
33  * This is a structure representing a single input device. Input devices may
34  * have zero or more buttons, pointers, or axes associated with them, and
35  * optionally a motion tracker.
36  *
37  * These devices are brought under a common interface because there is such a
38  * large range of devices out there that may support any number of these types
39  * of axes, we couldn't even begin to cover them with type-specific
40  * subclasses.
41  *
42  * Use the various has_() and get_num_() methods to determine information about
43  * the device capabilities. For instance, has_keyboard() will give an
44  * indication that you can receive keystroke events from this device, and
45  * get_num_buttons() will tell you that the device may send button events.
46  *
47  * There is the DeviceType enumeration, however, which will (if known) contain
48  * identification of the general category of devices this fits in, such as
49  * keyboard, mouse, gamepad, or flight stick.
50  */
51 class EXPCL_PANDA_DEVICE InputDevice : public TypedReferenceCount {
52 PUBLISHED:
53  // This enum contains information that can be used to identify the
54  // type of input device.
55  enum class DeviceClass {
56  // It is not known what type of device this is.
57  unknown,
58 
59  // This means that the device doesn't correspond to a physical
60  // device, but rather to a dynamic source of input events.
61  virtual_device,
62 
63  // A physical, alphabetical keyboard.
64  keyboard,
65 
66  mouse,
67  touch,
68 
69  // A gamepad with action buttons, a D-pad, and thumbsticks.
70  gamepad,
71 
72  flight_stick,
73  steering_wheel,
74  dance_pad,
75 
76  // Head-mounted display.
77  hmd,
78 
79  // 3D mouse, such as produced by 3Dconnexion.
80  spatial_mouse,
81  };
82 
83  enum class Feature {
84  // The device provides absolute screen coordinates.
85  pointer,
86 
87  // The device has an interface for providing text input.
88  keyboard,
89 
90  // The device has a motion tracker, such as an HMD.
91  tracker,
92 
93  // The device can produce force feedback.
94  vibration,
95 
96  // The device provides information about battery life.
97  battery,
98  };
99 
100  enum class Axis {
101  none,
102 
103  // Generic translational axes
104  x,
105  y,
106  z,
107 
108  // Generic rotational axes, used by joysticks and 3D mice
109  yaw,
110  pitch,
111  roll,
112 
113  // Gamepad
114  left_x,
115  left_y,
116  left_trigger,
117  right_x,
118  right_y,
119  right_trigger,
120 
121  // Flight stick specific
122  throttle,
123  rudder, // When available separately from yaw
124 
125  // Steering wheel / pedals
126  wheel,
127  accelerator,
128  brake,
129  };
130 
131  enum State {
132  S_unknown,
133  S_up,
134  S_down
135  };
136 
137  class ButtonState {
138  public:
139  constexpr ButtonState() = default;
140  INLINE ButtonState(ButtonHandle handle);
141  ALWAYS_INLINE bool is_known() const;
142  ALWAYS_INLINE bool is_pressed() const;
143 
144  PUBLISHED:
145  operator bool() { return _state != S_unknown; }
146 
147  MAKE_PROPERTY(known, is_known);
148  MAKE_PROPERTY(pressed, is_pressed);
149 
150  ButtonHandle handle = ButtonHandle::none();
151 
152  public:
153  State _state = S_unknown;
154  };
155 
156  class AxisState {
157  public:
158  constexpr AxisState() = default;
159 
160  PUBLISHED:
161  operator bool() { return known && value != 0.0; }
162 
163  Axis axis = Axis::none;
164  double value = 0.0;
165  bool known = false;
166 
167  public:
168  double _scale = 1.0;
169  double _bias = 0.0;
170  };
171 
172  class BatteryData {
173  PUBLISHED:
174  // Ranges from 0 through max_level.
175  short level = -1;
176 
177  // Maximum value of 'level' field.
178  short max_level = -1;
179  };
180 
181 protected:
182  InputDevice(const std::string &name, DeviceClass dev_class);
183 
184 public:
185  InputDevice();
186  InputDevice(const InputDevice &copy) = delete;
187  InputDevice &operator = (const InputDevice &copy) = delete;
188  virtual ~InputDevice();
189 
190  INLINE std::string get_name() const;
191  INLINE std::string get_manufacturer() const;
192  INLINE std::string get_serial_number() const;
193  INLINE unsigned short get_vendor_id() const;
194  INLINE unsigned short get_product_id() const;
195  INLINE bool is_connected() const;
196  INLINE DeviceClass get_device_class() const;
197 
198  INLINE bool has_pointer() const;
199  INLINE bool has_keyboard() const;
200  INLINE bool has_tracker() const;
201  INLINE bool has_vibration() const;
202  INLINE bool has_battery() const;
203 
204  INLINE TrackerData get_tracker() const;
205  INLINE BatteryData get_battery() const;
206 
207  INLINE size_t get_num_buttons() const;
208  INLINE ButtonHandle get_button_map(size_t index) const;
209  INLINE bool is_button_pressed(size_t index) const;
210  INLINE bool is_button_known(size_t index) const;
211  INLINE ButtonState get_button(size_t index) const;
212 
213  INLINE size_t get_num_axes() const;
214  INLINE double get_axis_value(size_t index) const;
215  INLINE bool is_axis_known(size_t index) const;
216  INLINE AxisState get_axis(size_t index) const;
217 
218 PUBLISHED:
219  // The human-readable name of this input device.
220  MAKE_PROPERTY(name, get_name);
221 
222  // The device's manufacturer, or the empty string if not known.
223  MAKE_PROPERTY(manufacturer, get_manufacturer);
224 
225  // The device's serial number, or the empty string if not known.
226  MAKE_PROPERTY(serial_number, get_serial_number);
227 
228  // USB vendor ID of the device, or 0 if not known.
229  MAKE_PROPERTY(vendor_id, get_vendor_id);
230 
231  // USB product ID of the device, or 0 if not known.
232  MAKE_PROPERTY(product_id, get_product_id);
233 
234  // This is false if we know that the device is not currently connected.
235  // May report false positives if we can't know this with certainty.
236  MAKE_PROPERTY(connected, is_connected);
237 
238  // This contains an identification of the general type of device. If
239  // this could not be determined, it is set to DC_unknown.
240  MAKE_PROPERTY(device_class, get_device_class);
241 
242  // Determine supported features
243  INLINE bool has_feature(Feature feature) const;
244 
245  // Getters for the various types of device data.
246  MAKE_PROPERTY2(tracker, has_tracker, get_tracker);
247  MAKE_PROPERTY2(battery, has_battery, get_battery);
248 
249  // Make device buttons and axes iterable
250  MAKE_SEQ_PROPERTY(buttons, get_num_buttons, get_button);
251  MAKE_SEQ_PROPERTY(axes, get_num_axes, get_axis);
252 
253  // Associate buttons/axes with symbolic handles.
254  INLINE void map_button(size_t index, ButtonHandle handle);
255  INLINE void map_axis(size_t index, Axis axis);
256  INLINE ButtonState find_button(ButtonHandle handle) const;
257  INLINE AxisState find_axis(Axis axis) const;
258 
259  // Enable rumble force-feedback effects
260  INLINE void set_vibration(double strong, double weak);
261 
262  INLINE void enable_pointer_events();
263  INLINE void disable_pointer_events();
264 
265  void poll();
266 
267  bool has_button_event() const;
268  PT(ButtonEventList) get_button_events();
269  bool has_pointer_event() const;
270  PT(PointerEventList) get_pointer_events();
271 
272  virtual void output(std::ostream &out) const;
273 
274 public:
275  static std::string format_device_class(DeviceClass dc);
276  static std::string format_axis(Axis axis);
277 
278 protected:
279  INLINE void enable_feature(Feature feature);
280 
281  // Called during the constructor to add new axes or buttons
282  int add_button(ButtonHandle handle);
283  int add_axis(Axis axis, int minimum, int maximum, bool centered);
284  int add_axis(Axis axis, int minimum, int maximum);
285 
286  int add_pointer(PointerType type, int id, bool primary = false);
287  void remove_pointer(int id);
288  void update_pointer(PointerData data, double time);
289  void pointer_moved(int id, double x, double y, double time);
290  void button_changed(int index, bool down);
291  void axis_changed(int index, int value);
292  void set_axis_value(int index, double state);
293 
294  void tracker_changed(const LPoint3 &pos, const LOrientation &orient, double time);
295 
296  virtual void do_set_vibration(double low, double high);
297  virtual void do_poll();
298 
299 public:
300  INLINE void set_connected(bool connected);
301 
302  void output_buttons(std::ostream &out) const;
303  void write_buttons(std::ostream &out, int indent_level) const;
304  void write_axes(std::ostream &out, int indent_level) const;
305 
306 protected:
308 
309  LightMutex _lock {"InputDevice"};
310 
311  std::string _name;
312  std::string _serial_number;
313  std::string _manufacturer;
314  DeviceClass _device_class = DeviceClass::unknown;
315  unsigned int _features = 0;
316  int _event_sequence = 0;
317  unsigned short _vendor_id = 0;
318  unsigned short _product_id = 0;
319  bool _is_connected = false;
320  bool _enable_pointer_events = false;
321  PT(ButtonEventList) _button_events;
322  PT(PointerEventList) _pointer_events;
323 
324  size_t _num_pointers = 0;
325  typedef pvector<PointerData> Pointers;
326  Pointers _pointers;
327 
328 PUBLISHED:
329  typedef pvector<ButtonState> Buttons;
330  typedef pvector<AxisState> Axes;
331  Buttons _buttons;
332  Axes _axes;
333 
334  PointerData _pointer_data;
335  BatteryData _battery_data;
336  TrackerData _tracker_data;
337 
338 public:
339  static TypeHandle get_class_type() {
340  return _type_handle;
341  }
342  static void init_type() {
343  TypedReferenceCount::init_type();
344  register_type(_type_handle, "InputDevice",
345  TypedReferenceCount::get_class_type());
346  }
347  virtual TypeHandle get_type() const {
348  return get_class_type();
349  }
350  virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
351 
352 private:
353  static TypeHandle _type_handle;
354 };
355 
356 INLINE std::ostream &operator << (std::ostream &out, const InputDevice &device) {
357  device.output(out);
358  return out;
359 }
360 
361 EXPCL_PANDA_DEVICE std::ostream &operator << (std::ostream &out, InputDevice::DeviceClass dc);
362 EXPCL_PANDA_DEVICE std::ostream &operator << (std::ostream &out, InputDevice::Axis axis);
363 
364 #include "inputDevice.I"
365 
366 #endif
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void register_type(TypeHandle &type_handle, const std::string &name)
This inline function is just a convenient way to call TypeRegistry::register_type(), along with zero to four record_derivation()s.
Definition: register_type.I:22
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A base class for things which need to inherit from both TypedObject and from ReferenceCount.
Records a set of pointer events that happened recently.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This is our own Panda specialization on the default STL deque.
Definition: pdeque.h:36
Records a set of button events that happened recently.
A ButtonHandle represents a single button from any device, including keyboard buttons and mouse butto...
Definition: buttonHandle.h:26
PointerType
Contains the types of pointer device.
Definition: pointerData.h:25
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
bool is_connected(MObject &node, const string &attribute_name)
Returns true if the named connection exists on the node and is connected to anything, false otherwise.
Definition: maya_funcs.cxx:72
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This is a structure representing a single input device.
Definition: inputDevice.h:51
Holds the data that might be generated by a 2-d pointer input device, such as the mouse in the Graphi...
Definition: pointerData.h:38
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Stores the kinds of data that a tracker might output.
Definition: trackerData.h:23
virtual void output(std::ostream &out) const
Writes a one-line string describing the device.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
This is a standard, non-reentrant mutex, similar to the Mutex class.
Definition: lightMutex.h:39
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.