11#include "third_party/nlohmann/json.hpp"
13#include <unordered_map>
21static std::unordered_map<std::string, SDL_Scancode>
s_keyNameMap = {
67 SYSTEM_LOG <<
"[InputConfig][Warning] Unknown key name: " <<
keyName <<
", using UNKNOWN\n";
77 SYSTEM_LOG <<
"[InputConfig][Info] Loading engine config from: " << path <<
"\n";
80 std::ifstream
file(path);
81 if (!
file.is_open()) {
82 SYSTEM_LOG <<
"[InputConfig][Warning] Could not open engine config file: " << path <<
"\n";
90 if (
j.contains(
"editor_enabled")) {
96 if (
j.contains(
"input_log_level")) {
97 std::string
logLevel =
j[
"input_log_level"].get<std::string>();
106 SYSTEM_LOG <<
"[InputConfig][Info] Engine config loaded successfully\n";
109 catch (
const std::exception&
e) {
110 SYSTEM_LOG <<
"[InputConfig][Error] Failed to parse engine config: " <<
e.what() <<
"\n";
116 SYSTEM_LOG <<
"[InputConfig][Info] Loading input config from: " << path <<
"\n";
119 std::ifstream
file(path);
120 if (!
file.is_open()) {
121 SYSTEM_LOG <<
"[InputConfig][Warning] Could not open input config file: " << path <<
"\n";
129 if (
j.contains(
"profiles")) {
131 SYSTEM_LOG <<
"[InputConfig][Warning] Failed to parse profiles section\n";
135 if (
j.contains(
"action_maps")) {
137 SYSTEM_LOG <<
"[InputConfig][Warning] Failed to parse action_maps section\n";
141 if (
j.contains(
"default_profile_assignment")) {
143 SYSTEM_LOG <<
"[InputConfig][Warning] Failed to parse default_profile_assignment section\n";
147 if (
j.contains(
"settings")) {
149 SYSTEM_LOG <<
"[InputConfig][Warning] Failed to parse settings section\n";
153 SYSTEM_LOG <<
"[InputConfig][Info] Input config loaded successfully\n";
156 catch (
const std::exception&
e) {
157 SYSTEM_LOG <<
"[InputConfig][Error] Failed to parse input config: " <<
e.what() <<
"\n";
164 SYSTEM_LOG <<
"[InputConfig][Error] Profiles must be an array\n";
170 std::string name =
profileJson[
"name"].get<std::string>();
177 auto profile = std::make_shared<InputProfile>(name, deviceType);
182 if (
settings.contains(
"deadzone")) {
183 profile->deadzone =
settings[
"deadzone"].get<
float>();
185 if (
settings.contains(
"sensitivity")) {
186 profile->sensitivity =
settings[
"sensitivity"].get<
float>();
188 if (
settings.contains(
"validate_overlaps")) {
189 profile->validateOverlaps =
settings[
"validate_overlaps"].get<
bool>();
196 for (
auto it = actions.begin();
it != actions.end(); ++
it) {
204 if (profile->validateOverlaps) {
205 profile->ValidateNoOverlaps();
215 catch (
const std::exception&
e) {
216 SYSTEM_LOG <<
"[InputConfig][Error] Failed to parse profile: " <<
e.what() <<
"\n";
226 std::string
typeStr =
j[
"type"].get<std::string>();
230 if (
j.contains(
"primary")) {
231 std::string
keyName =
j[
"primary"].get<std::string>();
234 if (
j.contains(
"alternate")) {
235 std::string
keyName =
j[
"alternate"].get<std::string>();
239 else if (
typeStr ==
"button") {
241 if (
j.contains(
"button")) {
242 binding.primaryInput =
j[
"button"].get<
int>();
247 if (
j.contains(
"axis")) {
248 binding.primaryInput =
j[
"axis"].get<
int>();
250 if (
j.contains(
"deadzone")) {
251 binding.axisDeadzone =
j[
"deadzone"].get<
float>();
253 if (
j.contains(
"sensitivity")) {
254 binding.axisScale =
j[
"sensitivity"].get<
float>();
260 if (
j.contains(
"stick")) {
261 binding.comment =
j[
"stick"].get<std::string>();
263 if (
j.contains(
"deadzone")) {
264 binding.axisDeadzone =
j[
"deadzone"].get<
float>();
266 if (
j.contains(
"sensitivity")) {
267 binding.axisScale =
j[
"sensitivity"].get<
float>();
270 else if (
typeStr ==
"trigger") {
272 if (
j.contains(
"trigger")) {
273 binding.comment =
j[
"trigger"].get<std::string>();
275 if (
j.contains(
"threshold")) {
276 binding.triggerThreshold =
j[
"threshold"].get<
float>();
279 else if (
typeStr ==
"mouse_button") {
281 if (
j.contains(
"button")) {
282 binding.primaryInput =
j[
"button"].get<
int>();
291 SYSTEM_LOG <<
"[InputConfig][Error] Action maps must be an array\n";
297 std::string name =
mapJson[
"name"].get<std::string>();
306 int priority =
mapJson.value(
"priority", 0);
311 if (
mapJson.contains(
"actions") &&
mapJson[
"actions"].is_array()) {
320 SYSTEM_LOG <<
"[InputConfig][Info] Loaded action map: " << name
321 <<
" (Context: " <<
contextStr <<
", Priority: " << priority <<
")\n";
324 catch (
const std::exception&
e) {
325 SYSTEM_LOG <<
"[InputConfig][Error] Failed to parse action map: " <<
e.what() <<
"\n";
334 if (
j.contains(
"Joystick")) {
335 std::string profileName =
j[
"Joystick"].get<std::string>();
339 if (
j.contains(
"KeyboardMouse")) {
340 std::string profileName =
j[
"KeyboardMouse"].get<std::string>();
346 catch (
const std::exception&
e) {
347 SYSTEM_LOG <<
"[InputConfig][Error] Failed to parse default assignments: " <<
e.what() <<
"\n";
354 if (
j.contains(
"log_level")) {
355 std::string
logLevel =
j[
"log_level"].get<std::string>();
361 catch (
const std::exception&
e) {
362 SYSTEM_LOG <<
"[InputConfig][Error] Failed to parse global settings: " <<
e.what() <<
"\n";
368 SYSTEM_LOG <<
"[InputConfig][Info] Loading profile overrides from: " << path <<
"\n";
371 std::ifstream
file(path);
372 if (!
file.is_open()) {
374 SYSTEM_LOG <<
"[InputConfig][Info] No user override file found (this is normal): " << path <<
"\n";
383 if (
j.contains(
"profile_overrides") &&
j[
"profile_overrides"].is_array()) {
385 std::string profileName =
overrideJson[
"profile"].get<std::string>();
389 SYSTEM_LOG <<
"[InputConfig][Warning] Cannot override profile '" << profileName <<
"': not found\n";
395 for (
auto it = actions.begin();
it != actions.end(); ++
it) {
402 <<
"' in profile '" << profileName <<
"'\n";
408 SYSTEM_LOG <<
"[InputConfig][Info] Applied user overrides successfully\n";
413 catch (
const std::exception&
e) {
414 SYSTEM_LOG <<
"[InputConfig][Error] Failed to parse profile overrides: " <<
e.what() <<
"\n";
420 SYSTEM_LOG <<
"[InputConfig][Info] Saving input config to: " << path <<
" (not implemented yet)\n";
ComponentTypeID GetComponentTypeID_Static()
void SetEditorEnabled(bool enabled)
static InputContextManager & Get()