CUGL 1.3
Cornell University Game Library
CUInput.h
1 //
2 // CUInput.h
3 // Cornell University Game Library (CUGL)
4 //
5 // This class is an event dispatcher that works as a singleton service. That
6 // is, it is singleton that allows us to access a modular collection of other
7 // singletons (in this case input devices) that implement a common interface.
8 // This makes sense for singletons that need flexible functionality like input
9 // devices and asset managers.
10 //
11 // We use templates to completely decouple the input devices from this class.
12 // That is, this class does not need to know the type of any new input device.
13 // Instead, you attach the devices by a template, which hashes the device by
14 // the type id. When the user requests a device, the type of the device is
15 // hashed to retrieve the singleton.
16 //
17 // CUGL MIT License:
18 // This software is provided 'as-is', without any express or implied
19 // warranty. In no event will the authors be held liable for any damages
20 // arising from the use of this software.
21 //
22 // Permission is granted to anyone to use this software for any purpose,
23 // including commercial applications, and to alter it and redistribute it
24 // freely, subject to the following restrictions:
25 //
26 // 1. The origin of this software must not be misrepresented; you must not
27 // claim that you wrote the original software. If you use this software
28 // in a product, an acknowledgment in the product documentation would be
29 // appreciated but is not required.
30 //
31 // 2. Altered source versions must be plainly marked as such, and must not
32 // be misrepresented as being the original software.
33 //
34 // 3. This notice may not be removed or altered from any source distribution.
35 //
36 // Author: Walker White
37 // Version: 7/8/16
38 
39 #ifndef __CU_INPUT_H__
40 #define __CU_INPUT_H__
41 
42 #include <cugl/base/CUBase.h>
43 #include <cugl/util/CUTimestamp.h>
44 #include <unordered_map>
45 #include <unordered_set>
46 #include <vector>
47 #include <typeindex>
48 
49 #ifndef UINT32_MAX
50 #define UINT32_MAX (0xffffffff)
51 #endif
52 
53 namespace cugl {
54 
55 class InputDevice;
56 
57 #pragma mark -
58 
77 class Input {
78 #pragma mark Values
79 protected:
81  static Input* _singleton;
82 
86  Uint32 _roffset;
87 
89  std::unordered_map<std::type_index, InputDevice*> _devices;
90 
92  std::unordered_map<Uint32,std::unordered_set<std::type_index>> _subscribers;
93 
94 #pragma mark Constructor
95 
98  Input() {}
99 
103  ~Input() { shutdown(); }
104 
105 #pragma mark Application Access
106 
117  static bool start();
118 
128  static void stop();
129 
142  static Input* get();
143 
152  void clear();
153 
167  bool update(SDL_Event event);
168 
169  // All of the above methods should only be accessed by this class
170  friend class Application;
171 
172 #pragma mark Internal Helpers
173 
185  bool registerDevice(std::type_index key, InputDevice* input);
186 
197  InputDevice* unregisterDevice(std::type_index key);
198 
205  void shutdown();
206 
207 
208 #pragma mark Service Access
209 public:
219  template <typename T>
220  static T* get() {
221  if (!_singleton) { return nullptr; }
222  std::type_index indx = std::type_index(typeid(T));
223  auto it = _singleton->_devices.find(indx);
224  if (it != _singleton->_devices.end()) {
225  return static_cast<T*>(it->second);
226  }
227  return nullptr;
228  }
229 
240  template <typename T>
241  static inline bool activate() {
242  if (!_singleton) { return false; }
243  std::type_index indx = std::type_index(typeid(T));
244  auto it = _singleton->_devices.find(indx);
245  // Return true if we are already active
246  if (it != _singleton->_devices.end()) {
247  return true;
248  } else {
249  T* alloc = new T();
250  // Fail gracefully if the user gave us a bad class.
251  if (alloc->init() && _singleton->registerDevice(indx,dynamic_cast<InputDevice*>(alloc))) {
252  return true;
253  } else {
254  delete alloc;
255  }
256  }
257  return false;
258  }
259 
270  template <typename T>
271  static bool deactivate() {
272  if (!_singleton) { return false; }
273  std::type_index indx = std::type_index(typeid(T));
274  auto it = _singleton->_devices.find(indx);
275  // Fail if we are not active
276  if (it != _singleton->_devices.end()) {
277  delete static_cast<T*>(_singleton->unregisterDevice(indx));
278  return true;
279  }
280  return false;
281  }
282 
283 };
284 
285 
286 #pragma mark -
287 
298 class InputDevice {
299 protected:
301  Uint32 _focus;
302 
303 public:
305  static const Uint32 RESERVED_KEY = UINT32_MAX;
306 
312  Uint32 currentFocus() const { return _focus; }
313 
322  virtual bool requestFocus(Uint32 key) { _focus = key; return true; }
323 
328 
329 protected:
336  InputDevice() : _focus(UINT32_MAX) {}
337 
341  virtual ~InputDevice() { }
342 
348  virtual bool init() { return true; }
349 
355  virtual void dispose() {}
356 
363  virtual void clearState() = 0;
364 
376  virtual bool updateState(const SDL_Event& event, const Timestamp& stamp) = 0;
377 
388  virtual void queryEvents(std::vector<Uint32>& eventset) = 0;
389 
390  // Only Input can access these methods.
391  friend class Input;
392 };
393 
394 }
395 
396 #endif /* __CU_INPUT_H__ */
cugl::Input::_reference
Timestamp _reference
Definition: CUInput.h:84
cugl::Input::get
static Input * get()
cugl::InputDevice::releaseFocus
void releaseFocus()
Definition: CUInput.h:327
cugl::Input::update
bool update(SDL_Event event)
cugl::Application
Definition: CUApplication.h:83
cugl::Input::_singleton
static Input * _singleton
Definition: CUInput.h:81
cugl::Timestamp
Definition: CUTimestamp.h:61
cugl::Input::shutdown
void shutdown()
cugl::Input::Input
Input()
Definition: CUInput.h:98
cugl::Input::~Input
~Input()
Definition: CUInput.h:103
cugl::InputDevice::dispose
virtual void dispose()
Definition: CUInput.h:355
cugl::Input::start
static bool start()
cugl::InputDevice::init
virtual bool init()
Definition: CUInput.h:348
cugl::InputDevice::InputDevice
InputDevice()
Definition: CUInput.h:336
cugl::Input::deactivate
static bool deactivate()
Definition: CUInput.h:271
cugl::Input::activate
static bool activate()
Definition: CUInput.h:241
cugl::InputDevice::RESERVED_KEY
static const Uint32 RESERVED_KEY
Definition: CUInput.h:305
cugl::Input::stop
static void stop()
cugl::InputDevice::clearState
virtual void clearState()=0
cugl::Input::registerDevice
bool registerDevice(std::type_index key, InputDevice *input)
cugl::InputDevice::_focus
Uint32 _focus
Definition: CUInput.h:301
cugl::InputDevice::currentFocus
Uint32 currentFocus() const
Definition: CUInput.h:312
cugl::Input::_devices
std::unordered_map< std::type_index, InputDevice * > _devices
Definition: CUInput.h:89
cugl::Input
Definition: CUInput.h:77
cugl::Input::_subscribers
std::unordered_map< Uint32, std::unordered_set< std::type_index > > _subscribers
Definition: CUInput.h:92
cugl::InputDevice::queryEvents
virtual void queryEvents(std::vector< Uint32 > &eventset)=0
cugl::InputDevice
Definition: CUInput.h:298
cugl::Input::_roffset
Uint32 _roffset
Definition: CUInput.h:86
cugl::InputDevice::requestFocus
virtual bool requestFocus(Uint32 key)
Definition: CUInput.h:322
cugl::InputDevice::~InputDevice
virtual ~InputDevice()
Definition: CUInput.h:341
cugl::Input::clear
void clear()
cugl::InputDevice::updateState
virtual bool updateState(const SDL_Event &event, const Timestamp &stamp)=0
cugl::Input::unregisterDevice
InputDevice * unregisterDevice(std::type_index key)