Olympe Engine 2.0
2D Game Engine with ECS Architecture
Loading...
Searching...
No Matches
InputDevice.h
Go to the documentation of this file.
1/*
2Olympe Engine V2 - 2026
3Input System Refactor
4
5This file defines the new input device abstraction layer including:
6- InputDeviceSlot: Logical device representation
7- InputProfile: Device-specific configuration
8- ActionMap: Context-aware action grouping
9- InputDeviceManager: Device assignment and management
10*/
11
12#pragma once
13
14#include <string>
15#include <unordered_map>
16#include <vector>
17#include <memory>
18#include <SDL3/SDL.h>
19
20// Forward declarations
21class InputProfile;
22class ActionMap;
23
24//==============================================================================
25// Input Device Types
26//==============================================================================
27
28enum class InputDeviceType {
29 None,
32};
33
34enum class InputType {
35 Button,
36 Key,
37 Axis,
38 Stick,
39 Trigger,
42};
43
44enum class ActionMapContext {
46 Editor,
47 UI,
48 System
49};
50
51//==============================================================================
52// Input Binding Structures
53//==============================================================================
54
57
58 // Key/button indices
59 int primaryInput = -1; // SDL_Scancode, button index, axis index
60 int alternateInput = -1; // Optional alternate binding
61
62 // Axis-specific settings
63 float axisScale = 1.0f;
64 float axisDeadzone = 0.15f;
65 bool invertAxis = false;
66
67 // Trigger settings
68 float triggerThreshold = 0.1f;
69
70 // Description
71 std::string comment;
72
73 InputBinding() = default;
74};
75
76//==============================================================================
77// Input Profile - Device-specific configuration
78//==============================================================================
79
81public:
82 InputProfile() = default;
83 InputProfile(const std::string& name, InputDeviceType type)
84 : profileName(name), deviceType(type) {}
85
86 // Profile identification
87 std::string profileName;
89 std::string description;
90
91 // Action mappings (action name -> input binding)
92 std::unordered_map<std::string, InputBinding> actionMappings;
93
94 // Settings
95 float deadzone = 0.15f;
96 float sensitivity = 1.0f;
97 bool invertYAxis = false;
98 bool validateOverlaps = true; // For keyboard profiles
99
100 // Add an action mapping
101 void AddAction(const std::string& actionName, const InputBinding& binding) {
103 }
104
105 // Get action binding (returns nullptr if not found)
106 const InputBinding* GetActionBinding(const std::string& actionName) const {
107 auto it = actionMappings.find(actionName);
108 if (it != actionMappings.end()) {
109 return &it->second;
110 }
111 return nullptr;
112 }
113
114 // Validate keyboard profile for overlapping keys
115 bool ValidateNoOverlaps() const;
116
117 // Initialize default bindings
118 void InitializeDefaults();
119};
120
121//==============================================================================
122// Input Device Slot - Logical device representation
123//==============================================================================
124
127 int deviceIndex = -1; // SDL_JoystickID for joysticks, -1 for keyboard-mouse
128 short assignedPlayerID = -1; // -1 if unassigned
129 bool isConnected = false;
130 std::string deviceName;
131 std::shared_ptr<InputProfile> profile; // Device-specific configuration
132
133 InputDeviceSlot() = default;
134
135 InputDeviceSlot(InputDeviceType t, int idx, const std::string& name)
137
138 bool IsAssigned() const { return assignedPlayerID >= 0; }
139 bool IsAvailable() const { return isConnected && !IsAssigned(); }
140};
141
142//==============================================================================
143// Action Map - Context-aware action grouping
144//==============================================================================
145
147public:
148 ActionMap() = default;
149 ActionMap(const std::string& name, ActionMapContext ctx, int prio = 0)
150 : mapName(name), context(ctx), priority(prio) {}
151
152 std::string mapName;
154 int priority = 0; // Higher = processed first (0-100)
155 bool exclusive = false; // Block lower priority maps when active
156 bool enabledByDefault = true;
157 std::string description;
158
159 std::vector<std::string> actions; // List of action names in this map
160
161 void AddAction(const std::string& actionName) {
162 actions.push_back(actionName);
163 }
164
165 bool ContainsAction(const std::string& actionName) const {
166 for (const auto& action : actions) {
167 if (action == actionName) return true;
168 }
169 return false;
170 }
171};
172
173//==============================================================================
174// Input Device Manager - Device assignment and management
175//==============================================================================
176
178public:
181
182 // Singleton access
185 return instance;
186 }
187
188 // Device registration (called when devices connect)
190 void UnregisterDevice(int deviceIndex);
191
192 // Auto-assignment (prefers joysticks, then keyboard-mouse)
194
195 // Manual assignment
196 bool AssignDeviceToPlayer(int deviceIndex, short playerID);
197 bool UnassignDevice(short playerID);
198
199 // Query
201 const InputDeviceSlot* GetDeviceForPlayer(short playerID) const;
202 std::vector<InputDeviceSlot*> GetAvailableDevices();
203 std::vector<InputDeviceSlot*> GetAllDevices();
204
205 // Profile management
206 void AddProfile(std::shared_ptr<InputProfile> profile);
207 std::shared_ptr<InputProfile> GetProfile(const std::string& profileName);
208 void SetDefaultProfile(InputDeviceType deviceType, const std::string& profileName);
209
210 // Action map management
211 void AddActionMap(const ActionMap& actionMap);
212 ActionMap* GetActionMap(const std::string& mapName);
213 std::vector<ActionMap*> GetActionMapsForContext(ActionMapContext context);
214
215 // Logging
216 void SetLogLevel(const std::string& level);
217 void LogDeviceStatus() const;
218
219private:
220 // Device slots (deviceIndex -> slot)
221 std::unordered_map<int, InputDeviceSlot> m_deviceSlots;
222
223 // Player assignments (playerID -> deviceIndex)
224 std::unordered_map<short, int> m_playerAssignments;
225
226 // Profiles (profileName -> profile)
227 std::unordered_map<std::string, std::shared_ptr<InputProfile>> m_profiles;
228
229 // Default profile assignments (deviceType -> profileName)
230 std::unordered_map<InputDeviceType, std::string> m_defaultProfiles;
231
232 // Action maps
233 std::vector<ActionMap> m_actionMaps;
234
235 // Logging level (0=error, 1=warning, 2=info, 3=debug)
236 int m_logLevel = 2;
237
238 // Helper: Find first available device (prefers joysticks)
240};
241
242//==============================================================================
243// Input Context Manager - Context stack and switching
244//==============================================================================
245
247public:
250
251 // Singleton access
254 return instance;
255 }
256
257 // Context stack operations
259 void PopContext();
261
262 // Configuration
263 bool IsEditorEnabled() const { return m_editorEnabled; }
264 void SetEditorEnabled(bool enabled);
265
266 // Initialization
267 void Initialize();
268 void LoadConfig(const std::string& configPath);
269
270private:
271 bool m_editorEnabled = false;
272 std::vector<ActionMapContext> m_contextStack;
273};
274
ComponentTypeID GetComponentTypeID_Static()
Definition ECS_Entity.h:56
InputType
Definition InputDevice.h:34
InputDeviceType
Definition InputDevice.h:28
ActionMapContext
Definition InputDevice.h:44
void AddAction(const std::string &actionName)
std::string description
bool enabledByDefault
ActionMapContext context
bool ContainsAction(const std::string &actionName) const
bool exclusive
ActionMap()=default
std::vector< std::string > actions
ActionMap(const std::string &name, ActionMapContext ctx, int prio=0)
std::string mapName
void PushContext(ActionMapContext ctx)
std::vector< ActionMapContext > m_contextStack
ActionMapContext GetActiveContext() const
void SetEditorEnabled(bool enabled)
bool IsEditorEnabled() const
~InputContextManager()=default
static InputContextManager & Get()
void LoadConfig(const std::string &configPath)
std::shared_ptr< InputProfile > GetProfile(const std::string &profileName)
std::unordered_map< std::string, std::shared_ptr< InputProfile > > m_profiles
std::vector< ActionMap * > GetActionMapsForContext(ActionMapContext context)
void RegisterDevice(const InputDeviceSlot &slot)
std::unordered_map< short, int > m_playerAssignments
std::unordered_map< int, InputDeviceSlot > m_deviceSlots
void AddProfile(std::shared_ptr< InputProfile > profile)
std::vector< ActionMap > m_actionMaps
static InputDeviceManager & Get()
std::vector< InputDeviceSlot * > GetAvailableDevices()
std::unordered_map< InputDeviceType, std::string > m_defaultProfiles
InputDeviceSlot * AutoAssignDevice(short playerID)
void LogDeviceStatus() const
bool UnassignDevice(short playerID)
void SetLogLevel(const std::string &level)
~InputDeviceManager()=default
void UnregisterDevice(int deviceIndex)
bool AssignDeviceToPlayer(int deviceIndex, short playerID)
InputDeviceSlot * FindFirstAvailableDevice()
InputDeviceManager()=default
ActionMap * GetActionMap(const std::string &mapName)
void AddActionMap(const ActionMap &actionMap)
std::vector< InputDeviceSlot * > GetAllDevices()
InputDeviceSlot * GetDeviceForPlayer(short playerID)
void SetDefaultProfile(InputDeviceType deviceType, const std::string &profileName)
std::string description
Definition InputDevice.h:89
bool ValidateNoOverlaps() const
InputDeviceType deviceType
Definition InputDevice.h:88
bool validateOverlaps
Definition InputDevice.h:98
std::string profileName
Definition InputDevice.h:87
InputProfile()=default
void InitializeDefaults()
InputProfile(const std::string &name, InputDeviceType type)
Definition InputDevice.h:83
float sensitivity
Definition InputDevice.h:96
void AddAction(const std::string &actionName, const InputBinding &binding)
std::unordered_map< std::string, InputBinding > actionMappings
Definition InputDevice.h:92
const InputBinding * GetActionBinding(const std::string &actionName) const
float axisDeadzone
Definition InputDevice.h:64
float triggerThreshold
Definition InputDevice.h:68
std::string comment
Definition InputDevice.h:71
InputType type
Definition InputDevice.h:56
InputBinding()=default
float axisScale
Definition InputDevice.h:63
std::shared_ptr< InputProfile > profile
InputDeviceSlot()=default
bool IsAssigned() const
InputDeviceSlot(InputDeviceType t, int idx, const std::string &name)
InputDeviceType type
std::string deviceName
bool IsAvailable() const