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  * @since 1.10.0
52  */
53 class EXPCL_PANDA_DEVICE InputDevice : public TypedReferenceCount {
54 PUBLISHED:
55  // This enum contains information that can be used to identify the
56  // type of input device.
57  enum class DeviceClass {
58  // It is not known what type of device this is.
59  unknown,
60 
61  // This means that the device doesn't correspond to a physical
62  // device, but rather to a dynamic source of input events.
63  virtual_device,
64 
65  // A physical, alphabetical keyboard.
66  keyboard,
67 
68  mouse,
69  touch,
70 
71  // A gamepad with action buttons, a D-pad, and thumbsticks.
72  gamepad,
73 
74  flight_stick,
75  steering_wheel,
76  dance_pad,
77 
78  // Head-mounted display.
79  hmd,
80 
81  // 3D mouse, such as produced by 3Dconnexion.
82  spatial_mouse,
83  };
84 
85  enum class Feature {
86  // The device provides absolute screen coordinates.
87  pointer,
88 
89  // The device has an interface for providing text input.
90  keyboard,
91 
92  // The device has a motion tracker, such as an HMD.
93  tracker,
94 
95  // The device can produce force feedback.
96  vibration,
97 
98  // The device provides information about battery life.
99  battery,
100  };
101 
102  enum class Axis {
103  none,
104 
105  // Generic translational axes
106  x,
107  y,
108  z,
109 
110  // Generic rotational axes, used by joysticks and 3D mice
111  yaw,
112  pitch,
113  roll,
114 
115  // Gamepad
116  left_x,
117  left_y,
118  left_trigger,
119  right_x,
120  right_y,
121  right_trigger,
122 
123  // Flight stick specific
124  throttle,
125  rudder, // When available separately from yaw
126 
127  // Steering wheel / pedals
128  wheel,
129  accelerator,
130  brake,
131  };
132 
133  enum State {
134  S_unknown,
135  S_up,
136  S_down
137  };
138 
139  class ButtonState {
140  public:
141  constexpr ButtonState() = default;
142  INLINE ButtonState(ButtonHandle handle);
143  ALWAYS_INLINE bool is_known() const;
144  ALWAYS_INLINE bool is_pressed() const;
145 
146  PUBLISHED:
147  operator bool() { return _state != S_unknown; }
148 
149  MAKE_PROPERTY(known, is_known);
150  MAKE_PROPERTY(pressed, is_pressed);
151 
152  ButtonHandle handle = ButtonHandle::none();
153 
154  public:
155  State _state = S_unknown;
156  };
157 
158  class AxisState {
159  public:
160  constexpr AxisState() = default;
161 
162  PUBLISHED:
163  operator bool() { return known && value != 0.0; }
164 
165  Axis axis = Axis::none;
166  double value = 0.0;
167  bool known = false;
168 
169  public:
170  double _scale = 1.0;
171  double _bias = 0.0;
172  };
173 
174  class BatteryData {
175  PUBLISHED:
176  // Ranges from 0 through max_level.
177  short level = -1;
178 
179  // Maximum value of 'level' field.
180  short max_level = -1;
181  };
182 
183 protected:
184  InputDevice(const std::string &name, DeviceClass dev_class);
185 
186 public:
187  InputDevice();
188  InputDevice(const InputDevice &copy) = delete;
189  InputDevice &operator = (const InputDevice &copy) = delete;
190  virtual ~InputDevice();
191 
192  INLINE std::string get_name() const;
193  INLINE std::string get_manufacturer() const;
194  INLINE std::string get_serial_number() const;
195  INLINE unsigned short get_vendor_id() const;
196  INLINE unsigned short get_product_id() const;
197  INLINE bool is_connected() const;
198  INLINE DeviceClass get_device_class() const;
199 
200  INLINE bool has_pointer() const;
201  INLINE bool has_keyboard() const;
202  INLINE bool has_tracker() const;
203  INLINE bool has_vibration() const;
204  INLINE bool has_battery() const;
205 
206  INLINE TrackerData get_tracker() const;
207  INLINE BatteryData get_battery() const;
208 
209  INLINE size_t get_num_buttons() const;
210  INLINE ButtonHandle get_button_map(size_t index) const;
211  INLINE bool is_button_pressed(size_t index) const;
212  INLINE bool is_button_known(size_t index) const;
213  INLINE ButtonState get_button(size_t index) const;
214 
215  INLINE size_t get_num_axes() const;
216  INLINE double get_axis_value(size_t index) const;
217  INLINE bool is_axis_known(size_t index) const;
218  INLINE AxisState get_axis(size_t index) const;
219 
220 PUBLISHED:
221  // The human-readable name of this input device.
222  MAKE_PROPERTY(name, get_name);
223 
224  // The device's manufacturer, or the empty string if not known.
225  MAKE_PROPERTY(manufacturer, get_manufacturer);
226 
227  // The device's serial number, or the empty string if not known.
228  MAKE_PROPERTY(serial_number, get_serial_number);
229 
230  // USB vendor ID of the device, or 0 if not known.
231  MAKE_PROPERTY(vendor_id, get_vendor_id);
232 
233  // USB product ID of the device, or 0 if not known.
234  MAKE_PROPERTY(product_id, get_product_id);
235 
236  // This is false if we know that the device is not currently connected.
237  // May report false positives if we can't know this with certainty.
238  MAKE_PROPERTY(connected, is_connected);
239 
240  // This contains an identification of the general type of device. If
241  // this could not be determined, it is set to DC_unknown.
242  MAKE_PROPERTY(device_class, get_device_class);
243 
244  // Determine supported features
245  INLINE bool has_feature(Feature feature) const;
246 
247  // Getters for the various types of device data.
248  MAKE_PROPERTY2(tracker, has_tracker, get_tracker);
249  MAKE_PROPERTY2(battery, has_battery, get_battery);
250 
251  // Make device buttons and axes iterable
252  MAKE_SEQ_PROPERTY(buttons, get_num_buttons, get_button);
253  MAKE_SEQ_PROPERTY(axes, get_num_axes, get_axis);
254 
255  // Associate buttons/axes with symbolic handles.
256  INLINE void map_button(size_t index, ButtonHandle handle);
257  INLINE void map_axis(size_t index, Axis axis);
258  INLINE ButtonState find_button(ButtonHandle handle) const;
259  INLINE AxisState find_axis(Axis axis) const;
260 
261  // Enable rumble force-feedback effects
262  INLINE void set_vibration(double strong, double weak);
263 
264  INLINE void enable_pointer_events();
265  INLINE void disable_pointer_events();
266 
267  void poll();
268 
269  bool has_button_event() const;
270  PT(ButtonEventList) get_button_events();
271  bool has_pointer_event() const;
272  PT(PointerEventList) get_pointer_events();
273 
274  virtual void output(std::ostream &out) const;
275 
276 public:
277  static std::string format_device_class(DeviceClass dc);
278  static std::string format_axis(Axis axis);
279 
280 protected:
281  INLINE void enable_feature(Feature feature);
282 
283  // Called during the constructor to add new axes or buttons
284  int add_button(ButtonHandle handle);
285  int add_axis(Axis axis, int minimum, int maximum, bool centered);
286  int add_axis(Axis axis, int minimum, int maximum);
287 
288  int add_pointer(PointerType type, int id, bool primary = false);
289  void remove_pointer(int id);
290  void update_pointer(PointerData data, double time);
291  void pointer_moved(int id, double x, double y, double time);
292  void button_changed(int index, bool down);
293  void axis_changed(int index, int value);
294  void set_axis_value(int index, double state);
295 
296  void tracker_changed(const LPoint3 &pos, const LOrientation &orient, double time);
297 
298  virtual void do_set_vibration(double low, double high);
299  virtual void do_poll();
300 
301 public:
302  INLINE void set_connected(bool connected);
303 
304  void output_buttons(std::ostream &out) const;
305  void write_buttons(std::ostream &out, int indent_level) const;
306  void write_axes(std::ostream &out, int indent_level) const;
307 
308 protected:
310 
311  LightMutex _lock {"InputDevice"};
312 
313  std::string _name;
314  std::string _serial_number;
315  std::string _manufacturer;
316  DeviceClass _device_class = DeviceClass::unknown;
317  unsigned int _features = 0;
318  int _event_sequence = 0;
319  unsigned short _vendor_id = 0;
320  unsigned short _product_id = 0;
321  bool _is_connected = false;
322  bool _enable_pointer_events = false;
323  PT(ButtonEventList) _button_events;
324  PT(PointerEventList) _pointer_events;
325 
326  size_t _num_pointers = 0;
327  typedef pvector<PointerData> Pointers;
328  Pointers _pointers;
329 
330 PUBLISHED:
331  typedef pvector<ButtonState> Buttons;
332  typedef pvector<AxisState> Axes;
333  Buttons _buttons;
334  Axes _axes;
335 
336  PointerData _pointer_data;
337  BatteryData _battery_data;
338  TrackerData _tracker_data;
339 
340 public:
341  static TypeHandle get_class_type() {
342  return _type_handle;
343  }
344  static void init_type() {
345  TypedReferenceCount::init_type();
346  register_type(_type_handle, "InputDevice",
347  TypedReferenceCount::get_class_type());
348  }
349  virtual TypeHandle get_type() const {
350  return get_class_type();
351  }
352  virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
353 
354 private:
355  static TypeHandle _type_handle;
356 };
357 
358 INLINE std::ostream &operator << (std::ostream &out, const InputDevice &device) {
359  device.output(out);
360  return out;
361 }
362 
363 EXPCL_PANDA_DEVICE std::ostream &operator << (std::ostream &out, InputDevice::DeviceClass dc);
364 EXPCL_PANDA_DEVICE std::ostream &operator << (std::ostream &out, InputDevice::Axis axis);
365 
366 #include "inputDevice.I"
367 
368 #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(),...
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,...
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:53
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.