@@ -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 | | | |||
@@ -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 | |||
@@ -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", | |||
@@ -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; | |||
} | |||
@@ -7,6 +7,7 @@ | |||
#include <ini-config/source/types/int.h> | |||
#include "../../stdinc/IZ_string.h" | |||
#include "../../stdinc/IZ_stdlib.h" | |||
#include "../../log/IZ_log.h" | |||
#include "IZ_action.h" | |||
typedef struct { | |||
@@ -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 | |||
} |
@@ -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 <SDL_filesystem.h> | |||
#if defined IZ_WINDOWS | |||
#include <io.h> | |||
@@ -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; | |||
} |
@@ -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 |