Sfoglia il codice sorgente

Update gamepad event handling

Use game controller APIs instead of the joystick ones to be able to use
the gamepad button DB file.
master
parent
commit
8bf3b46233
20 ha cambiato i file con 612 aggiunte e 823 eliminazioni
  1. +29
    -26
      CMakeLists.txt
  2. +4
    -0
      __mocks__/src/packages/log/IZ_log.mock.h
  3. +48
    -0
      __mocks__/subprojects/SDL/SDL_gamecontroller.mock.h
  4. +0
    -43
      __mocks__/subprojects/SDL/SDL_joystick.mock.h
  5. +14
    -14
      __mocks__/subprojects/ini-config/source/ini-config.mock.h
  6. +83
    -277
      __tests__/src/packages/game/input.test.c
  7. BIN
      assets_src/gfx/weapons-rigged.cdr
  8. +43
    -18
      docs/controls.md
  9. +2
    -2
      src/packages/config/IZ_config_guid.c
  10. +272
    -0
      src/packages/game/input/IZ_gamecontroller.c
  11. +104
    -0
      src/packages/game/input/IZ_gamecontroller.h
  12. +4
    -4
      src/packages/game/input/IZ_input.c
  13. +2
    -2
      src/packages/game/input/IZ_input.h
  14. +0
    -324
      src/packages/game/input/IZ_joystick.c
  15. +0
    -106
      src/packages/game/input/IZ_joystick.h
  16. +2
    -2
      src/packages/game/input/IZ_keyboard.c
  17. +1
    -1
      src/packages/game/input/IZ_keyboard.h
  18. +1
    -1
      src/packages/game/input/IZ_midi.h
  19. +2
    -2
      src/packages/net/IZ_net_client.h
  20. +1
    -1
      subprojects/ini-config

+ 29
- 26
CMakeLists.txt Vedi File

