Overte C++ Documentation
UserInputMapper.h
1 //
2 // Created by Sam Gateau on 4/27/15.
3 // Copyright 2015 High Fidelity, Inc.
4 // Copyright 2023 Overte e.V.
5 //
6 // Distributed under the Apache License, Version 2.0.
7 // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
8 // SPDX-License-Identifier: Apache-2.0
9 //
10 
11 #pragma once
12 #ifndef hifi_UserInputMapper_h
13 #define hifi_UserInputMapper_h
14 
15 #include <glm/glm.hpp>
16 
17 #include <unordered_set>
18 #include <functional>
19 #include <memory>
20 #include <mutex>
21 
22 #include <QQueue>
23 #include <QtQml/QJSValue>
24 
25 #include <DependencyManager.h>
26 #include <RegisteredMetaTypes.h>
27 
28 #include "Forward.h"
29 #include "Pose.h"
30 #include "Input.h"
31 #include "InputDevice.h"
32 #include "DeviceProxy.h"
33 #include "StandardControls.h"
34 #include "Actions.h"
35 #include "StateController.h"
36 
37 class ScriptEngine;
38 class ScriptManager;
39 class ScriptValue;
40 
41 namespace controller {
42 
43  class RouteBuilderProxy;
44  class MappingBuilderProxy;
45 
46  class UserInputMapper : public QObject, public Dependency {
47  Q_OBJECT
48  SINGLETON_DEPENDENCY
49  Q_ENUMS(Action)
50 
51  public:
52  // FIXME move to unordered set / map
53  using EndpointToInputMap = std::map<EndpointPointer, Input>;
54  using MappingNameMap = std::map<QString, MappingPointer>;
55  using MappingDeviceMap = std::map<uint16_t, MappingPointer>;
56  using MappingStack = std::list<MappingPointer>;
57  using InputToEndpointMap = std::map<Input, EndpointPointer>;
58  using EndpointSet = std::unordered_set<EndpointPointer>;
59  using EndpointPair = std::pair<EndpointPointer, EndpointPointer>;
60  using EndpointPairMap = std::map<EndpointPair, EndpointPointer>;
61  using DevicesMap = std::map<int, InputDevice::Pointer>;
62  using uint16 = uint16_t;
63  using uint32 = uint32_t;
64 
65  static const uint16_t STANDARD_DEVICE;
66  static const uint16_t ACTIONS_DEVICE;
67  static const uint16_t STATE_DEVICE;
68 
69  UserInputMapper();
70  virtual ~UserInputMapper();
71 
72 
73  static void registerControllerTypes(ScriptEngine* engine);
74 
75  void registerDevice(InputDevice::Pointer device);
76  InputDevice::Pointer getDevice(const Input& input);
77  QString getDeviceName(uint16 deviceID);
78 
79  Input::NamedVector getAvailableInputs(uint16 deviceID) const;
80  Input::NamedVector getActionInputs() const { return getAvailableInputs(ACTIONS_DEVICE); }
81  Input::NamedVector getStandardInputs() const { return getAvailableInputs(STANDARD_DEVICE); }
82 
83  int findDevice(QString name) const;
84  QVector<QString> getDeviceNames();
85  Input findDeviceInput(const QString& inputName) const;
86 
87  QVector<Action> getAllActions() const;
88  QString getActionName(Action action) const;
89  QString getStandardPoseName(uint16_t pose);
90  float getActionState(Action action) const;
91  bool getActionStateValid(Action action) const;
92  Pose getPoseState(Action action) const;
93  int findAction(const QString& actionName) const;
94  QVector<QString> getActionNames() const;
95  Input inputFromAction(Action action) const { return getActionInputs()[toInt(action)].first; }
96 
97  void setActionState(Action action, float value, bool valid = true);
98  void deltaActionState(Action action, float delta, bool valid = true);
99  void setActionState(Action action, const Pose& value) { _poseStates[toInt(action)] = value; }
100  bool triggerHapticPulse(float strength, float duration, uint16_t index);
101  bool triggerHapticPulseOnDevice(uint16 deviceID, float strength, float duration, uint16_t index);
102 
103  static Input makeStandardInput(controller::StandardButtonChannel button);
104  static Input makeStandardInput(controller::StandardAxisChannel axis);
105  static Input makeStandardInput(controller::StandardPoseChannel pose);
106 
107  void removeDevice(int device);
108 
109  // Update means go grab all the device input channels and update the output channel values
110  void update(float deltaTime);
111 
112  const DevicesMap& getDevices() { return _registeredDevices; }
113  uint16 getStandardDeviceID() const { return STANDARD_DEVICE; }
114  InputDevice::Pointer getStandardDevice() { return _registeredDevices[getStandardDeviceID()]; }
115  StateController::Pointer getStateDevice() { return _stateDevice; }
116 
117  MappingPointer newMapping(const QString& mappingName);
118  MappingPointer parseMapping(const QString& json);
119  MappingPointer loadMapping(const QString& jsonFile, bool enable = false);
120  MappingPointer loadMappings(const QStringList& jsonFiles);
121 
122  void loadDefaultMapping(uint16 deviceID);
123  void enableMapping(const QString& mappingName, bool enable = true);
124 
125  void setInputCalibrationData(const InputCalibrationData& data) { inputCalibrationData = data; }
126  const InputCalibrationData& getInputCalibrationData() { return inputCalibrationData; }
127 
128  void unloadMappings(const QStringList& jsonFiles);
129  void unloadMapping(const QString& jsonFile);
130 
140  void scheduleScriptEndpointCleanup(std::shared_ptr<ScriptManager> manager);
141 
142  AxisValue getValue(const Input& input) const;
143  Pose getPose(const Input& input) const;
144 
145  // perform an action when the UserInputMapper mutex is acquired.
146  using Locker = std::unique_lock<std::recursive_mutex>;
147  template <typename F>
148  void withLock(F&& f) { Locker locker(_lock); f(); }
149 
150  EndpointPointer endpointFor(const Input& endpoint) const;
151 
152  signals:
153  void actionEvent(int action, float state);
154  void inputEvent(int input, float state);
155  void hardwareChanged();
156 
157  protected:
158  // GetFreeDeviceID should be called before registering a device to use an ID not used by a different device.
159  uint16 getFreeDeviceID() { return _nextFreeDeviceID++; }
160  DevicesMap _registeredDevices;
161  StateController::Pointer _stateDevice;
162  uint16 _nextFreeDeviceID = STANDARD_DEVICE + 1;
163 
164  std::vector<float> _actionStates = std::vector<float>(toInt(Action::NUM_ACTIONS), 0.0f);
165  std::vector<float> _actionScales = std::vector<float>(toInt(Action::NUM_ACTIONS), 1.0f);
166  std::vector<float> _lastActionStates = std::vector<float>(toInt(Action::NUM_ACTIONS), 0.0f);
167  std::vector<bool> _actionStatesValid = std::vector<bool>(toInt(Action::NUM_ACTIONS), false);
168  std::vector<Pose> _poseStates = std::vector<Pose>(toInt(Action::NUM_ACTIONS));
169  std::vector<AxisValue> _lastStandardStates = std::vector<AxisValue>();
170 
171  static AxisValue getValue(const EndpointPointer& endpoint, bool peek = false);
172  static Pose getPose(const EndpointPointer& endpoint, bool peek = false);
173 
174  friend class RouteBuilderProxy;
175  friend class MappingBuilderProxy;
176 
177  void runMappings();
178 
179  static void applyRoutes(const RouteList& route);
180  static bool applyRoute(const RoutePointer& route, bool force = false);
181  void enableMapping(const MappingPointer& mapping);
182  void disableMapping(const MappingPointer& mapping);
183 
191  void runScriptEndpointCleanup();
192 
193  EndpointPointer endpointFor(const QJSValue& endpoint);
194  EndpointPointer endpointFor(const ScriptValue& endpoint);
195  EndpointPointer compositeEndpointFor(EndpointPointer first, EndpointPointer second);
196  ConditionalPointer conditionalFor(const QJSValue& endpoint);
197  ConditionalPointer conditionalFor(const ScriptValue& endpoint);
198  ConditionalPointer conditionalFor(const Input& endpoint) const;
199 
200  MappingPointer parseMapping(const QJsonValue& json);
201  RoutePointer parseRoute(const QJsonValue& value);
202  EndpointPointer parseDestination(const QJsonValue& value);
203  EndpointPointer parseSource(const QJsonValue& value);
204  EndpointPointer parseAxis(const QJsonValue& value);
205  EndpointPointer parseAny(const QJsonValue& value);
206  EndpointPointer parseEndpoint(const QJsonValue& value);
207  ConditionalPointer parseConditional(const QJsonValue& value);
208 
209  static FilterPointer parseFilter(const QJsonValue& value);
210  static FilterList parseFilters(const QJsonValue& value);
211 
212  InputToEndpointMap _endpointsByInput;
213  EndpointToInputMap _inputsByEndpoint;
214  EndpointPairMap _compositeEndpoints;
215 
216  MappingNameMap _mappingsByName;
217  MappingDeviceMap _mappingsByDevice;
218 
219  RouteList _deviceRoutes;
220  RouteList _standardRoutes;
221 
222  QSet<QString> _loadedRouteJsonFiles;
223 
224  InputCalibrationData inputCalibrationData;
225 
226  // Contains pointers to script engines that are requesting callback cleanup during their shutdown process
227  QQueue<std::shared_ptr<ScriptManager>> scriptManagersRequestingCleanup;
228 
229  mutable std::recursive_mutex _lock;
230  };
231 
232 }
233 
234 Q_DECLARE_METATYPE(controller::Input::NamedPair)
235 Q_DECLARE_METATYPE(controller::Pose)
236 Q_DECLARE_METATYPE(QVector<controller::Input::NamedPair>)
237 Q_DECLARE_METATYPE(controller::Input)
238 Q_DECLARE_METATYPE(controller::Action)
239 Q_DECLARE_METATYPE(QVector<controller::Action>)
240 Q_DECLARE_METATYPE(controller::Hand)
241 
242 // Cheating.
243 using UserInputMapper = controller::UserInputMapper;
244 
245 #endif // hifi_UserInputMapper_h
Provides an engine-independent interface for a scripting engine.
Definition: ScriptEngine.h:93
Manages a single scripting engine.
Definition: ScriptManager.h:281
[ScriptInterface] Provides an engine-independent interface for QScriptValue
Definition: ScriptValue.h:40