diff --git a/docs/reference/controls.md b/docs/reference/controls.md index 06f53e5..0159155 100644 --- a/docs/reference/controls.md +++ b/docs/reference/controls.md @@ -1,5 +1,7 @@ # Controls +![Defailt Gamepad Controls](./controls.svg) + | Action | Default Gamepad Control | Effect | Remarks | |---------|-----------------------------------------------|-----------------------------------|--------------------------------------------------------------------------------------------------------| | Up | DPad Up/Left Stick Up/Right Stick Up | Select Menu Item Up/Look Up | | diff --git a/src/packages/game/input/IZ_gamecontroller.c b/src/packages/game/input/IZ_gamecontroller.c index 33fb81f..e1cfa2f 100644 --- a/src/packages/game/input/IZ_gamecontroller.c +++ b/src/packages/game/input/IZ_gamecontroller.c @@ -54,10 +54,25 @@ void IZ_GameControllerHandleAxisEvents(IZ_GameControllerState* state, IZ_Action* bool is_capture = false; const u16 bitflag = (0x1 << control_index); - if ( - strstr(state->config.control_mapping[control_index], current_positive_axis_full_name) - || strstr(state->config.control_mapping[control_index], current_negative_axis_full_name) - ) { + if (strstr(state->config.control_mapping[control_index], current_positive_axis_full_name)) { + if (*action & bitflag) { + IZ_LogInfo(IZ_LOG_CATEGORY_INPUT, "input/gamepad", "up %s", IZ_ACTION_NAMES[control_index]); + } + // TODO: optimize unsetting of action + *action &= ~bitflag; + // should we implement actions that do not cancel out across input controllers? + // add extra byte for source of action: + // 0x1 - keyboard + // 0x2 - game controller dpad + // 0x4 - game controller left stick + // 0x8 - game controller right stick + // 0x10 - other device + } + + if (strstr(state->config.control_mapping[control_index], current_negative_axis_full_name)) { + if (*action & bitflag) { + IZ_LogInfo(IZ_LOG_CATEGORY_INPUT, "input/gamepad", "up %s", IZ_ACTION_NAMES[control_index]); + } *action &= ~bitflag; // should we implement actions that do not cancel out across input controllers? // add extra byte for source of action: @@ -69,6 +84,7 @@ void IZ_GameControllerHandleAxisEvents(IZ_GameControllerState* state, IZ_Action* } char current_axis_full_name[IZ_GAME_CONTROLLER_MAX_CONTROL_NAME_LENGTH]; + IZ_memset(current_axis_full_name, 0, IZ_GAME_CONTROLLER_MAX_CONTROL_NAME_LENGTH); if (e.caxis.value > 0) { IZ_memcpy( current_axis_full_name, @@ -97,6 +113,7 @@ void IZ_GameControllerHandleAxisEvents(IZ_GameControllerState* state, IZ_Action* } *action |= bitflag; + IZ_LogInfo(IZ_LOG_CATEGORY_INPUT, "input/gamepad", "dn %s (%s)", IZ_ACTION_NAMES[control_index], current_axis_full_name); } } @@ -115,17 +132,19 @@ void IZ_GameControllerHandleButtonEvents(IZ_GameControllerState* state, IZ_Actio current_button_name ); - if (!strstr(state->config.control_mapping[control_index], current_button_full_name)) { + if (!IZ_contains(state->config.control_mapping[control_index], IZ_GAME_CONTROLLER_MAX_CONTROL_NAME_LENGTH, current_button_full_name, IZ_GAME_CONTROLLER_MAX_CONTROL_NAME_LENGTH)) { continue; } const u16 bitflag = (0x1 << control_index); if (e.type == SDL_CONTROLLERBUTTONDOWN) { + IZ_LogInfo(IZ_LOG_CATEGORY_INPUT, "input/gamepad", "dn %s (%s)", IZ_ACTION_NAMES[control_index], current_button_full_name); *action |= bitflag; return; } if (e.type == SDL_CONTROLLERBUTTONUP) { + IZ_LogInfo(IZ_LOG_CATEGORY_INPUT, "input/gamepad", "up %s (%s)", IZ_ACTION_NAMES[control_index], current_button_full_name); *action &= ~bitflag; return; } @@ -246,9 +265,18 @@ IZ_ProcedureResult IZ_GameControllerInitialize(IZ_GameControllerState(* state)[I if (!(*state)[player_index].device) { break; } + (*state)[player_index].config.device_id = SDL_JoystickInstanceID(SDL_GameControllerGetJoystick((*state)[player_index].device)); SDL_GUID game_controller_guid = SDL_JoystickGetGUID(SDL_GameControllerGetJoystick((*state)[player_index].device)); IZ_memcpy(&(*state)[player_index].config.guid, sizeof(SDL_GUID), &game_controller_guid, sizeof(SDL_GUID)); + + IZ_LogInfo( + IZ_LOG_CATEGORY_GENERIC, + "input/gamepad", + "Found device for player %u: %s", + player_index, + SDL_GameControllerName((*state)[player_index].device) + ); } // Post config (after game_controller GUIDs have been queried), this is unique to game_controllers since they can be plugged in any diff --git a/src/packages/game/input/IZ_gamecontroller.h b/src/packages/game/input/IZ_gamecontroller.h index fbfbe3f..f1be053 100644 --- a/src/packages/game/input/IZ_gamecontroller.h +++ b/src/packages/game/input/IZ_gamecontroller.h @@ -38,9 +38,9 @@ static const IZ_GameControllerState IZ_GAME_CONTROLLER_DEFAULT_STATE[IZ_PLAYERS] { .config = { .control_mapping = { - "button:dpup axis:+lefty axis:+righty", + "button:dpup axis:-lefty axis:-righty", "button:dpright axis:+leftx axis:+rightx", - "button:dpdown axis:-lefty axis:-righty", + "button:dpdown axis:+lefty axis:+righty", "button:dpleft axis:-leftx axis:-rightx", "button:start", "button:back", diff --git a/src/packages/game/input/IZ_keyboard.c b/src/packages/game/input/IZ_keyboard.c index 3f3a5f9..679786d 100644 --- a/src/packages/game/input/IZ_keyboard.c +++ b/src/packages/game/input/IZ_keyboard.c @@ -16,11 +16,25 @@ void IZ_KeyboardHandleKeyUpDownEvents(IZ_KeyboardState* state, IZ_Action* action for (control_index = 0; control_index < IZ_CONTROLS; control_index += 1) { if (e.key.keysym.sym == state->config.control_mapping[control_index]) { const u16 bitflag = (0x1 << control_index); - if (e.type == SDL_KEYDOWN) { + if (e.type == SDL_KEYDOWN && !(*action & bitflag)) { + IZ_LogInfo( + IZ_LOG_CATEGORY_INPUT, + "input/keyboard", + "dn %s (%s)", + IZ_ACTION_NAMES[control_index], + SDL_GetKeyName(e.key.keysym.sym) + ); *action |= bitflag; return; } - if (e.type == SDL_KEYUP) { + if (e.type == SDL_KEYUP && (*action & bitflag)) { + IZ_LogInfo( + IZ_LOG_CATEGORY_INPUT, + "input/keyboard", + "up %s (%s)", + IZ_ACTION_NAMES[control_index], + SDL_GetKeyName(e.key.keysym.sym) + ); *action &= ~bitflag; return; } diff --git a/src/packages/game/input/IZ_keyboard.h b/src/packages/game/input/IZ_keyboard.h index 92abf3c..cef6633 100644 --- a/src/packages/game/input/IZ_keyboard.h +++ b/src/packages/game/input/IZ_keyboard.h @@ -7,6 +7,7 @@ #include #include "../../stdinc/IZ_string.h" #include "../../stdinc/IZ_stdlib.h" +#include "../../log/IZ_log.h" #include "IZ_action.h" typedef struct { diff --git a/src/packages/log/IZ_log.c b/src/packages/log/IZ_log.c index 70a81d1..8454ce8 100644 --- a/src/packages/log/IZ_log.c +++ b/src/packages/log/IZ_log.c @@ -83,11 +83,11 @@ void IZ_LogError(const char* context, const char* fmt, ...) { va_end(args); if (IZ_LogIsSupportedColor(stdout_dest)) { - fprintf(stdout_dest, RED "%24s" RESET " " BOLD "%-6s" RESET " %s\n", IZ_LOG_DATE_FUNCTION(), context, buffer); + fprintf(stdout_dest, RED "%-" IZ_LOG_WIDTH_TIMESTAMP "s" RESET " " BOLD "%-" IZ_LOG_WIDTH_CATEGORY "s" RESET " %s\n", IZ_LOG_DATE_FUNCTION(), context, buffer); return; } - fprintf(stderr_dest, "%24s" " " "%-6s" " %s\n", IZ_LOG_DATE_FUNCTION(), context, buffer); + fprintf(stderr_dest, "%-" IZ_LOG_WIDTH_TIMESTAMP "s" " " "%-" IZ_LOG_WIDTH_CATEGORY "s" " %s\n", IZ_LOG_DATE_FUNCTION(), context, buffer); #endif } @@ -103,20 +103,20 @@ void IZ_LogInfo(IZ_LogCategory category, const char* context, const char* fmt, . switch (category) { default: case IZ_LOG_CATEGORY_GENERIC: - fprintf(stdout_dest, CYN "%24s" RESET " " BOLD "%-6s" RESET " %s\n", IZ_LOG_DATE_FUNCTION(), context, buffer); + fprintf(stdout_dest, CYN "%-" IZ_LOG_WIDTH_TIMESTAMP "s" RESET " " BOLD "%-" IZ_LOG_WIDTH_CATEGORY "s" RESET " %s\n", IZ_LOG_DATE_FUNCTION(), context, buffer); break; case IZ_LOG_CATEGORY_GLOBAL: - fprintf(stdout_dest, MAG "%24s" RESET " " BOLD "%-6s" RESET " %s\n", IZ_LOG_DATE_FUNCTION(), context, buffer); + fprintf(stdout_dest, MAG "%-" IZ_LOG_WIDTH_TIMESTAMP "s" RESET " " BOLD "%-" IZ_LOG_WIDTH_CATEGORY "s" RESET " %s\n", IZ_LOG_DATE_FUNCTION(), context, buffer); break; case IZ_LOG_CATEGORY_INPUT: - fprintf(stdout_dest, WHT "%24s" RESET " " BOLD "%-6s" RESET " %s\n", IZ_LOG_DATE_FUNCTION(), context, buffer); + fprintf(stdout_dest, WHT "%-" IZ_LOG_WIDTH_TIMESTAMP "s" RESET " " BOLD "%-" IZ_LOG_WIDTH_CATEGORY "s" RESET " %s\n", IZ_LOG_DATE_FUNCTION(), context, buffer); break; } return; } - fprintf(stdout_dest, "%24s" " " "%-6s" " %s\n", IZ_LOG_DATE_FUNCTION(), context, buffer); + fprintf(stdout_dest, "%-" IZ_LOG_WIDTH_TIMESTAMP "s" " " "%-" IZ_LOG_WIDTH_CATEGORY "s" " %s\n", IZ_LOG_DATE_FUNCTION(), context, buffer); #endif } @@ -130,14 +130,14 @@ void IZ_LogWarn(bool is_critical, const char* context, const char* fmt, ...) { if (IZ_LogIsSupportedColor(stdout_dest)) { if (is_critical) { - fprintf(stdout_dest, GRN "%24s" RESET " " BOLD "%-6s" RESET " %s\n", IZ_LOG_DATE_FUNCTION(), context, buffer); + fprintf(stdout_dest, GRN "%-" IZ_LOG_WIDTH_TIMESTAMP "s" RESET " " BOLD "%-" IZ_LOG_WIDTH_CATEGORY "s" RESET " %s\n", IZ_LOG_DATE_FUNCTION(), context, buffer); } else { - fprintf(stdout_dest, YEL "%24s" RESET " " BOLD "%-6s" RESET " %s\n", IZ_LOG_DATE_FUNCTION(), context, buffer); + fprintf(stdout_dest, YEL "%-" IZ_LOG_WIDTH_TIMESTAMP "s" RESET " " BOLD "%-" IZ_LOG_WIDTH_CATEGORY "s" RESET " %s\n", IZ_LOG_DATE_FUNCTION(), context, buffer); } return; } - fprintf(stdout_dest, "%24s" " " "%-6s" " %s\n", IZ_LOG_DATE_FUNCTION(), context, buffer); + fprintf(stdout_dest, "%-" IZ_LOG_WIDTH_TIMESTAMP "s" " " "%-" IZ_LOG_WIDTH_CATEGORY "s" " %s\n", IZ_LOG_DATE_FUNCTION(), context, buffer); #endif } @@ -149,11 +149,11 @@ void IZ_Log(const char* context, const char* fmt, ...) { vsnprintf(buffer, sizeof(buffer), fmt, args); va_end(args); if (IZ_LogIsSupportedColor(stdout_dest)) { - fprintf(stdout_dest, BLU "%24s" RESET " " BOLD "%-6s" RESET " %s\n", IZ_LOG_DATE_FUNCTION(), context, buffer); + fprintf(stdout_dest, BLU "%-" IZ_LOG_WIDTH_TIMESTAMP "s" RESET " " BOLD "%-" IZ_LOG_WIDTH_CATEGORY "s" RESET " %s\n", IZ_LOG_DATE_FUNCTION(), context, buffer); return; } - fprintf(stdout_dest, "%24s" " " "%-6s" " %s\n", IZ_LOG_DATE_FUNCTION(), context, buffer); + fprintf(stdout_dest, "%-" IZ_LOG_WIDTH_TIMESTAMP "s" " " "%-" IZ_LOG_WIDTH_CATEGORY "s" " %s\n", IZ_LOG_DATE_FUNCTION(), context, buffer); fflush(stdout_dest); #endif } diff --git a/src/packages/log/IZ_log.h b/src/packages/log/IZ_log.h index ebacf70..3954837 100644 --- a/src/packages/log/IZ_log.h +++ b/src/packages/log/IZ_log.h @@ -16,6 +16,9 @@ #define IZ_LOG_LEVEL_FLAG_WARN #define IZ_LOG_LEVEL_FLAG_ERROR +#define IZ_LOG_WIDTH_TIMESTAMP "24" +#define IZ_LOG_WIDTH_CATEGORY "14" + #include #if defined IZ_WINDOWS #include diff --git a/src/packages/stdinc/IZ_string.c b/src/packages/stdinc/IZ_string.c index 9f15923..02169a3 100644 --- a/src/packages/stdinc/IZ_string.c +++ b/src/packages/stdinc/IZ_string.c @@ -39,3 +39,19 @@ errno_t IZ_strlwr(char* dest, const char* str, rsize_t str_size) { void* IZ_memset(void* dest, int value, rsize_t dest_size) { return memset(dest, value, dest_size); } + +const char* IZ_contains(const char* haystack, rsize_t haystack_size, const char* needle, rsize_t needle_size) { + int i; + for (i = 0; i < haystack_size; i += 1) { + int j; + for (j = 0; j <= needle_size; j += 1) { + if ((haystack[j] == ' ' || haystack[j] == '\0' || j == needle_size) && (haystack[i + j] == ' ' || haystack[i + j] == '\0')) { + return haystack + i; + } + if (haystack[i + j] != needle[j]) { + break; + } + } + } + return NULL; +} diff --git a/src/packages/stdinc/IZ_string.h b/src/packages/stdinc/IZ_string.h index 8bd7001..89d5dd4 100644 --- a/src/packages/stdinc/IZ_string.h +++ b/src/packages/stdinc/IZ_string.h @@ -19,4 +19,6 @@ errno_t IZ_strlwr(char*, const char*, rsize_t); void* IZ_memset(void*, int, rsize_t); +const char* IZ_contains(const char*, rsize_t, const char*, rsize_t); + #endif