@@ -69,7 +69,7 @@ include_directories(
"${CMAKE_HOME_DIRECTORY}/dependencies/SDL2_image/include"
"${CMAKE_HOME_DIRECTORY}/dependencies/SDL2_ttf/include"
"${CMAKE_HOME_DIRECTORY}/subprojects/ini-config/subprojects/minIni/dev"
"${CMAKE_HOME_DIRECTORY}/subprojects/ini-config"
"${CMAKE_HOME_DIRECTORY}/subprojects/ini-config/source"
"${CMAKE_HOME_DIRECTORY}/subprojects/bdd-for-c"
"${CMAKE_HOME_DIRECTORY}/subprojects/bdd-for-c-mocks"
"${CMAKE_HOME_DIRECTORY}/subprojects/midi-utils"
@@ -142,12 +142,12 @@ add_executable(
${IZ_EXECUTABLE_TYPE}
subprojects/ini-config/subprojects/minIni/dev/minIni.h
subprojects/ini-config/subprojects/minIni/dev/minIni.c
subprojects/ini-config/ini-config.h
subprojects/ini-config/ini-config.c
subprojects/ini-config/types/int.h
subprojects/ini-config/types/int.c
subprojects/ini-config/types/string.h
subprojects/ini-config/types/string.c
subprojects/ini-config/source/ini-config.h
subprojects/ini-config/source/ini-config.c
subprojects/ini-config/source/types/int.h
subprojects/ini-config/source/types/int.c
subprojects/ini-config/source/types/string.h
subprojects/ini-config/source/types/string.c
subprojects/midi-utils/midi-utils.h
subprojects/midi-utils/midi-utils.c
${IZ_GETOPT_DEPENDENCIES}
@@ -158,8 +158,8 @@ add_executable(
src/packages/game/IZ_app.h
src/packages/game/IZ_app.c
src/packages/game/main.c
src/packages/game/input/IZ_joystick.c
src/packages/game/input/IZ_joystick.h
src/packages/game/input/IZ_gamecontroller.c
src/packages/game/input/IZ_gamecontroller.h
src/packages/game/input/IZ_keyboard.c
src/packages/game/input/IZ_keyboard.h
src/packages/game/geometry/IZ_vector2d.c
@@ -242,23 +242,26 @@ add_executable(
subprojects/bdd-for-c/bdd-for-c.h
subprojects/bdd-for-c-mocks/bdd-for-c-mocks.h

subprojects/ini-config/ini-config.h
__mocks__/subprojects/ini-config/ini-config.mock.h
subprojects/ini-config/source/ini-config.h
__mocks__/subprojects/ini-config/source/ini-config.mock.h

__mocks__/subprojects/SDL/SDL_keyboard.mock.h
__mocks__/subprojects/SDL/SDL_events.mock.h
__mocks__/subprojects/SDL/SDL_joystick.mock.h
__mocks__/subprojects/SDL/SDL_gamecontroller.mock.h
__mocks__/subprojects/SDL/SDL_stdinc.mock.h
__mocks__/subprojects/portmidi/portmidi.mock.h

src/packages/log/IZ_log.h
__mocks__/src/packages/log/IZ_log.mock.h

src/packages/config/IZ_config_guid.h
src/packages/config/IZ_config_guid.c

src/packages/game/input/IZ_keyboard.h
src/packages/game/input/IZ_keyboard.c

src/packages/game/input/IZ_joystick.h
src/packages/game/input/IZ_joystick.c
src/packages/game/input/IZ_gamecontroller.h
src/packages/game/input/IZ_gamecontroller.c

src/packages/game/input/IZ_midi.h
src/packages/game/input/IZ_midi.c
@@ -350,12 +353,12 @@ add_executable(
dependencies/sqlite/sqlite3.c
subprojects/ini-config/subprojects/minIni/dev/minIni.h
subprojects/ini-config/subprojects/minIni/dev/minIni.c
subprojects/ini-config/ini-config.h
subprojects/ini-config/ini-config.c
subprojects/ini-config/types/int.h
subprojects/ini-config/types/int.c
subprojects/ini-config/types/string.h
subprojects/ini-config/types/string.c
subprojects/ini-config/source/ini-config.h
subprojects/ini-config/source/ini-config.c
subprojects/ini-config/source/types/int.h
subprojects/ini-config/source/types/int.c
subprojects/ini-config/source/types/string.h
subprojects/ini-config/source/types/string.c
src/packages/log/IZ_intercept.h
src/packages/log/IZ_intercept.c
src/packages/server/main.c
@@ -394,12 +397,12 @@ add_executable(
asset-inv
subprojects/ini-config/subprojects/minIni/dev/minIni.h
subprojects/ini-config/subprojects/minIni/dev/minIni.c
subprojects/ini-config/ini-config.h
subprojects/ini-config/ini-config.c
subprojects/ini-config/types/int.h
subprojects/ini-config/types/int.c
subprojects/ini-config/types/string.h
subprojects/ini-config/types/string.c
subprojects/ini-config/source/ini-config.h
subprojects/ini-config/source/ini-config.c
subprojects/ini-config/source/types/int.h
subprojects/ini-config/source/types/int.c
subprojects/ini-config/source/types/string.h
subprojects/ini-config/source/types/string.c
src/packages/common/IZ_common.h
src/packages/asset-inv/main.c
)


+ 4
- 0
__mocks__/src/packages/log/IZ_log.mock.h Vedi File

@@ -9,6 +9,10 @@ mock_modes(IZ_LogInfo) {
IZ_LOG_INFO_LOG,
};

mock(IZ_LOG_DATE_FUNCTION) char* IZ_LOG_DATE_FUNCTION(void) {
mock_return(IZ_LOG_DATE_FUNCTION) "";
}

mock(IZ_LogInfo) void IZ_LogInfo(IZ_LogCategory category, const char* context, const char* fmt, ...) {
mock_mode_if(IZ_LogInfo, IZ_LOG_INFO_SUPPRESS) {
mock_return(IZ_LogInfo);


+ 48
- 0
__mocks__/subprojects/SDL/SDL_gamecontroller.mock.h Vedi File

@@ -0,0 +1,48 @@
#ifndef SDL_GAMECONTROLLER_MOCK_H
#define SDL_GAMECONTROLLER_MOCK_H

#include <bdd-for-c-mocks.h>
#include <SDL_gamecontroller.h>
#include <SDL_rwops.h>
#include "../../../src/packages/common/IZ_common.h"

#define MOCK_OPEN_JOYSTICKS 1

mock(SDL_GameControllerOpen) SDL_GameController* SDL_GameControllerOpen(i32 device_index) {
static void* joystick = (void*) 1;
mock_return(SDL_GameControllerOpen) (SDL_GameController*) &joystick;
}

mock(SDL_NumJoysticks) i32 SDL_NumJoysticks(void) {
mock_return(SDL_NumJoysticks) MOCK_OPEN_JOYSTICKS;
}

mock(SDL_JoystickInstanceID) i32 SDL_JoystickInstanceID(SDL_Joystick* joystick) {
mock_return(SDL_JoystickInstanceID) 0;
}

mock(SDL_GameControllerClose) void SDL_GameControllerClose(SDL_GameController* _joystick) {
mock_return(SDL_GameControllerClose);
}

mock(SDL_JoystickGetGUID) SDL_JoystickGUID SDL_JoystickGetGUID(SDL_Joystick* joystick) {
mock_return(SDL_JoystickGetGUID) (SDL_JoystickGUID) {
.data = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, }
};
}

mock(SDL_GameControllerAddMappingsFromRW) int SDL_GameControllerAddMappingsFromRW(SDL_RWops *rw, int freerw) {
mock_return(SDL_GameControllerAddMappingsFromRW) 1;
}

mock(SDL_GameControllerFromInstanceID) SDL_GameController* SDL_GameControllerFromInstanceID(SDL_JoystickID instance_id) {
static void* joystick = (void*) 1;
mock_return(SDL_GameControllerFromInstanceID) (SDL_GameController*) &joystick;
}

mock(SDL_GameControllerGetJoystick) SDL_Joystick* SDL_GameControllerGetJoystick(SDL_GameController* gamecontroller) {
static void* joystick = (void*) 1;
mock_return(SDL_GameControllerGetJoystick) (SDL_Joystick*) &joystick;
}

#endif

+ 0
- 43
__mocks__/subprojects/SDL/SDL_joystick.mock.h Vedi File

@@ -1,43 +0,0 @@
#ifndef SDL_JOYSTICK_MOCK_H
#define SDL_JOYSTICK_MOCK_H

#include <bdd-for-c-mocks.h>
#include <SDL_joystick.h>
#include <SDL_rwops.h>
#include "../../../src/packages/common/IZ_common.h"

#define MOCK_OPEN_JOYSTICKS 1

mock(SDL_JoystickOpen) SDL_Joystick* SDL_JoystickOpen(i32 device_index) {
static void* joystick = (void*) 1;
mock_return(SDL_JoystickOpen) (SDL_Joystick*) &joystick;
}

mock(SDL_NumJoysticks) i32 SDL_NumJoysticks(void) {
mock_return(SDL_NumJoysticks) MOCK_OPEN_JOYSTICKS;
}

mock(SDL_JoystickInstanceID) i32 SDL_JoystickInstanceID(SDL_Joystick* joystick) {
mock_return(SDL_JoystickInstanceID) 0;
}

mock(SDL_JoystickClose) void SDL_JoystickClose(SDL_Joystick* _joystick) {
mock_return(SDL_JoystickClose);
}

mock(SDL_JoystickGetGUID) SDL_JoystickGUID SDL_JoystickGetGUID(SDL_Joystick* joystick) {
mock_return(SDL_JoystickGetGUID) (SDL_JoystickGUID) {
.data = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, }
};
}

mock(SDL_GameControllerAddMappingsFromRW) int SDL_GameControllerAddMappingsFromRW(SDL_RWops *rw, int freerw) {
mock_return(SDL_GameControllerAddMappingsFromRW) 0;
}

mock(SDL_JoystickFromInstanceID) SDL_Joystick* SDL_JoystickFromInstanceID(SDL_JoystickID instance_id) {
static void* joystick = (void*) 1;
mock_return(SDL_JoystickFromInstanceID) (SDL_Joystick*) &joystick;
}

#endif

__mocks__/subprojects/ini-config/ini-config.mock.h → __mocks__/subprojects/ini-config/source/ini-config.mock.h Vedi File

@@ -16,59 +16,59 @@ mock(INI_ConfigGetCommandlineOption) const char* INI_ConfigGetCommandlineOption(
mock_return(INI_ConfigGetCommandlineOption) "";
}

mock(INI_ConfigLoadU8) void INI_ConfigLoadU8(INI_ConfigItem* _item, const char* _config_path) {
mock(INI_ConfigLoadU8) void INI_ConfigLoadU8(INI_ConfigItem* _item, const char* _config_path, void* _item_array) {
mock_return(INI_ConfigLoadU8);
}

mock(INI_ConfigLoadU16) void INI_ConfigLoadU16(INI_ConfigItem* _item, const char* _config_path) {
mock(INI_ConfigLoadU16) void INI_ConfigLoadU16(INI_ConfigItem* _item, const char* _config_path, void* _item_array) {
mock_return(INI_ConfigLoadU16);
}

mock(INI_ConfigLoadU32) void INI_ConfigLoadU32(INI_ConfigItem* _item, const char* _config_path) {
mock(INI_ConfigLoadU32) void INI_ConfigLoadU32(INI_ConfigItem* _item, const char* _config_path, void* _item_array) {
mock_return(INI_ConfigLoadU32);
}

mock(INI_ConfigLoadI8) void INI_ConfigLoadI8(INI_ConfigItem* _item, const char* _config_path) {
mock(INI_ConfigLoadI8) void INI_ConfigLoadI8(INI_ConfigItem* _item, const char* _config_path, void* _item_array) {
mock_return(INI_ConfigLoadI8);
}

mock(INI_ConfigLoadI16) void INI_ConfigLoadI16(INI_ConfigItem* _item, const char* _config_path) {
mock(INI_ConfigLoadI16) void INI_ConfigLoadI16(INI_ConfigItem* _item, const char* _config_path, void* _item_array) {
mock_return(INI_ConfigLoadI16);
}

mock(INI_ConfigLoadI32) void INI_ConfigLoadI32(INI_ConfigItem* _item, const char* _config_path) {
mock(INI_ConfigLoadI32) void INI_ConfigLoadI32(INI_ConfigItem* _item, const char* _config_path, void* _item_array) {
mock_return(INI_ConfigLoadI32);
}

mock(INI_ConfigLoadString) void INI_ConfigLoadString(INI_ConfigItem* _item, const char* _config_path) {
mock(INI_ConfigLoadString) void INI_ConfigLoadString(INI_ConfigItem* _item, const char* _config_path, void* _item_array) {
mock_return(INI_ConfigLoadString);
}

mock(INI_ConfigSaveU8) INI_ConfigSaveItemResult INI_ConfigSaveU8(INI_ConfigItem* _item, const char* _config_path) {
mock(INI_ConfigSaveU8) INI_ConfigSaveItemResult INI_ConfigSaveU8(INI_ConfigItem* _item, const char* _config_path, void* _item_array) {
mock_return(INI_ConfigSaveU8) INI_CONFIG_SAVE_ITEM_OK;
}

mock(INI_ConfigSaveU16) INI_ConfigSaveItemResult INI_ConfigSaveU16(INI_ConfigItem* _item, const char* _config_path) {
mock(INI_ConfigSaveU16) INI_ConfigSaveItemResult INI_ConfigSaveU16(INI_ConfigItem* _item, const char* _config_path, void* _item_array) {
mock_return(INI_ConfigSaveU16) INI_CONFIG_SAVE_ITEM_OK;
}

mock(INI_ConfigSaveU32) INI_ConfigSaveItemResult INI_ConfigSaveU32(INI_ConfigItem* _item, const char* _config_path) {
mock(INI_ConfigSaveU32) INI_ConfigSaveItemResult INI_ConfigSaveU32(INI_ConfigItem* _item, const char* _config_path, void* _item_array) {
mock_return(INI_ConfigSaveU32) INI_CONFIG_SAVE_ITEM_OK;
}

mock(INI_ConfigSaveI8) INI_ConfigSaveItemResult INI_ConfigSaveI8(INI_ConfigItem* _item, const char* _config_path) {
mock(INI_ConfigSaveI8) INI_ConfigSaveItemResult INI_ConfigSaveI8(INI_ConfigItem* _item, const char* _config_path, void* _item_array) {
mock_return(INI_ConfigSaveI8) INI_CONFIG_SAVE_ITEM_OK;
}

mock(INI_ConfigSaveI16) INI_ConfigSaveItemResult INI_ConfigSaveI16(INI_ConfigItem* _item, const char* _config_path) {
mock(INI_ConfigSaveI16) INI_ConfigSaveItemResult INI_ConfigSaveI16(INI_ConfigItem* _item, const char* _config_path, void* _item_array) {
mock_return(INI_ConfigSaveI16) INI_CONFIG_SAVE_ITEM_OK;
}

mock(INI_ConfigSaveI32) INI_ConfigSaveItemResult INI_ConfigSaveI32(INI_ConfigItem* _item, const char* _config_path) {
mock(INI_ConfigSaveI32) INI_ConfigSaveItemResult INI_ConfigSaveI32(INI_ConfigItem* _item, const char* _config_path, void* _item_array) {
mock_return(INI_ConfigSaveI32) INI_CONFIG_SAVE_ITEM_OK;
}

mock(INI_ConfigSaveString) INI_ConfigSaveItemResult INI_ConfigSaveString(INI_ConfigItem* _item, const char* _config_path) {
mock(INI_ConfigSaveString) INI_ConfigSaveItemResult INI_ConfigSaveString(INI_ConfigItem* _item, const char* _config_path, void* _item_array) {
mock_return(INI_ConfigSaveString) INI_CONFIG_SAVE_ITEM_OK;
}


+ 83
- 277
__tests__/src/packages/game/input.test.c Vedi File

@@ -3,29 +3,22 @@
#endif
#include <bdd-for-c.h>
#include <subprojects/SDL/SDL_keyboard.mock.h>
#include <subprojects/SDL/SDL_joystick.mock.h>
#include <subprojects/SDL/SDL_gamecontroller.mock.h>
#include <subprojects/SDL/SDL_stdinc.mock.h>
#include <subprojects/minIni/minIni.mock.h>
#include <subprojects/portmidi/portmidi.mock.h>
#include <stdinc/IZ_string.mock.h>
#include <stdinc/IZ_stdlib.mock.h>
#include <subprojects/ini-config/ini-config.mock.h>
#include <log/IZ_log.mock.h>
#include <subprojects/ini-config/source/ini-config.mock.h>
#include <game/input/IZ_keyboard.h>
#include <game/input/IZ_joystick.h>
#include <game/input/IZ_gamecontroller.h>
#include <game/input/IZ_midi.h>

i16 GenerateAxisValueWithinThreshold(u16 threshold) {
return rand() % threshold;
}

i16 GenerateAxisValueOutsideThreshold(u16 threshold) {
return threshold + (rand() % (RAND_MAX - threshold - 1)) + 1;
}

spec("input") {
describe("joystick") {
describe("gamecontroller") {
describe("Initialize") {
static IZ_JoystickState state[IZ_PLAYERS];
static IZ_GameControllerState state[IZ_PLAYERS];

after_each() {
mock_reset(IZ_memcpy);
@@ -36,7 +29,7 @@ spec("input") {
}

after_each() {
mock_reset(SDL_JoystickOpen);
mock_reset(SDL_GameControllerOpen);
}

after_each() {
@@ -48,41 +41,41 @@ spec("input") {
}

it("sets initial state") {
IZ_JoystickInitialize(&state, IZ_CONFIG_GAME_PATH, 0, NULL);
IZ_GameControllerInitialize(&state, IZ_CONFIG_GAME_PATH, 0, NULL);

check(mock_is_called(IZ_memcpy), "Initial state not loaded.");
check(mock_is_called(SDL_NumJoysticks), "Connected joysticks not checked.");
}

it("calls load method") {
IZ_JoystickInitialize(&state, IZ_CONFIG_GAME_PATH, 0, NULL);
IZ_GameControllerInitialize(&state, IZ_CONFIG_GAME_PATH, 0, NULL);

check(mock_is_called(INI_ConfigInitialize), "Config load function not called.");
}

it("calls save method") {
IZ_JoystickInitialize(&state, IZ_CONFIG_GAME_PATH, 0, NULL);
IZ_GameControllerInitialize(&state, IZ_CONFIG_GAME_PATH, 0, NULL);

check(mock_is_called(INI_ConfigSave), "Config save function not called.");
}

it("opens device handles") {
mock_set_expected_calls(SDL_JoystickOpen, MOCK_OPEN_JOYSTICKS);
mock_set_expected_calls(SDL_GameControllerOpen, MOCK_OPEN_JOYSTICKS);

IZ_JoystickInitialize(&state, IZ_CONFIG_GAME_PATH, 0, NULL);
IZ_GameControllerInitialize(&state, IZ_CONFIG_GAME_PATH, 0, NULL);

check(
mock_get_expected_calls(SDL_JoystickOpen) == mock_get_actual_calls(SDL_JoystickOpen),
"Call count mismatch for SDL_JoystickOpen() (expected %u, received %u).",
mock_get_expected_calls(SDL_JoystickOpen),
mock_get_actual_calls(SDL_JoystickOpen)
mock_get_expected_calls(SDL_GameControllerOpen) == mock_get_actual_calls(SDL_GameControllerOpen),
"Call count mismatch for SDL_GameControllerOpen() (expected %u, received %u).",
mock_get_expected_calls(SDL_GameControllerOpen),
mock_get_actual_calls(SDL_GameControllerOpen)
);
}
}

describe("HandleEvents") {
static SDL_Event e;
static IZ_JoystickState state[IZ_PLAYERS] = {};
static IZ_GameControllerState state[IZ_PLAYERS] = {};
static IZ_Action action[IZ_PLAYERS] = {};

u8 p;
@@ -90,267 +83,75 @@ spec("input") {
describe("on player %u", p) {
describe("on axis motion events") {
before_each() {
e.type = SDL_JOYAXISMOTION;
state[p].config.axis_threshold = 8000u;
state[p].config.axis_threshold = IZ_GAME_CONTROLLER_AXIS_THRESHOLD;
}

describe("on primary horizontal direction") {
before_each() {
e.jaxis.axis = IZ_JOY_AXIS_DIRECTION_HORIZONTAL1;
}

it("handles positive motion") {
e.jaxis.value = GenerateAxisValueOutsideThreshold(state[p].config.axis_threshold);
if (e.jaxis.value < 0) {
e.jaxis.value = -e.jaxis.value;
}
action[p] = 0;

printf("(axis value: %d) ", e.jaxis.value);
IZ_JoystickHandleEvents(&state, &action, e);
check(
action[p] == (0x1 << IZ_ACTION_INDEX_RIGHT),
"Action not set."
);
}
for (u8 i = 0; i < SDL_CONTROLLER_AXIS_MAX; i += 1) {
static const char* axis_name;
axis_name = SDL_GameControllerGetStringForAxis(i);

it("handles negative motion") {
e.jaxis.value = -GenerateAxisValueOutsideThreshold(state[p].config.axis_threshold);
if (e.jaxis.value > 0) {
e.jaxis.value = -e.jaxis.value;
}
it("handles %s positive motion activation", axis_name) {
e.type = SDL_CONTROLLERAXISMOTION;
e.caxis.axis = i;
e.caxis.value = IZ_GAME_CONTROLLER_AXIS_THRESHOLD + 1;
sprintf(state[p].config.control_mapping[0], "axis:+%s", axis_name);
action[p] = 0;

printf("(axis value: %d) ", e.jaxis.value);
IZ_JoystickHandleEvents(&state, &action, e);
check(
action[p] == (0x1 << IZ_ACTION_INDEX_LEFT),
"Action not set."
);
}

it("handles neutral motion") {
e.jaxis.value = GenerateAxisValueWithinThreshold(state[p].config.axis_threshold);
action[p] = 0;

printf("(axis value: %d) ", e.jaxis.value);
IZ_JoystickHandleEvents(&state, &action, e);
check(
action[p] == 0,
"Action not set."
);
}
}

describe("on secondary horizontal direction") {
before_each() {
e.jaxis.axis = IZ_JOY_AXIS_DIRECTION_HORIZONTAL2;
IZ_GameControllerHandleEvents(&state, &action, e);
check(action[p] != 0, "Action not set.");
}

it("handles positive motion") {
e.jaxis.value = GenerateAxisValueOutsideThreshold(state[p].config.axis_threshold);
if (e.jaxis.value < 0) {
e.jaxis.value = -e.jaxis.value;
}
it("handles %s negative motion activation", axis_name) {
e.type = SDL_CONTROLLERAXISMOTION;
e.caxis.axis = i;
e.caxis.value = -(IZ_GAME_CONTROLLER_AXIS_THRESHOLD + 1);
sprintf(state[p].config.control_mapping[0], "axis:-%s", axis_name);
action[p] = 0;

printf("(axis value: %d) ", e.jaxis.value);
IZ_JoystickHandleEvents(&state, &action, e);
check(
action[p] == (0x1 << IZ_ACTION_INDEX_RIGHT),
"Action not set."
);
IZ_GameControllerHandleEvents(&state, &action, e);
check(action[p] != 0, "Action not set.");
}

it("handles negative motion") {
e.jaxis.value = -GenerateAxisValueOutsideThreshold(state[p].config.axis_threshold);
if (e.jaxis.value > 0) {
e.jaxis.value = -e.jaxis.value;
}
action[p] = 0;

printf("(axis value: %d) ", e.jaxis.value);
IZ_JoystickHandleEvents(&state, &action, e);
check(
action[p] == (0x1 << IZ_ACTION_INDEX_LEFT),
"Action not set."
);
it("handles %s positive motion deactivation", axis_name) {
e.type = SDL_CONTROLLERAXISMOTION;
e.caxis.axis = i;
e.caxis.value = IZ_GAME_CONTROLLER_AXIS_THRESHOLD - 1;
sprintf(state[p].config.control_mapping[0], "axis:+%s", axis_name);
action[p] = 1;
IZ_GameControllerHandleEvents(&state, &action, e);
check(action[p] != 1, "Action not unset. %d", action[p]);
}

it("handles neutral motion") {
e.jaxis.value = GenerateAxisValueWithinThreshold(state[p].config.axis_threshold);;
action[p] = 0;

printf("(axis value: %d) ", e.jaxis.value);
IZ_JoystickHandleEvents(&state, &action, e);
check(
action[p] == 0,
"Action not set."
);
}
}

describe("on primary vertical direction") {
before_each() {
e.jaxis.axis = IZ_JOY_AXIS_DIRECTION_VERTICAL1;
}

it("handles positive motion") {
e.jaxis.value = GenerateAxisValueOutsideThreshold(state[p].config.axis_threshold);
if (e.jaxis.value < 0) {
e.jaxis.value = -e.jaxis.value;
}
action[p] = 0;

printf("(axis value: %d) ", e.jaxis.value);
IZ_JoystickHandleEvents(&state, &action, e);
check(
action[p] == (0x1 << IZ_ACTION_INDEX_DOWN),
"Action not set."
);
}

it("handles negative motion") {
e.jaxis.value = -GenerateAxisValueOutsideThreshold(state[p].config.axis_threshold);
if (e.jaxis.value > 0) {
e.jaxis.value = -e.jaxis.value;
}
action[p] = 0;

printf("(axis value: %d) ", e.jaxis.value);
IZ_JoystickHandleEvents(&state, &action, e);
check(
action[p] == (0x1 << IZ_ACTION_INDEX_UP),
"Action not set."
);
}

it("handles neutral motion") {
e.jaxis.value = GenerateAxisValueWithinThreshold(state[p].config.axis_threshold);;
action[p] = 0;

printf("(axis value: %d) ", e.jaxis.value);
IZ_JoystickHandleEvents(&state, &action, e);
check(
action[p] == 0,
"Action not set."
);
}
}

describe("on secondary vertical direction") {
before_each() {
e.jaxis.axis = IZ_JOY_AXIS_DIRECTION_VERTICAL2;
}

it("handles positive motion") {
e.jaxis.value = GenerateAxisValueOutsideThreshold(state[p].config.axis_threshold);
if (e.jaxis.value < 0) {
e.jaxis.value = -e.jaxis.value;
}
action[p] = 0;

printf("(axis value: %d) ", e.jaxis.value);
IZ_JoystickHandleEvents(&state, &action, e);
check(
action[p] == (0x1 << IZ_ACTION_INDEX_DOWN),
"Action not set."
);
}

it("handles negative motion") {
e.jaxis.value = -GenerateAxisValueOutsideThreshold(state[p].config.axis_threshold);
if (e.jaxis.value > 0) {
e.jaxis.value = -e.jaxis.value;
}
action[p] = 0;

printf("(axis value: %d) ", e.jaxis.value);
IZ_JoystickHandleEvents(&state, &action, e);
check(
action[p] == (0x1 << IZ_ACTION_INDEX_UP),
"Action not set."
);
}

it("handles neutral motion") {
e.jaxis.value = GenerateAxisValueWithinThreshold(state[p].config.axis_threshold);;
action[p] = 0;

printf("(axis value: %d) ", e.jaxis.value);
IZ_JoystickHandleEvents(&state, &action, e);
check(
action[p] == 0,
"Action not set."
);
}
}
}

describe("on hat motion events") {
before_each() {
e.type = SDL_JOYHATMOTION;
}

for (u8 i = 0; i < 4; i += 1) {
it("handles motion for %s action", IZ_ACTION_NAMES[i]) {
e.jhat.value = (0x1u << i);
action[p] = 0;

IZ_JoystickHandleEvents(&state, &action, e);
check(
action[p] == (0x1u << i),
"Action not set."
);
}

it("handles motion for %s deactivation", IZ_ACTION_NAMES[i]) {
e.jhat.value = 0;
action[p] = ~0;

IZ_JoystickHandleEvents(&state, &action, e);
check(
!(action[p] & (0x1 << i)),
"Action not unset."
);
it("handles %s negative motion deactivation", axis_name) {
e.type = SDL_CONTROLLERAXISMOTION;
e.caxis.axis = i;
e.caxis.value = -(IZ_GAME_CONTROLLER_AXIS_THRESHOLD - 1);
sprintf(state[p].config.control_mapping[0], "axis:-%s", axis_name);
action[p] = 1;
IZ_GameControllerHandleEvents(&state, &action, e);
check(action[p] != 1, "Action not unset. %d", action[p]);
}
}
}

describe("on button events") {
for (u8 i = 4; i < IZ_CONTROLS; i += 1) {
it("handles %s action activation", IZ_ACTION_NAMES[i]) {
e.type = SDL_JOYBUTTONDOWN;
e.jbutton.button = IZ_JOYSTICK_DEFAULT_STATE[p].config.control_mapping[i];
state[p].config.control_mapping[i] = IZ_JOYSTICK_DEFAULT_STATE[p].config.control_mapping[i];
for (u8 i = 0; i < SDL_CONTROLLER_BUTTON_MAX; i += 1) {
static const char* button_name;
button_name = SDL_GameControllerGetStringForButton(i);
it("handles %s action activation", button_name) {
e.type = SDL_CONTROLLERBUTTONDOWN;
e.cbutton.button = i;
sprintf(state[p].config.control_mapping[0], "button:%s", button_name);
action[p] = 0;

if (i == IZ_ACTION_INDEX_ACTION2) {
;
}

if (i == IZ_ACTION_INDEX_ACTION4) {
;
}

IZ_JoystickHandleEvents(&state, &action, e);
check(
action[p] == (0x1u << i),
"Action not set."
);
IZ_GameControllerHandleEvents(&state, &action, e);
check(action[p] != 0, "Action not set.");
}

it("handles %s action deactivation", IZ_ACTION_NAMES[i]) {
e.type = SDL_JOYBUTTONUP;
e.jbutton.button = IZ_JOYSTICK_DEFAULT_STATE[p].config.control_mapping[i];
state[p].config.control_mapping[i] = IZ_JOYSTICK_DEFAULT_STATE[p].config.control_mapping[i];
action[p] = ~0;

IZ_JoystickHandleEvents(&state, &action, e);
check(
!(action[p] & (0x1 << i)),
"Action not unset."
);
it("handles %s action deactivation", button_name) {
e.type = SDL_CONTROLLERBUTTONUP;
e.cbutton.button = i;
sprintf(state[p].config.control_mapping[0], "button:%s", button_name);
action[p] = 1;
IZ_GameControllerHandleEvents(&state, &action, e);
check(action[p] != 1, "Action not unset.");
}
}
}
@@ -359,7 +160,7 @@ spec("input") {
}

describe("SaveConfig") {
static IZ_JoystickState state[IZ_PLAYERS];
static IZ_GameControllerState state[IZ_PLAYERS];

after_each() {
mock_reset(INI_ConfigSave);
@@ -368,13 +169,18 @@ spec("input") {
before_each() {
for (u8 p = 0; p < IZ_PLAYERS; p += 1) {
for (u8 i = 0; i < IZ_CONTROLS; i += 1) {
state[p].config.control_mapping[i] = IZ_JOYSTICK_DEFAULT_STATE[p].config.control_mapping[i];
IZ_memcpy(
state[p].config.control_mapping[i],
IZ_GAME_CONTROLLER_MAX_CONTROL_NAME_LENGTH,
IZ_GAME_CONTROLLER_DEFAULT_STATE[p].config.control_mapping[i],
IZ_GAME_CONTROLLER_MAX_CONTROL_NAME_LENGTH
);
}
}
}

it("calls save method") {
IZ_JoystickSaveConfig(&state, IZ_CONFIG_GAME_PATH);
IZ_GameControllerSaveConfig(&state, IZ_CONFIG_GAME_PATH);

check(mock_is_called(INI_ConfigSave), "Config save function not called.");
}
@@ -382,7 +188,7 @@ spec("input") {

describe("Teardown") {
static void* device = (void*) 1;
static IZ_JoystickState state[IZ_PLAYERS] = {};
static IZ_GameControllerState state[IZ_PLAYERS] = {};

before_each() {
for (u8 p = 0; p < IZ_PLAYERS; p += 1) {
@@ -391,19 +197,19 @@ spec("input") {
}

after_each() {
mock_reset(SDL_JoystickClose);
mock_reset(SDL_GameControllerClose);
}

it("closes opened devices") {
mock_set_expected_calls(SDL_JoystickClose, IZ_PLAYERS);
mock_set_expected_calls(SDL_GameControllerClose, IZ_PLAYERS);

IZ_JoystickTeardown(&state);
IZ_GameControllerTeardown(&state);

check(
mock_get_expected_calls(SDL_JoystickClose) == mock_get_actual_calls(SDL_JoystickClose),
"Call count mismatch for SDL_JoystickClose() (expected %u, received %u).",
mock_get_expected_calls(SDL_JoystickClose),
mock_get_actual_calls(SDL_JoystickClose)
mock_get_expected_calls(SDL_GameControllerClose) == mock_get_actual_calls(SDL_GameControllerClose),
"Call count mismatch for SDL_GameControllerClose() (expected %u, received %u).",
mock_get_expected_calls(SDL_GameControllerClose),
mock_get_actual_calls(SDL_GameControllerClose)
);
}
}


BIN
assets_src/gfx/weapons-rigged.cdr Vedi File


+ 43
- 18
docs/controls.md Vedi File

@@ -1,20 +1,45 @@
# Controls

| Action | XInput | PS4 | Effect | Remarks |
|---------|---------:|---------:|-----------------------------------|--------------------------------------------------------------------------------------------------------|
| Up | A1+, A3+ | A1+, A4+ | Select Menu Item Up/Look Up | |
| Right | A0+, A2+ | A0+, A2+ | Select Menu Item Right/Move Right | |
| Down | A1-, A3- | A1-, A4- | Select Menu Item Down/Crouch | |
| Left | A0-, A2- | A0-, A2- | Select Menu Item Left/Move Left | |
| Affirm | B11 | | Confirm Selected Option | |
| Negate | B10 | | Go Back | |
| Action0 | B1 | B2 | Jump | When crouched, player will go down a solid-on-top ground. |
| Action1 | B0 | B1 | Primary Fire | Each weapon has firing characteristics, see below. |
| Action2 | B4 | | Secondary Fire | Each weapon has firing characteristics, see below. |
| Action3 | B3 | | Reload | Reload always drops current clip regardless if there are rounds left. |
| Action4 | B6 | | Switch Weapon Mode | Press to select next weapon mode (cycle), hold then press Left/Right to set previous/next weapon mode. |
| Action5 | B7 | | Switch Weapon | Press to select next weapon (cycle), hold then press Left/Right to set previous/next weapon. |
| Action6 | B8 | | Item/Inventory | Hold to open inventory, double press to use current item. |
| Action7 | B9 | | Switch Item | Press to select next item (cycle), hold then press Left/Right to set previous/next item. |
| Action8 | B13 | | Take Cover | Enter doors, go between objects to hide from enemies. |
| Action9 | B14 | | Sneak | Hold then press Left/Right to sneak. (do we need this control, or crouch is enough?) |
| Action | Default Control | Effect | Remarks |
|---------|------------------------|-----------------------------------|--------------------------------------------------------------------------------------------------------|
| Up | DPad Up/Stick Up | Select Menu Item Up/Look Up | |
| Right | DPad Right/Stick Right | Select Menu Item Right/Move Right | |
| Down | DPad Down/Stick Down | Select Menu Item Down/Crouch | |
| Left | DPad Left/Stick Left | Select Menu Item Left/Move Left | |
| Affirm | Start | Confirm Selected Option | |
| Negate | Select (Back) | Go Back | |
| Action0 | Button X | Jump | When crouched, player will go down a solid-on-top ground. |
| Action1 | Right Trigger | Primary Fire | Each weapon has firing characteristics, see below. |
| Action2 | Left Trigger | Secondary Fire | Each weapon has firing characteristics, see below. |
| Action3 | Button A | Reload | Reload always drops current clip regardless if there are rounds left. |
| Action4 | Button Y | Switch Weapon Mode | Press to select next weapon mode (cycle), hold then press Left/Right to set previous/next weapon mode. |
| Action5 | Right Bumper/Shoulder | Switch Weapon | Press to select next weapon (cycle), hold then press Left/Right to set previous/next weapon. |
| Action6 | Left Stick Button | Item/Inventory | Hold to open inventory, double press to use current item. |
| Action7 | Right Stick Button | Switch Item | Press to select next item (cycle), hold then press Left/Right to set previous/next item. |
| Action8 | Left Bumper/Shoulder | Take Cover | Enter doors, go between objects to hide from enemies. |
| Action9 | Button B | Sneak | Hold then press Left/Right to sneak. (do we need this control, or crouch is enough?) |

# Control Internals

| Control | Config Key |
|-----------------------|------------------------|
| DPad Up | `button:dpup` |
| DPad Right | `button:dpright` |
| DPad Down | `button:dpdown` |
| DPad Left | `button:dpleft` |
| Start | `button:start` |
| Select (Back) | `button:back` |
| Button A | `button:a` |
| Button B | `button:b` |
| Button X | `button:x` |
| Button Y | `button:y` |
| Right Bumper/Shoulder | `button:rightshoulder` |
| Right Trigger | `axis:+righttrigger` |
| Left Stick Button | `button:leftstick` |
| Right Stick Button | `button:rightstick` |
| Left Bumper/Shoulder | `button:leftshoulder` |
| Left Trigger | `axis:lefttrigger` |

> **Note:** The config keys are based from SDL internal names, only we have added the `button:` and `axis:` bind
> prefixes to be flexible on setting up controls on the gamepad. The reason is because gamepad controls use different
> types of binds.

+ 2
- 2
src/packages/config/IZ_config_guid.c Vedi File

@@ -26,7 +26,7 @@ void INI_ConfigEnsureValidGuid(INI_ConfigItem* item, SDL_GUID raw_value, SDL_GUI
*dest = raw_value;
}

void INI_ConfigLoadGuid(INI_ConfigItem* item, const char* config_path) {
void INI_ConfigLoadGuid(INI_ConfigItem* item, const char* config_path, void* item_array) {
static SDL_GUID raw_value;
static SDL_GUID default_value = {
.data = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
@@ -53,7 +53,7 @@ void INI_ConfigLoadGuid(INI_ConfigItem* item, const char* config_path) {
INI_ConfigEnsureValidGuid(item, raw_value, default_value);
}

INI_ConfigSaveItemResult INI_ConfigSaveGuid(INI_ConfigItem* item, const char* config_path) {
INI_ConfigSaveItemResult INI_ConfigSaveGuid(INI_ConfigItem* item, const char* config_path, void* item_array) {
SDL_GUID dest = *((SDL_GUID*) item->dest);
if (item->validator) {
INI_ConfigLoadParamsGuidValidator* validate = item->validator;


+ 272
- 0
src/packages/game/input/IZ_gamecontroller.c Vedi File

@@ -0,0 +1,272 @@
#include "IZ_gamecontroller.h"

static INI_ConfigItem game_controller_config_items[IZ_PLAYERS * (IZ_CONTROLS + IZ_GAME_CONTROLLER_DEFAULT_CONFIGS) + 1];

bool IZ_GameControllerIsValidAxisThreshold(u16 value) {
return (IZ_GAME_CONTROLLER_MIN_AXIS_THRESHOLD <= value && value <= IZ_GAME_CONTROLLER_MAX_AXIS_THRESHOLD);
}

void IZ_GameControllerHandleDeviceEvents(IZ_GameControllerState* state, SDL_Event e) {
if (e.type == SDL_CONTROLLERDEVICEADDED) {
u8 game_controllers_count = SDL_NumJoysticks();
if (game_controllers_count <= IZ_PLAYERS && !state->device) {
state->device = SDL_GameControllerOpen(e.cdevice.which);
}
return;
}

if (e.type == SDL_CONTROLLERDEVICEREMOVED) {
if (
state->device
&& SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(state->device)) == e.cdevice.which
) {
state->device = NULL;
}
}
}

void IZ_GameControllerHandleAxisEvents(IZ_GameControllerState* state, IZ_Action* action, SDL_Event e) {
if (e.type != SDL_CONTROLLERAXISMOTION) {
return;
}

u8 control_index;

for (control_index = 0; control_index < IZ_CONTROLS; control_index += 1) {
const char* current_axis_name = SDL_GameControllerGetStringForAxis(e.caxis.axis);
if (!current_axis_name) {
continue;
}

char current_positive_axis_full_name[IZ_GAME_CONTROLLER_MAX_CONTROL_NAME_LENGTH];
sprintf(
current_positive_axis_full_name,
"axis:+%s",
current_axis_name
);

char current_negative_axis_full_name[IZ_GAME_CONTROLLER_MAX_CONTROL_NAME_LENGTH];
sprintf(
current_negative_axis_full_name,
"axis:-%s",
current_axis_name
);

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)
) {
*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
}

char current_axis_full_name[IZ_GAME_CONTROLLER_MAX_CONTROL_NAME_LENGTH];
if (e.caxis.value > 0) {
IZ_memcpy(
current_axis_full_name,
IZ_GAME_CONTROLLER_MAX_CONTROL_NAME_LENGTH,
current_positive_axis_full_name,
IZ_GAME_CONTROLLER_MAX_CONTROL_NAME_LENGTH
);
is_capture = e.caxis.value > state->config.axis_threshold;
}
if (e.caxis.value < 0) {
IZ_memcpy(
current_axis_full_name,
IZ_GAME_CONTROLLER_MAX_CONTROL_NAME_LENGTH,
current_negative_axis_full_name,
IZ_GAME_CONTROLLER_MAX_CONTROL_NAME_LENGTH
);
is_capture = e.jaxis.value <= -state->config.axis_threshold;
}

if (!strstr(state->config.control_mapping[control_index], current_axis_full_name)) {
continue;
}

if (!is_capture) {
continue;
}

*action |= bitflag;
}
}

void IZ_GameControllerHandleButtonEvents(IZ_GameControllerState* state, IZ_Action* action, SDL_Event e) {
u8 control_index;
for (control_index = 0; control_index < IZ_CONTROLS; control_index += 1) {
const char* current_button_name = SDL_GameControllerGetStringForButton(e.cbutton.button);
if (!current_button_name) {
continue;
}

char current_button_full_name[IZ_GAME_CONTROLLER_MAX_CONTROL_NAME_LENGTH];
sprintf(
current_button_full_name,
"button:%s",
current_button_name
);

if (!strstr(state->config.control_mapping[control_index], current_button_full_name)) {
continue;
}

const u16 bitflag = (0x1 << control_index);
if (e.type == SDL_CONTROLLERBUTTONDOWN) {
*action |= bitflag;
return;
}

if (e.type == SDL_CONTROLLERBUTTONUP) {
*action &= ~bitflag;
return;
}
}
}

void IZ_GameControllerHandleEvents(IZ_GameControllerState(* state)[IZ_PLAYERS], IZ_Action(* action)[IZ_PLAYERS], SDL_Event e) {
u8 player_index;
for (player_index = 0; player_index < IZ_PLAYERS; player_index += 1) {
IZ_GameControllerHandleDeviceEvents(&(*state)[player_index], e);
IZ_GameControllerHandleAxisEvents(&(*state)[player_index], &(*action)[player_index], e);
IZ_GameControllerHandleButtonEvents(&(*state)[player_index], &(*action)[player_index], e);
}
}

void IZ_GameControllerBindStateToConfig(IZ_GameControllerState(* state)[IZ_PLAYERS], INI_ConfigItem config_items[]) {
u8 player_index;
u8 control_index;
for (player_index = 0; player_index < IZ_PLAYERS; player_index += 1) {
// The `+ 3` corresponds to the first three config items. Add as appropriate.
u8 base_index = (player_index * (IZ_CONTROLS + IZ_GAME_CONTROLLER_DEFAULT_CONFIGS));
config_items[base_index + 0].dest = &((*state)[player_index].config.axis_threshold);
config_items[base_index + 1].dest = &((*state)[player_index].config.guid);
for (control_index = 0; control_index < IZ_CONTROLS; control_index += 1) {
config_items[base_index + IZ_GAME_CONTROLLER_DEFAULT_CONFIGS + control_index].dest = &((*state)[player_index].config.control_mapping[control_index]);
}
}
}

IZ_ProcedureResult IZ_GameControllerSaveConfig(IZ_GameControllerState(* state)[IZ_PLAYERS], const char* config_path) {
IZ_GameControllerBindStateToConfig(state, game_controller_config_items);
return INI_ConfigSave(game_controller_config_items, config_path);
}

void IZ_GameControllerInitializeConfigItems(INI_ConfigItem config_items[]) {
u8 player_index;
u8 control_index;
char* main_section_name;
char* control_mapping_section_name;
for (player_index = 0; player_index < IZ_PLAYERS; player_index += 1) {
main_section_name = IZ_calloc(64, sizeof(char));
sprintf(main_section_name, "GameController.%d", player_index);
// The `+ 3` corresponds to the first three config items. Add as appropriate.
u8 base_index = (player_index * (IZ_CONTROLS + IZ_GAME_CONTROLLER_DEFAULT_CONFIGS));
config_items[base_index + 0] = (INI_ConfigItem) {
INI_CONFIG_TYPE_U16,
main_section_name,
"AxisThreshold",
NULL,
&IZ_GAME_CONTROLLER_DEFAULT_STATE[player_index].config.axis_threshold,
IZ_GameControllerIsValidAxisThreshold,
INI_CONFIG_TRANSFORMER_NONE,
NULL,
};

config_items[base_index + 1] = (INI_ConfigItem) {
INI_CONFIG_TYPE_GUID,
main_section_name,
"GUID",
NULL,
&IZ_GAME_CONTROLLER_DEFAULT_STATE[player_index].config.guid,
NULL,
INI_CONFIG_TRANSFORMER_NONE,
NULL,
};

control_mapping_section_name = IZ_calloc(64, sizeof(char));
sprintf(control_mapping_section_name, "GameController.%d.ControlMapping", player_index);
for (control_index = 0; control_index < IZ_CONTROLS; control_index += 1) {
config_items[base_index + IZ_GAME_CONTROLLER_DEFAULT_CONFIGS + control_index] = (INI_ConfigItem) {
INI_CONFIG_TYPE_STRING(IZ_GAME_CONTROLLER_MAX_CONTROL_NAME_LENGTH),
control_mapping_section_name,
IZ_ACTION_NAMES[control_index],
NULL,
&IZ_GAME_CONTROLLER_DEFAULT_STATE[player_index].config.control_mapping[control_index],
NULL,
INI_CONFIG_TRANSFORMER_NONE,
NULL,
};
}
}

config_items[IZ_PLAYERS * (IZ_CONTROLS + IZ_GAME_CONTROLLER_DEFAULT_CONFIGS)] = INI_CONFIG_ITEM_NULL;
}

IZ_ProcedureResult IZ_GameControllerInitializeConfig(IZ_GameControllerState(* state)[IZ_PLAYERS], const char* config_path, u8 argc, const char* argv[]) {
IZ_GameControllerInitializeConfigItems(game_controller_config_items);
IZ_GameControllerBindStateToConfig(state, game_controller_config_items);
if (INI_ConfigInitialize(game_controller_config_items, config_path, argc, argv) < 0) {
return -1;
}
return 0;
}

IZ_ProcedureResult IZ_GameControllerInitialize(IZ_GameControllerState(* state)[IZ_PLAYERS], const char* config_path, u8 argc, const char* argv[]) {
IZ_memcpy(state, sizeof(IZ_GameControllerState) * IZ_PLAYERS, &IZ_GAME_CONTROLLER_DEFAULT_STATE, sizeof(IZ_GameControllerState) * IZ_PLAYERS);

// TODO query this file from the internet?
IZ_LogInfo(IZ_LOG_CATEGORY_GENERIC, "input", "Loading game controller mappings file: %s", "assets/gamecontrollerdb.txt");
const i16 loaded_mappings = SDL_GameControllerAddMappingsFromFile("assets/gamecontrollerdb.txt");
if (loaded_mappings <= 0) {
return -1;
}
IZ_LogInfo(IZ_LOG_CATEGORY_GENERIC, "input", "Mappings loaded: %d", loaded_mappings);
u8 player_index;

if (IZ_GameControllerInitializeConfig(state, config_path, argc, argv) < 0) {
return -2;
}

u8 game_controllers_count = SDL_NumJoysticks();
for (player_index = 0; player_index < game_controllers_count; player_index += 1) {
if (player_index >= IZ_PLAYERS) {
break;
}

(*state)[player_index].device = SDL_GameControllerOpen(state[player_index]->config.device_id);
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));
}

// Post config (after game_controller GUIDs have been queried), this is unique to game_controllers since they can be plugged in any
// time.
INI_ConfigSaveResult post_config_save_result = IZ_GameControllerSaveConfig(state, config_path);
if (post_config_save_result < 0) {
return -3;
}

return 0;
}

void IZ_GameControllerTeardown(IZ_GameControllerState(* state)[IZ_PLAYERS]) {
u8 player_index;
for (player_index = 0; player_index < IZ_PLAYERS; player_index += 1) {
if (!(*state)[player_index].device) {
continue;
}
SDL_GameControllerClose((*state)[player_index].device);
}
}

+ 104
- 0
src/packages/game/input/IZ_gamecontroller.h Vedi File

@@ -0,0 +1,104 @@
#ifndef IZ_GAMECONTROLLER_H
#define IZ_GAMECONTROLLER_H

#include <SDL_gamecontroller.h>
#include <SDL_events.h>
#include <ini-config.h>
#include <ini-config/source/types/int.h>
#include <ini-config/source/types/string.h>
#include "../../config/IZ_config_guid.h"
#include "../../common/IZ_common.h"
#include "../../stdinc/IZ_string.h"
#include "../../stdinc/IZ_stdlib.h"
#include "../../log/IZ_log.h"
#include "IZ_action.h"

#define IZ_GAME_CONTROLLER_AXIS_THRESHOLD ((u16) 8000)

#define IZ_GAME_CONTROLLER_MIN_AXIS_THRESHOLD ((u16) 4000)
#define IZ_GAME_CONTROLLER_MAX_AXIS_THRESHOLD ((u16) 12000)

#define IZ_GAME_CONTROLLER_DEFAULT_CONFIGS 2

#define IZ_GAME_CONTROLLER_MAX_CONTROL_NAME_LENGTH 64

typedef struct {
u16 axis_threshold;
SDL_JoystickID device_id;
SDL_GUID guid;
const char control_mapping[IZ_CONTROLS][IZ_GAME_CONTROLLER_MAX_CONTROL_NAME_LENGTH];
} IZ_GameControllerConfig;

typedef struct {
SDL_GameController* device;
IZ_GameControllerConfig config;
} IZ_GameControllerState;

static const IZ_GameControllerState IZ_GAME_CONTROLLER_DEFAULT_STATE[IZ_PLAYERS] = {
{
.config = {
.control_mapping = {
"button:dpup axis:+lefty axis:+righty",
"button:dpright axis:+leftx axis:+rightx",
"button:dpdown axis:-lefty axis:-righty",
"button:dpleft axis:-leftx axis:-rightx",
"button:start",
"button:back",
"button:x",
"axis:+righttrigger",
"axis:+lefttrigger",
"button:a",
"button:y",
"button:rightshoulder",
"button:leftstick",
"button:rightstick",
"button:leftshoulder",
"button:b",
},
.axis_threshold = IZ_GAME_CONTROLLER_AXIS_THRESHOLD,
.guid = {
.data = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
},
},
.device = NULL,
},
#if IZ_PLAYERS > 1
{
.config = {
.control_mapping = {
"button:dpadup",
"button:dpadright",
"button:dpaddown",
"button:dpadleft",
"button:start",
"button:back",
"button:x",
"button:y",
"button:a",
"button:b",
"button:rightshoulder",
"axis:righttrigger",
"button:leftstick",
"button:rightstick",
"button:leftshoulder",
"axis:lefttrigger",
},
.axis_threshold = 8000u,
.guid = {
.data = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
},
},
.device = NULL,
},
#endif
};

IZ_ProcedureResult IZ_GameControllerSaveConfig(IZ_GameControllerState(*)[IZ_PLAYERS], const char*);

void IZ_GameControllerHandleEvents(IZ_GameControllerState(*)[IZ_PLAYERS], IZ_Action(*)[IZ_PLAYERS], SDL_Event);

IZ_ProcedureResult IZ_GameControllerInitialize(IZ_GameControllerState(*)[IZ_PLAYERS], const char*, u8, const char*[]);

void IZ_GameControllerTeardown(IZ_GameControllerState(*)[IZ_PLAYERS]);

#endif

+ 4
- 4
src/packages/game/input/IZ_input.c Vedi File

@@ -1,7 +1,7 @@
#include "IZ_input.h"

void IZ_InputHandleSDLEvents(IZ_InputState* state, SDL_Event e) {
IZ_JoystickHandleEvents(&state->joystick_state, &state->action, e);
IZ_GameControllerHandleEvents(&state->game_controller_state, &state->action, e);
IZ_KeyboardHandleEvents(&state->keyboard_state, &state->action, e);
}

@@ -14,14 +14,14 @@ IZ_ProcedureResult IZ_InputInitialize(IZ_InputState* state, const char* config_p

*state = (IZ_InputState) {
.action = {},
.joystick_state = {},
.game_controller_state = {},
.midi_input_state = {},
.keyboard_state = {},
};

IZ_ProcedureResult result = 0;

if (IZ_JoystickInitialize(&state->joystick_state, config_path, argc, argv) < 0) {
if (IZ_GameControllerInitialize(&state->game_controller_state, config_path, argc, argv) < 0) {
result |= 1;
}

@@ -47,6 +47,6 @@ IZ_ProcedureResult IZ_InputInitialize(IZ_InputState* state, const char* config_p

void IZ_InputTeardown(IZ_InputState* state) {
IZ_LogInfo(IZ_LOG_CATEGORY_GLOBAL, "input", "Shutting down...");
IZ_JoystickTeardown(&state->joystick_state);
IZ_GameControllerTeardown(&state->game_controller_state);
IZ_MIDIInputTeardown(&state->midi_input_state);
}

+ 2
- 2
src/packages/game/input/IZ_input.h Vedi File

@@ -3,14 +3,14 @@

#include "IZ_action.h"
#include "IZ_keyboard.h"
#include "IZ_joystick.h"
#include "IZ_gamecontroller.h"
#include "IZ_midi.h"
#include "../../log/IZ_log.h"

typedef struct {
IZ_Action action[IZ_PLAYERS];
IZ_KeyboardState keyboard_state[IZ_PLAYERS];
IZ_JoystickState joystick_state[IZ_PLAYERS];
IZ_GameControllerState game_controller_state[IZ_PLAYERS];
IZ_MIDIInputState midi_input_state[IZ_PLAYERS];
} IZ_InputState;



+ 0
- 324
src/packages/game/input/IZ_joystick.c Vedi File

@@ -1,324 +0,0 @@
#include "IZ_joystick.h"

static INI_ConfigItem joystick_config_items[IZ_PLAYERS * (IZ_CONTROLS - 4 + 3) + 1];

bool IZ_JoystickIsValidAxisThreshold(u16 value) {
return (4000 <= value && value <= 12000);
}

void IZ_JoystickHandleDeviceEvents(IZ_JoystickState* state, SDL_Event e) {
if (e.type == SDL_JOYDEVICEADDED) {
u8 joysticks_count = SDL_NumJoysticks();
if (joysticks_count <= IZ_PLAYERS && !state->device) {
state->device = SDL_JoystickOpen(e.jdevice.which);
}
return;
}

if (e.type == SDL_JOYDEVICEREMOVED) {
if (
state->device
&& SDL_JoystickInstanceID(state->device) == e.jdevice.which
) {
state->device = NULL;
}
}
}

void IZ_JoystickHandleAxisEvents(IZ_JoystickState* state, IZ_Action* action, SDL_Event e) {
if (e.type == SDL_JOYAXISMOTION) {
// XInput handling
u8 control_index;
for (control_index = 4; control_index < IZ_CONTROLS; control_index += 1) {
if (e.jaxis.axis == IZ_JOY_AXIS_DIRECTION_LEFT_SHOULDER && state->config.control_mapping[control_index] == 10) {
const u16 bitflag = (0x1 << control_index);

if (e.jaxis.value > state->config.axis_threshold) {
*action |= bitflag;
return;
}

if (e.jaxis.value <= state->config.axis_threshold) {
*action &= ~bitflag;
return;
}
}

if (e.jaxis.axis == IZ_JOY_AXIS_DIRECTION_RIGHT_SHOULDER && state->config.control_mapping[control_index] == 11) {
const u16 bitflag = (0x1 << control_index);

if (e.jaxis.value > state->config.axis_threshold) {
*action |= bitflag;
return;
}

if (e.jaxis.value <= state->config.axis_threshold) {
*action &= ~bitflag;
return;
}
}
}

if (
e.jaxis.axis == IZ_JOY_AXIS_DIRECTION_HORIZONTAL1
|| e.jaxis.axis == IZ_JOY_AXIS_DIRECTION_HORIZONTAL2
) {
*action &= ~(0x1 << IZ_ACTION_INDEX_RIGHT);
*action &= ~(0x1 << IZ_ACTION_INDEX_LEFT);
if (e.jaxis.value > state->config.axis_threshold) {
*action |= (0x1 << IZ_ACTION_INDEX_RIGHT);
return;
}
if (e.jaxis.value <= -state->config.axis_threshold) {
*action |= (0x1 << IZ_ACTION_INDEX_LEFT);
}
return;
}
if (
e.jaxis.axis == IZ_JOY_AXIS_DIRECTION_VERTICAL1
|| e.jaxis.axis == IZ_JOY_AXIS_DIRECTION_VERTICAL2
) {
*action &= ~(0x1 << IZ_ACTION_INDEX_UP);
*action &= ~(0x1 << IZ_ACTION_INDEX_DOWN);
if (e.jaxis.value > state->config.axis_threshold) {
*action |= (0x1 << IZ_ACTION_INDEX_DOWN);
return;
}
if (e.jaxis.value <= -state->config.axis_threshold) {
*action |= (0x1 << IZ_ACTION_INDEX_UP);
}
}
}
}

void IZ_JoystickHandleHatEvents(IZ_Action* action, SDL_Event e) {
if (e.type == SDL_JOYHATMOTION) {
*action &= ~(0x1 << IZ_ACTION_INDEX_UP);
*action &= ~(0x1 << IZ_ACTION_INDEX_RIGHT);
*action &= ~(0x1 << IZ_ACTION_INDEX_DOWN);
*action &= ~(0x1 << IZ_ACTION_INDEX_LEFT);
if (e.jhat.value != 0) {
*action |= e.jhat.value;
}
}
}

void IZ_JoystickHandleButtonEvents(IZ_JoystickState* state, IZ_Action* action, SDL_Event e) {
u8 control_index;

SDL_JoystickGUID joystick_guid = SDL_JoystickGetGUID(SDL_JoystickFromInstanceID(e.jbutton.which));
bool is_valid_event = false;
for (u8 zz = 0; zz < 16; zz += 1) {
is_valid_event |= joystick_guid.data[zz] != 0;
}
if (!is_valid_event) {
return;
}

// printf("button event from guid: ");
// for (u8 zz = 0; zz < 16; zz += 1) {
// printf("%02x", joystick_guid.data[zz]);
// }
// printf("\n");

for (control_index = 4; control_index < IZ_CONTROLS; control_index += 1) {
u8 normalized_button = e.jbutton.button;

/*
* ZL ZR
* L R
*
* U SLCT STRT 3
* L R 2 0
* D 1
*
*
*
*/

// TODO test with XInput, make compatible with Apple

// TODO honor mapping with controller

#ifdef IZ_MACOS
//printf("%d\n", e.jbutton.button);
// if (e.jbutton.button == 2) {
// normalized_button = 4;
// } else if (e.jbutton.button == 6) {
// normalized_button = 11;
// } else if (e.jbutton.button == 4) {
// normalized_button = 10;
// }
#endif

if (normalized_button == state->config.control_mapping[control_index]) {
const u16 bitflag = (0x1 << control_index);

if (e.type == SDL_JOYBUTTONDOWN) {
*action |= bitflag;
return;
}

if (e.type == SDL_JOYBUTTONUP) {
*action &= ~bitflag;
return;
}
}
}
}

void IZ_JoystickHandleEvents(IZ_JoystickState(* state)[IZ_PLAYERS], IZ_Action(* action)[IZ_PLAYERS], SDL_Event e) {
u8 player_index;
for (player_index = 0; player_index < IZ_PLAYERS; player_index += 1) {
IZ_JoystickHandleDeviceEvents(&(*state)[player_index], e);
IZ_JoystickHandleAxisEvents(&(*state)[player_index], &(*action)[player_index], e);
IZ_JoystickHandleHatEvents(&(*action)[player_index], e);
IZ_JoystickHandleButtonEvents(&(*state)[player_index], &(*action)[player_index], e);
}
}

void IZ_JoystickBindStateToConfig(IZ_JoystickState(* state)[IZ_PLAYERS], INI_ConfigItem config_items[]) {
u8 player_index;
u8 control_index;
for (player_index = 0; player_index < IZ_PLAYERS; player_index += 1) {
u8 base_index = (player_index * (IZ_CONTROLS - 4 + 2));
config_items[base_index].dest = &((*state)[player_index].config.device_id);
config_items[base_index + 1].dest = &((*state)[player_index].config.axis_threshold);
config_items[base_index + 2].dest = &((*state)[player_index].config.guid);
for (control_index = 4; control_index < IZ_CONTROLS; control_index += 1) {
config_items[base_index + 3 + (control_index - 4)].dest = &((*state)[player_index].config.control_mapping[control_index]);
}
}
}

IZ_ProcedureResult IZ_JoystickSaveConfig(IZ_JoystickState(* state)[IZ_PLAYERS], const char* config_path) {
IZ_JoystickBindStateToConfig(state, joystick_config_items);
return INI_ConfigSave(joystick_config_items, config_path);
}

void IZ_JoystickInitializeConfigItems(INI_ConfigItem config_items[]) {
u8 player_index;
u8 control_index;
char* main_section_name;
char* control_mapping_section_name;
for (player_index = 0; player_index < IZ_PLAYERS; player_index += 1) {
main_section_name = IZ_calloc(64, sizeof(char));
sprintf(main_section_name, "Joystick.%d", player_index);
// The `+ 3` corresponds to the first three config items. Add as appropriate.
u8 base_index = (player_index * (IZ_CONTROLS - 4 + 3));
config_items[base_index] = (INI_ConfigItem) {
INI_CONFIG_TYPE_I32,
main_section_name,
"DeviceID",
NULL,
&IZ_JOYSTICK_DEFAULT_STATE[player_index].config.device_id,
NULL,
INI_CONFIG_TRANSFORMER_NONE,
NULL,
};

config_items[base_index + 1] = (INI_ConfigItem) {
INI_CONFIG_TYPE_U16,
main_section_name,
"AxisThreshold",
NULL,
&IZ_JOYSTICK_DEFAULT_STATE[player_index].config.axis_threshold,
IZ_JoystickIsValidAxisThreshold,
INI_CONFIG_TRANSFORMER_NONE,
NULL,
};

config_items[base_index + 2] = (INI_ConfigItem) {
INI_CONFIG_TYPE_GUID,
main_section_name,
"GUID",
NULL,
&IZ_JOYSTICK_DEFAULT_STATE[player_index].config.guid,
NULL,
INI_CONFIG_TRANSFORMER_NONE,
NULL,
};

// todo add game controller GUID for determining mappings

control_mapping_section_name = IZ_calloc(64, sizeof(char));
sprintf(control_mapping_section_name, "Joystick.%d.ControlMapping", player_index);
for (control_index = 4; control_index < IZ_CONTROLS; control_index += 1) {
config_items[base_index + 3 + (control_index - 4)] = (INI_ConfigItem) {
INI_CONFIG_TYPE_U8,
control_mapping_section_name,
IZ_ACTION_NAMES[control_index],
NULL,
&IZ_JOYSTICK_DEFAULT_STATE[player_index].config.control_mapping[control_index],
NULL,
INI_CONFIG_TRANSFORMER_NONE,
NULL,
};
}
}

config_items[IZ_PLAYERS * (IZ_CONTROLS - 4 + 3)] = INI_CONFIG_ITEM_NULL;
}

IZ_ProcedureResult IZ_JoystickInitializeConfig(IZ_JoystickState(* state)[IZ_PLAYERS], const char* config_path, u8 argc, const char* argv[]) {
IZ_JoystickInitializeConfigItems(joystick_config_items);
IZ_JoystickBindStateToConfig(state, joystick_config_items);
if (INI_ConfigInitialize(joystick_config_items, config_path, argc, argv) < 0) {
return -1;
}
return 0;
}

IZ_ProcedureResult IZ_JoystickInitialize(IZ_JoystickState(* state)[IZ_PLAYERS], const char* config_path, u8 argc, const char* argv[]) {
IZ_memcpy(state, sizeof(IZ_JoystickState) * IZ_PLAYERS, &IZ_JOYSTICK_DEFAULT_STATE, sizeof(IZ_JoystickState) * IZ_PLAYERS);

// TODO query this file from the internet?
SDL_GameControllerAddMappingsFromFile("assets/gamecontrollerdb.txt");
u8 player_index;

if (IZ_JoystickInitializeConfig(state, config_path, argc, argv) < 0) {
return -2;
}

u8 joysticks_count = SDL_NumJoysticks();
for (player_index = 0; player_index < joysticks_count; player_index += 1) {
if (player_index >= IZ_PLAYERS) {
break;
}

(*state)[player_index].device = SDL_JoystickOpen(state[player_index]->config.device_id);
if (!(*state)[player_index].device) {
break;
}

(*state)[player_index].config.device_id = SDL_JoystickInstanceID((*state)[player_index].device);
SDL_GUID joystick_guid = SDL_JoystickGetGUID((*state)[player_index].device);
IZ_memcpy(&(*state)[player_index].config.guid, sizeof(SDL_GUID), &joystick_guid, sizeof(SDL_GUID));
//(*state)[player_index].config.guid = joystick_guid;

// printf("[INPUT:JOYSTICK] Initialize event from GUID: ");
// for (u8 zz = 0; zz < 16; zz += 1) {
// printf("%02x", (*state)[player_index].config.guid.data[zz]);
// }
// printf("\n");
}

// Post config (after joystick GUIDs have been queried), this is unique to joysticks since they can be plugged in any
// time.
INI_ConfigSaveResult post_config_save_result = IZ_JoystickSaveConfig(state, config_path);
if (post_config_save_result < 0) {
return -3;
}

return 0;
}

void IZ_JoystickTeardown(IZ_JoystickState(* state)[IZ_PLAYERS]) {
u8 player_index;
for (player_index = 0; player_index < IZ_PLAYERS; player_index += 1) {
if (!(*state)[player_index].device) {
continue;
}
SDL_JoystickClose((*state)[player_index].device);
}
}

+ 0
- 106
src/packages/game/input/IZ_joystick.h Vedi File

@@ -1,106 +0,0 @@
#ifndef IZ_JOYSTICK_H
#define IZ_JOYSTICK_H

#include <SDL_joystick.h>
#include <SDL_gamecontroller.h>
#include <SDL_events.h>
#include <ini-config.h>
#include <ini-config/types/int.h>
#include "../../config/IZ_config_guid.h"
#include "../../common/IZ_common.h"
#include "../../stdinc/IZ_string.h"
#include "../../stdinc/IZ_stdlib.h"
#include "IZ_action.h"

typedef u8 IZ_PadButton;

#define IZ_DEFAULT_AXIS_THRESHOLD ((u16) 8000)

typedef enum {
IZ_JOY_AXIS_DIRECTION_HORIZONTAL1 = 0,
IZ_JOY_AXIS_DIRECTION_VERTICAL1 = 1,
IZ_JOY_AXIS_DIRECTION_HORIZONTAL2 = 2,
IZ_JOY_AXIS_DIRECTION_VERTICAL2 = 3,
IZ_JOY_AXIS_DIRECTION_LEFT_SHOULDER = 4,
IZ_JOY_AXIS_DIRECTION_RIGHT_SHOULDER = 5,
} IZ_JoyAxisDirection;

typedef struct {
u16 axis_threshold;
SDL_JoystickID device_id;
SDL_GUID guid;
IZ_PadButton control_mapping[IZ_CONTROLS];
} IZ_JoystickConfig;

typedef struct {
SDL_Joystick* device;
IZ_JoystickConfig config;
} IZ_JoystickState;

static const IZ_JoystickState IZ_JOYSTICK_DEFAULT_STATE[IZ_PLAYERS] = {
{
.config = {
.control_mapping = {
255,
255,
255,
255,
11,
10,
1,
0,
4,
3,
6,
7,
8,
9,
13,
14,
},
.axis_threshold = IZ_DEFAULT_AXIS_THRESHOLD,
.device_id = 0,
.guid = {
.data = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
}
},
.device = NULL,
},
#if IZ_PLAYERS > 1
{
.config = {
.control_mapping = {
255,
255,
255,
255,
11,
10,
1,
0,
4,
3,
6,
7,
8,
9,
13,
14,
},
.axis_threshold = 8000u,
.device_id = 1,
},
.device = NULL,
},
#endif
};

IZ_ProcedureResult IZ_JoystickSaveConfig(IZ_JoystickState(*)[IZ_PLAYERS], const char*);

void IZ_JoystickHandleEvents(IZ_JoystickState(*)[IZ_PLAYERS], IZ_Action(*)[IZ_PLAYERS], SDL_Event);

IZ_ProcedureResult IZ_JoystickInitialize(IZ_JoystickState(*)[IZ_PLAYERS], const char*, u8, const char*[]);

void IZ_JoystickTeardown(IZ_JoystickState(*)[IZ_PLAYERS]);

#endif

+ 2
- 2
src/packages/game/input/IZ_keyboard.c Vedi File

@@ -2,12 +2,12 @@

static INI_ConfigItem keyboard_config_items[IZ_PLAYERS * IZ_CONTROLS + 1];

void IZ_KeyboardSerializeControl(i32 value, char control[128]) {
void IZ_KeyboardSerializeControl(i32 value, char control[128], void* _unused) {
const char* serialized = SDL_GetKeyName(value);
IZ_memcpy(control, 128, serialized, 128);
}

i32 IZ_KeyboardDeserializeControl(const char* control) {
i32 IZ_KeyboardDeserializeControl(const char* control, void* _unused) {
return SDL_GetKeyFromName(control);
}



+ 1
- 1
src/packages/game/input/IZ_keyboard.h Vedi File

@@ -4,7 +4,7 @@
#include <SDL_keyboard.h>
#include <SDL_events.h>
#include <ini-config.h>
#include <ini-config/types/int.h>
#include <ini-config/source/types/int.h>
#include "../../stdinc/IZ_string.h"
#include "../../stdinc/IZ_stdlib.h"
#include "IZ_action.h"


+ 1
- 1
src/packages/game/input/IZ_midi.h Vedi File

@@ -6,7 +6,7 @@

#include <midi-utils.h>
#include <ini-config.h>
#include <ini-config/types/int.h>
#include <ini-config/source/types/int.h>
#include "../../stdinc/IZ_string.h"
#include "../../stdinc/IZ_stdlib.h"
#include "IZ_action.h"


+ 2
- 2
src/packages/net/IZ_net_client.h Vedi File

@@ -3,8 +3,8 @@

#include <SDL_thread.h>
#include <ini-config.h>
#include <ini-config/types/int.h>
#include <ini-config/types/string.h>
#include <ini-config/source/types/int.h>
#include <ini-config/source/types/string.h>

#include "../common/IZ_common.h"
#include "../game/input/IZ_action.h"


+ 1
- 1
subprojects/ini-config

@@ -1 +1 @@
Subproject commit b5007a86c4c9db88427362a9cda53ce8315cbfbd
Subproject commit f3eb15d59ce81fb92a16375189f1d4755e2b7574

Caricamento…
Annulla
Salva