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