VR-Engage  2.2
Loading...
Searching...
No Matches
vreInputManager.h
Go to the documentation of this file.
1/******************************************************************************
2** Copyright (c) 2025 MAK Technologies, Inc.
3** All rights reserved.
4******************************************************************************/
5
6//! \file
7//! \brief Input management system for handling device input and action mapping
8
9#pragma once
10
11#include "vreInput/export.h"
13
14#include <vreUtil/delegate.h>
15#include <vreUtil/factory.h>
16
17#include <vrvUtil/DtVirtualBaseClass.h>
18
19#include <string>
20#include <vector>
21#include <unordered_map>
22#include <deque>
23#include <memory>
24#include <boost/signals2.hpp>
25
26namespace makVre
27{
28 //! Forward declarations
31 class DtInputDevice;
32 class DtValueTransform;
33 struct DtInputData;
34 //! \brief Structure representing an input action with a name and value
35 //!
36 //! This structure represents a logical action that can be triggered by an input device
37 //! and processed by an action handler.
38 struct DtAction
39 {
40 //! \brief Group name for categorizing actions (e.g., "movement", "combat")
41 std::string group;
42
43 //! \brief Name of the action to be performed
44 std::string name;
45
46 //! \brief Intensity or value of the action (range typically -1.0 to 1.0)
47 float value;
48 };
49
50 // Only for pairs of std::hash-able types for simplicity.
51 // You can of course template this struct to allow other hash functions
52 struct pair_hash {
53 template <class T1, class T2>
54 std::size_t operator () (const std::pair<T1, T2>& p) const {
55 auto h1 = std::hash<T1>{}(p.first);
56 auto h2 = std::hash<T2>{}(p.second);
57
58 // Mainly for demonstration purposes, i.e. works but is overly simple
59 // In the real world, use sth. like boost.hash_combine
60 return h1 ^ h2;
61 }
62 };
63
64 //! \brief Delegate type for handling action events
65 //! \param float The value/intensity of the action
67
68 using ActionHandlerMap = std::unordered_map<std::pair<std::string, std::string>, DtActionDelegate, pair_hash>;
69
70 //! \brief Delegate type for handling raw input data events
71 //! \param DtInputData The raw input data from a device
72 //! \return bool True if the input was handled, false to continue processing
74
75 //! \brief Central manager for input device handling, action mapping, and input processing
76 //!
77 //! This class manages the input device lifecycle, input processing, and mapping of
78 //! device inputs to logical actions. It provides a layered approach to input configuration,
79 //! allowing multiple mapping configurations to be active simultaneously with priority handling.
80 class VREINPUT_DLL DtVreInputManager : public makVrv::DtVirtualBaseClass
81 {
82 public:
83 //! \brief List type for storing managed input devices
84 using DeviceList = std::vector<std::unique_ptr<DtInputDevice>>;
85 //! \brief Structure representing a layer of input mapping configuration
86 //!
87 //! Each mapping layer contains configurations for one or more devices and can be
88 //! arranged in a stack to provide priority-based input handling.
90 {
91 //! \brief Source configuration file name
92 std::string config;
93
94 //! \brief Mapping group name within the configuration
95 std::string group;
96
97 //! \brief Map of device name/type to its mapping configuration
98 std::unordered_map<std::string, std::unique_ptr<DtDeviceMapping>> deviceMappings;
99
100 //! \brief If true, keep this layer at the top of the stack regardless of other layers
102
103 //! \brief If true, this layer remains active even when player controls are disabled
105 };
106 //! \brief Stack type for managing priority-ordered input mapping layers
107 using MappingStack = std::deque<MappingLayer>;
108
109 //! \brief Factory type for creating value transform objects
111
112 //! \brief Constructor for the input manager
113 //!
114 //! Initializes the input manager with the player station application context,
115 //! sets up value transform factories, and configures debug facilities.
116 //!
117 //! \param app Reference to the player station application that owns this manager
119 //! \brief Virtual destructor
120 //!
121 //! Cleans up debug callbacks and resources owned by the input manager.
122 virtual ~DtVreInputManager() override;
123
124 //! \brief Copy constructor (deleted)
125 //!
126 //! Input manager cannot be copied due to unique ownership of resources.
127 DtVreInputManager(const DtVreInputManager& mapping) = delete;
128
129 //! \brief Assignment operator (deleted)
130 //!
131 //! Input manager cannot be assigned due to unique ownership of resources.
133
134 //-----------------------Interface-------------------------------------
135
136 ////----Factory functions used by DeviceMappers
137
138 //! \brief Access the value transform factory used by device mappers
139 //!
140 //! Provides access to the factory that creates value transformation objects
141 //! used to modify input values (like scaling, inversion, etc.)
142 //!
143 //! \return Reference to the value transform factory
145
146 //----Startup/Shutdown operations
147
148 //! \brief Creates and initializes input devices from the provided list of device types
149 //!
150 //! This method should be called once at application startup to instantiate all the
151 //! input devices that will be used. Each device is created using the input device factory
152 //! and then initialized with this manager as context.
153 //!
154 //! \param hardwareHandlerList List of device type names to create and initialize
155 //! \return True if all devices were created successfully, false otherwise
156 virtual bool realizeHardwareHandlers(const std::vector<std::string>& hardwareHandlerList);
157
158 //! \brief Shuts down the input manager and releases all resources
159 //!
160 //! Clears all mapping layers, disconnects action handlers, and shuts down
161 //! all input devices. This should be called before application exit.
162 //!
163 //! \return True if shutdown was successful, false otherwise
164 virtual bool shutdown();
165
166
167 //----Configuration operations
168
169 //! \brief Creates and adds an input mapping layer to the mapping stack
170 //!
171 //! Loads mapping configuration from the specified config file and group,
172 //! and adds it to the mapping stack with the specified priority parameters.
173 //! If a layer with the same config and group already exists, it will not be added again.
174 //!
175 //! \param configName Name of the configuration file (without path) to load
176 //! \param group Group name within the configuration to activate
177 //! \param alwaysOnTop If true, layer will be kept at the top of the stack
178 //! \param alwaysEnabled If true, layer will remain active even when player controls are disabled
179 //! \return True if the layer was added successfully, false otherwise
180 virtual bool addMappingLayer(const std::string& configName, const std::string& group, bool alwaysOnTop, bool alwaysEnabled);
181
182 //! \brief Removes a mapping layer from the stack
183 //!
184 //! Finds and removes a mapping layer with the specified configuration and group name.
185 //! If no matching layer is found, this operation has no effect.
186 //!
187 //! \param configName Name of the configuration file that was used to create the layer
188 //! \param group Group name within the configuration to remove
189 virtual void removeMappingLayer(const std::string& configName, const std::string& group);
190
191 //! \brief Sets a raw input data handler
192 //!
193 //! This handler will be called before any mapping layer processing occurs,
194 //! allowing for pre-processing or interception of raw input data.
195 //!
196 //! \param inputDelegate Delegate to be called with input data before mapping occurs
197 virtual void setRawInputHandler(const DtInputDelegate& inputDelegate);
198
199 //! \brief Removes the previously set raw input handler
200 //!
201 //! After this call, raw input will no longer be pre-processed and will go
202 //! directly to the mapping layers.
203 virtual void removeRawInputHandler();
204
205
206 //----Runtime operations
207
208 //! \brief Updates the input system for the current frame
209 //!
210 //! This method should be called once per frame to allow devices and mappings
211 //! to update their state and process time-dependent operations.
212 //!
213 //! \param dt Delta time in seconds since the last frame
214 virtual void tick(double dt);
215
216 //! \brief Processes raw input data from a device
217 //!
218 //! Called by input devices when they receive input to be processed. This method
219 //! handles passing the data to the raw input handler (if set) and through the mapping
220 //! layers based on device type and name until it is processed or falls through.
221 //!
222 //! \param data The input data structure containing all input information
223 //! \return True if the input was processed by a handler, false if it was not handled
224 virtual bool processInput(const DtInputData& data);
225
226
227 //---Accessors to internal data structures, may be useful
228
229 //! \brief Finds an input device by its numeric ID
230 //!
231 //! \param id The numeric ID of the device to find
232 //! \return Reference to the unique pointer containing the device
233 virtual const std::unique_ptr<DtInputDevice>& findDevice(int id) const;
234
235 //! \brief Gets the list of all input devices
236 //!
237 //! \return Reference to the list of all input devices managed by this manager
238 virtual const DeviceList& deviceList() const;
239
240 //! \brief Gets the full path to the input settings directory
241 //!
242 //! Returns the directory where input configuration files are stored.
243 //! This path is resolved based on the application's path configuration.
244 //!
245 //! \return String containing the full path to the input settings directory
246 virtual std::string inputSettingsPath() const;
247
248 //! \brief Gets the current simulation time
249 //!
250 //! \return Current simulation time in seconds
251 virtual double simulationTime() const;
252
253 //! \brief Gets the player station application associated with this manager
254 //!
255 //! \return Reference to the player station application
257
258
259 //----Action handling
260
261 //! \brief Registers a handler for a named action
262 //!
263 //! Associates the specified action name with a delegate that will be called
264 //! whenever that action is triggered by input mappings. The group and action
265 //! name combination uniquely identifies the handler in the system.
266 //!
267 //! \param group Group name for categorizing the action (e.g., "movement", "combat", "ui")
268 //! \param action Name of the action to register a handler for
269 //! \param handler Delegate to be called when the action is triggered
270 virtual void addActionHandler(const std::string& group, const std::string& action, const DtActionDelegate& handler);
271
272 //! \brief Removes a previously registered action handler
273 //!
274 //! Removes the handler associated with the specified group and action name.
275 //! If no handler is registered for the action, this has no effect.
276 //!
277 //! \param group Group name for categorizing the action
278 //! \param action Name of the action to remove the handler for
279 virtual void removeActionHandler(const std::string& group, const std::string& action);
280
281 //! \brief Checks if an action has a registered handler
282 //!
283 //! Determines whether the specified group and action name combination has a handler registered.
284 //!
285 //! \param group Group name for categorizing the action
286 //! \param action Name of the action to check
287 //! \return True if the action has a handler, false otherwise
288 virtual bool isActionApplicable(const std::string& group, const std::string& action) const;
289
290 //! \brief Processes an action by calling its registered handler
291 //!
292 //! This is called by input mapping evaluators when an action is triggered.
293 //! The method assumes that the action is applicable (has a registered handler).
294 //! Logs actions for debugging if action logging is enabled.
295 //!
296 //! \param action The action structure containing the name and value
297 virtual void handleAction(const DtAction& action);
298
299 //! \brief Checks if player controls are currently enabled
300 //!
301 //! When player controls are disabled, only mapping layers with alwaysEnabled=true
302 //! will be processed.
303 //!
304 //! \return True if player controls are enabled, false otherwise
305 virtual bool isPlayerControlsEnabled() const;
306
307 //! \brief Sets whether player controls are enabled
308 //!
309 //! Enables or disables player controls, affecting which mapping layers are active.
310 //!
311 //! \param enabled True to enable player controls, false to disable
312 virtual void setPlayerControlsEnabled(bool enabled);
313
314 //----Debugging
315
316 //! \brief Checks if input event logging is enabled
317 //!
318 //! \return True if input events are being logged, false otherwise
319 virtual bool loggingEvents() const;
320
321 //! \brief Callback for the debug menu
322 //!
323 //! Renders debug UI options for the input system when accessed through
324 //! the debug menu (Shift-F4). Allows toggling of input event logging and
325 //! viewing input event history.
326 virtual void debugMenuCallback();
327
328 //! \brief Gets the action handlers map (for debugging/configuration purposes)
329 //!
330 //! \return Constant reference to the action handlers map
332
333 //! \brief Gets the mapping stack (for debugging/configuration purposes)
334 //!
335 //! \return Constant reference to the mapping stack
336 const MappingStack& getMappingStack() const { return myMappingStack; }
337 protected:
338 //! \brief Reference to the parent player station application
340
341 //! \brief List of all input devices managed by this manager
343
344 //! \brief Stack of mapping layers in priority order (front = highest priority)
346
347 //! \brief Map of action names to their handler delegates
349
350 //! \brief Optional delegate for handling raw input before mapping
352
353 //! \brief Factory for creating value transformation objects
355
356 //! \brief Path to the directory containing input configuration files
358
359 //! \brief Flag indicating if player controls are currently enabled
361
362 //! \brief Flag indicating if the simulation is currently playing
364
365 // For debugging: enable through Shift-F4 Debug Menu
366 //! \brief Flag indicating if input event logging is enabled
368
369 //! \brief Counter for assigning unique IDs to logged events
371
372 //! \brief Map of event IDs to their log messages
373 std::map<int, std::string> myLatestEventLog;
374
375 //! \brief Flag indicating if direct action logging is enabled
377
378 //! \brief Map of event IDs to their direct action log messages
379 std::map<int, std::vector<std::string>> myLatestDirectActionLog;
380
381 //! \brief Queue of tick-based action log messages
382 std::deque<std::string> myLatestsTickedActionLog;
383
384 //! \brief Input configuration viewer instance
385 std::unique_ptr<DtInputConfigViewer> myInputConfigViewer;
386 };
387
388} //::makVre
Modern delegate class that can bind and invoke callables with any number of parameters.
Definition delegate.h:31
Factory class for creating objects of different derived types.
Definition factory.h:79
ImGui-based input configuration viewer for the debug menu.
Definition inputConfigViewer.h:44
Abstract base class for hardware input device implementations.
Definition inputDevice.h:25
Top-level class representing the VR-Engage application.
Definition playerStationApp.h:163
Abstract base class for transforming input values.
Definition valueTransform.h:24
DtVreInputManager(const DtVreInputManager &mapping)=delete
Copy constructor (deleted)
virtual void debugMenuCallback()
Callback for the debug menu.
DtPlayerStationApp & myApp
Reference to the parent player station application.
Definition vreInputManager.h:339
virtual const std::unique_ptr< DtInputDevice > & findDevice(int id) const
Finds an input device by its numeric ID.
virtual ~DtVreInputManager() override
Virtual destructor.
std::deque< std::string > myLatestsTickedActionLog
Queue of tick-based action log messages.
Definition vreInputManager.h:382
DtVreInputManager & operator=(const DtVreInputManager &)=delete
Assignment operator (deleted)
std::deque< MappingLayer > MappingStack
Stack type for managing priority-ordered input mapping layers.
Definition vreInputManager.h:107
virtual void tick(double dt)
Updates the input system for the current frame.
DeviceList myDevices
List of all input devices managed by this manager.
Definition vreInputManager.h:342
const ActionHandlerMap & getActionHandlers() const
Gets the action handlers map (for debugging/configuration purposes)
Definition vreInputManager.h:331
DtFactory< DtValueTransform > DtValueTransformFactory
Factory type for creating value transform objects.
Definition vreInputManager.h:110
int myLastEventDebugId
Counter for assigning unique IDs to logged events.
Definition vreInputManager.h:370
virtual bool shutdown()
Shuts down the input manager and releases all resources.
virtual DtValueTransformFactory & valueTransformFactory() const
Access the value transform factory used by device mappers.
const MappingStack & getMappingStack() const
Gets the mapping stack (for debugging/configuration purposes)
Definition vreInputManager.h:336
virtual void removeActionHandler(const std::string &group, const std::string &action)
Removes a previously registered action handler.
virtual void addActionHandler(const std::string &group, const std::string &action, const DtActionDelegate &handler)
Registers a handler for a named action.
MappingStack myMappingStack
Stack of mapping layers in priority order (front = highest priority)
Definition vreInputManager.h:345
virtual double simulationTime() const
Gets the current simulation time.
std::vector< std::unique_ptr< DtInputDevice > > DeviceList
List type for storing managed input devices.
Definition vreInputManager.h:84
virtual void removeMappingLayer(const std::string &configName, const std::string &group)
Removes a mapping layer from the stack.
bool myIsPlaying
Flag indicating if the simulation is currently playing.
Definition vreInputManager.h:363
virtual bool loggingEvents() const
Checks if input event logging is enabled.
std::unique_ptr< DtInputConfigViewer > myInputConfigViewer
Input configuration viewer instance.
Definition vreInputManager.h:385
virtual const DeviceList & deviceList() const
Gets the list of all input devices.
virtual void handleAction(const DtAction &action)
Processes an action by calling its registered handler.
DtValueTransformFactory myValueTransformFactory
Factory for creating value transformation objects.
Definition vreInputManager.h:354
std::string myInputSettingsPath
Path to the directory containing input configuration files.
Definition vreInputManager.h:357
bool myLoggingEvents
Flag indicating if input event logging is enabled.
Definition vreInputManager.h:367
std::map< int, std::vector< std::string > > myLatestDirectActionLog
Map of event IDs to their direct action log messages.
Definition vreInputManager.h:379
DtPlayerStationApp & app() const
Gets the player station application associated with this manager.
virtual bool isPlayerControlsEnabled() const
Checks if player controls are currently enabled.
DtInputDelegate myRawInputHandler
Optional delegate for handling raw input before mapping.
Definition vreInputManager.h:351
bool myPlayerControlsEnabled
Flag indicating if player controls are currently enabled.
Definition vreInputManager.h:360
virtual bool addMappingLayer(const std::string &configName, const std::string &group, bool alwaysOnTop, bool alwaysEnabled)
Creates and adds an input mapping layer to the mapping stack.
virtual std::string inputSettingsPath() const
Gets the full path to the input settings directory.
virtual void removeRawInputHandler()
Removes the previously set raw input handler.
bool myLoggingDirectActions
Flag indicating if direct action logging is enabled.
Definition vreInputManager.h:376
virtual bool processInput(const DtInputData &data)
Processes raw input data from a device.
virtual void setPlayerControlsEnabled(bool enabled)
Sets whether player controls are enabled.
virtual bool realizeHardwareHandlers(const std::vector< std::string > &hardwareHandlerList)
Creates and initializes input devices from the provided list of device types.
ActionHandlerMap myActionHandlers
Map of action names to their handler delegates.
Definition vreInputManager.h:348
std::map< int, std::string > myLatestEventLog
Map of event IDs to their log messages.
Definition vreInputManager.h:373
DtVreInputManager(DtPlayerStationApp &app)
Constructor for the input manager.
virtual void setRawInputHandler(const DtInputDelegate &inputDelegate)
Sets a raw input data handler.
virtual bool isActionApplicable(const std::string &group, const std::string &action) const
Checks if an action has a registered handler.
Defines mapping between device inputs and actions.
Provides a template-based factory system for object creation.
Defines DLL export/import macros for the vreInput library.
#define VREINPUT_DLL
DLL export/import macro for the vreInput library.
Definition export.h:25
Include export definitions for this library.
Definition glsVreMessageUtil.h:49
std::unordered_map< std::pair< std::string, std::string >, DtActionDelegate, pair_hash > ActionHandlerMap
Definition vreInputManager.h:68
DtDelegate< void, float > DtActionDelegate
Delegate type for handling action events.
Definition vreInputManager.h:66
DtDelegate< bool, const DtInputData & > DtInputDelegate
Delegate type for handling raw input data events.
Definition vreInputManager.h:73
Structure representing an input action with a name and value.
Definition vreInputManager.h:39
std::string group
Group name for categorizing actions (e.g., "movement", "combat")
Definition vreInputManager.h:41
float value
Intensity or value of the action (range typically -1.0 to 1.0)
Definition vreInputManager.h:47
std::string name
Name of the action to be performed.
Definition vreInputManager.h:44
Structure for transferring input data through the input system.
Definition inputData.h:89
Structure representing a layer of input mapping configuration.
Definition vreInputManager.h:90
std::string group
Mapping group name within the configuration.
Definition vreInputManager.h:95
bool alwaysOnTop
If true, keep this layer at the top of the stack regardless of other layers.
Definition vreInputManager.h:101
std::unordered_map< std::string, std::unique_ptr< DtDeviceMapping > > deviceMappings
Map of device name/type to its mapping configuration.
Definition vreInputManager.h:98
std::string config
Source configuration file name.
Definition vreInputManager.h:92
bool alwaysEnabled
If true, this layer remains active even when player controls are disabled.
Definition vreInputManager.h:104
Definition vreInputManager.h:52
std::size_t operator()(const std::pair< T1, T2 > &p) const
Definition vreInputManager.h:54