Input bind complete.
This commit is contained in:
@@ -17,11 +17,12 @@ void cmdBind(const consolecmdexec_t *exec) {
|
||||
|
||||
if(exec->argc == 1) {
|
||||
consolePrint("TODO: Show binds");
|
||||
// consolePrint("Current binds:");
|
||||
// inputbinddata_t *data = INPUT.binds;
|
||||
// do {
|
||||
return;
|
||||
}
|
||||
|
||||
// } while(data < INPUT.binds + INPUT_BIND_COUNT);
|
||||
inputbutton_t button = inputButtonGetByName(exec->argv[0]);
|
||||
if(button.type == INPUT_BUTTON_TYPE_NONE) {
|
||||
consolePrint("Unknown button \"%s\"", exec->argv[0]);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -31,5 +32,7 @@ void cmdBind(const consolecmdexec_t *exec) {
|
||||
return;
|
||||
}
|
||||
|
||||
consolePrint("test");
|
||||
// By default I unbind all.
|
||||
inputUnbindButton(button);
|
||||
inputBind(bind, button);
|
||||
}
|
@@ -7,6 +7,8 @@
|
||||
target_sources(${DUSK_TARGET_NAME}
|
||||
PRIVATE
|
||||
input.c
|
||||
inputbutton.c
|
||||
inputbind.c
|
||||
)
|
||||
|
||||
if(DUSK_TARGET_SYSTEM STREQUAL "linux")
|
||||
|
@@ -9,30 +9,23 @@
|
||||
#include "assert/assert.h"
|
||||
#include "util/memory.h"
|
||||
#include "util/string.h"
|
||||
|
||||
char_t INPUT_BIND_NAMES[INPUT_BIND_COUNT][16] = {
|
||||
[INPUT_BIND_UP] = "UP",
|
||||
[INPUT_BIND_DOWN] = "DOWN",
|
||||
[INPUT_BIND_LEFT] = "LEFT",
|
||||
[INPUT_BIND_RIGHT] = "RIGHT",
|
||||
[INPUT_BIND_ACCEPT] = "ACCEPT",
|
||||
[INPUT_BIND_CANCEL] = "CANCEL",
|
||||
[INPUT_BIND_CONSOLE] = "CONSOLE"
|
||||
};
|
||||
#include "util/math.h"
|
||||
|
||||
input_t INPUT;
|
||||
|
||||
void inputInit(void) {
|
||||
memoryZero(&INPUT, sizeof(input_t));
|
||||
|
||||
INPUT.binds[INPUT_BIND_UP].keyboard[0] = SDL_SCANCODE_W;
|
||||
INPUT.binds[INPUT_BIND_UP].keyboard[1] = SDL_SCANCODE_UP;
|
||||
INPUT.binds[INPUT_BIND_CONSOLE].keyboard[0] = SDL_SCANCODE_GRAVE;
|
||||
for(uint8_t i = 0; i < INPUT_BIND_COUNT; i++) {
|
||||
INPUT.binds[i].bind = (inputbind_t)i;
|
||||
INPUT.binds[i].lastValue = 0.0f;
|
||||
INPUT.binds[i].currentValue = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
void inputUpdate(void) {
|
||||
#if INPUT_SDL2 == 1
|
||||
const uint8_t *keyboardState = SDL_GetKeyboardState(NULL);
|
||||
INPUT.keyboardState = SDL_GetKeyboardState(NULL);
|
||||
#endif
|
||||
|
||||
// For each input bind...
|
||||
@@ -41,20 +34,13 @@ void inputUpdate(void) {
|
||||
data->lastValue = data->currentValue;
|
||||
data->currentValue = 0.0f;
|
||||
|
||||
// Handle keyboard
|
||||
#if INPUT_KEYBOARD == 1
|
||||
for(uint32_t i = 0; i < INPUT_BIND_KEYBOARD_BUTTONS_MAX; i++) {
|
||||
if(data->keyboard[i] == 0) break;
|
||||
|
||||
#if INPUT_SDL2 == 1
|
||||
if(keyboardState[data->keyboard[i]]) {
|
||||
data->currentValue = 1.0f;
|
||||
break;
|
||||
for(uint8_t i = 0; i < INPUT_BIND_BUTTONS_MAX; i++) {
|
||||
inputbutton_t button = data->buttons[i];
|
||||
if(button.type == INPUT_BUTTON_TYPE_NONE) continue;// TODO: Break?
|
||||
data->currentValue = mathMax(
|
||||
inputButtonGetValue(button), data->currentValue
|
||||
);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
data++;
|
||||
} while(data < INPUT.binds + INPUT_BIND_COUNT);
|
||||
}
|
||||
@@ -85,12 +71,68 @@ bool_t inputReleased(const inputbind_t bind) {
|
||||
return !inputIsDown(bind) && inputWasDown(bind);
|
||||
}
|
||||
|
||||
inputbind_t inputBindGetByName(const char_t *name) {
|
||||
assertNotNull(name, "name must not be NULL");
|
||||
for(inputbind_t i = 0; i < INPUT_BIND_COUNT; i++) {
|
||||
if(stringCompareInsensitive(INPUT_BIND_NAMES[i], name) == 0) {
|
||||
return i;
|
||||
void inputBind(const inputbind_t bind, const inputbutton_t button) {
|
||||
assertTrue(bind < INPUT_BIND_COUNT, "Input bind out of bounds");
|
||||
|
||||
inputbinddata_t *data = &INPUT.binds[bind];
|
||||
|
||||
for(uint8_t i = 0; i < INPUT_BIND_BUTTONS_MAX; i++) {
|
||||
if(data->buttons[i].type != INPUT_BUTTON_TYPE_NONE) continue;
|
||||
data->buttons[i] = button;
|
||||
return;
|
||||
}
|
||||
}
|
||||
return INPUT_BIND_COUNT;
|
||||
|
||||
void inputUnbind(const inputbind_t bind, const inputbutton_t button) {
|
||||
assertTrue(bind < INPUT_BIND_COUNT, "Input bind out of bounds");
|
||||
|
||||
inputbinddata_t *data = &INPUT.binds[bind];
|
||||
|
||||
for(uint8_t i = 0; i < INPUT_BIND_BUTTONS_MAX; i++) {
|
||||
if(data->buttons[i].type == INPUT_BUTTON_TYPE_NONE) break;
|
||||
if(memoryCompare(&data->buttons[i], &button, sizeof(inputbutton_t)) != 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Shift remaining buttons down
|
||||
memoryMove(
|
||||
&data->buttons[i],
|
||||
&data->buttons[i + 1],
|
||||
sizeof(inputbutton_t) * (INPUT_BIND_BUTTONS_MAX - i - 1)
|
||||
);
|
||||
data->buttons[INPUT_BIND_BUTTONS_MAX - 1].type = INPUT_BUTTON_TYPE_NONE;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void inputUnbindAll(void) {
|
||||
for(uint8_t i = 0; i < INPUT_BIND_COUNT; i++) {
|
||||
memoryZero(
|
||||
&INPUT.binds[i].buttons,
|
||||
sizeof(inputbutton_t) * INPUT_BIND_BUTTONS_MAX
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void inputUnbindButton(const inputbutton_t button) {
|
||||
for(uint8_t i = 0; i < INPUT_BIND_COUNT; i++) {
|
||||
inputbinddata_t *data = &INPUT.binds[i];
|
||||
for(uint8_t j = 0; j < INPUT_BIND_BUTTONS_MAX; j++) {
|
||||
if(data->buttons[j].type == INPUT_BUTTON_TYPE_NONE) break;
|
||||
if(memoryCompare(&data->buttons[j], &button, sizeof(inputbutton_t)) != 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
inputUnbind((inputbind_t)i, button);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void inputUnbindBind(const inputbind_t bind) {
|
||||
assertTrue(bind < INPUT_BIND_COUNT, "Input bind out of bounds");
|
||||
|
||||
memoryZero(
|
||||
&INPUT.binds[bind].buttons,
|
||||
sizeof(inputbutton_t) * INPUT_BIND_BUTTONS_MAX
|
||||
);
|
||||
}
|
@@ -6,65 +6,19 @@
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "dusk.h"
|
||||
|
||||
#if INPUT_SDL2 == 1
|
||||
#include <SDL2/SDL.h>
|
||||
#else
|
||||
#error "No input backend defined"
|
||||
#endif
|
||||
|
||||
// Keyboard defs
|
||||
#if INPUT_KEYBOARD == 1
|
||||
#define INPUT_BIND_KEYBOARD_BUTTONS_MAX 32
|
||||
|
||||
#if INPUT_SDL2 == 1
|
||||
typedef SDL_Scancode inputscancode_t;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Gamepad defs
|
||||
#if INPUT_GAMEPAD == 1
|
||||
#define INPUT_GAMEPAD_BUTTON_NAME_MAX 8
|
||||
#define INPUT_BIND_GAMEPAD_BUTTONS_MAX 8
|
||||
|
||||
#if INPUT_SDL2 == 1
|
||||
typedef SDL_GameControllerButton inputgamepadbutton_t;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
INPUT_BIND_UP,
|
||||
INPUT_BIND_DOWN,
|
||||
INPUT_BIND_LEFT,
|
||||
INPUT_BIND_RIGHT,
|
||||
INPUT_BIND_ACCEPT,
|
||||
INPUT_BIND_CANCEL,
|
||||
INPUT_BIND_CONSOLE,
|
||||
|
||||
INPUT_BIND_COUNT
|
||||
} inputbind_t;
|
||||
|
||||
typedef struct {
|
||||
inputbind_t bind;
|
||||
float_t lastValue;
|
||||
float_t currentValue;
|
||||
|
||||
#if INPUT_GAMEPAD == 1
|
||||
inputgamepadbutton_t gamepad[INPUT_BIND_GAMEPAD_BUTTONS_MAX];
|
||||
uint8_t gamepadButtonCount;
|
||||
#endif
|
||||
|
||||
#if INPUT_KEYBOARD == 1
|
||||
inputscancode_t keyboard[INPUT_BIND_KEYBOARD_BUTTONS_MAX];
|
||||
#endif
|
||||
} inputbinddata_t;
|
||||
#include "inputbutton.h"
|
||||
#include "inputbind.h"
|
||||
|
||||
typedef struct {
|
||||
inputbinddata_t binds[INPUT_BIND_COUNT];
|
||||
|
||||
#if INPUT_SDL2 == 1
|
||||
#if INPUT_KEYBOARD == 1
|
||||
const uint8_t *keyboardState;
|
||||
#endif
|
||||
#endif
|
||||
} input_t;
|
||||
|
||||
extern char_t INPUT_BIND_NAMES[INPUT_BIND_COUNT][16];
|
||||
extern input_t INPUT;
|
||||
|
||||
/**
|
||||
@@ -127,9 +81,36 @@ bool_t inputPressed(const inputbind_t bind);
|
||||
bool_t inputReleased(const inputbind_t bind);
|
||||
|
||||
/**
|
||||
* Gets an input bind by its name.
|
||||
* Binds an input button to a specific input bind.
|
||||
*
|
||||
* @param name The name of the input bind.
|
||||
* @return The input bind, or INPUT_BIND_COUNT if not found.
|
||||
* @param bind The input bind to bind the button to.
|
||||
* @param button The input button to bind.
|
||||
*/
|
||||
inputbind_t inputBindGetByName(const char_t *name);
|
||||
void inputBind(const inputbind_t bind, const inputbutton_t button);
|
||||
|
||||
/**
|
||||
* Unbinds an input button from a specific input bind.
|
||||
*
|
||||
* @param bind The input bind to unbind the button from.
|
||||
* @param button The input button to unbind.
|
||||
*/
|
||||
void inputUnbind(const inputbind_t bind, const inputbutton_t button);
|
||||
|
||||
/**
|
||||
* Unbinds all input buttons from all input binds.
|
||||
*/
|
||||
void inputUnbindAll();
|
||||
|
||||
/**
|
||||
* Unbinds an input button from all input binds.
|
||||
*
|
||||
* @param button The input button to unbind.
|
||||
*/
|
||||
void inputUnbindButton(const inputbutton_t button);
|
||||
|
||||
/**
|
||||
* Unbinds all input buttons from a specific input bind.
|
||||
*
|
||||
* @param bind The input bind to unbind all buttons from.
|
||||
*/
|
||||
void inputUnbindBind(const inputbind_t bind);
|
30
src/input/inputbind.c
Normal file
30
src/input/inputbind.c
Normal file
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "inputbind.h"
|
||||
#include "assert/assert.h"
|
||||
#include "util/string.h"
|
||||
|
||||
const char_t INPUT_BIND_NAMES[INPUT_BIND_COUNT][INPUT_BIND_NAME_MAX] = {
|
||||
[INPUT_BIND_UP] = "UP",
|
||||
[INPUT_BIND_DOWN] = "DOWN",
|
||||
[INPUT_BIND_LEFT] = "LEFT",
|
||||
[INPUT_BIND_RIGHT] = "RIGHT",
|
||||
[INPUT_BIND_ACCEPT] = "ACCEPT",
|
||||
[INPUT_BIND_CANCEL] = "CANCEL",
|
||||
[INPUT_BIND_CONSOLE] = "CONSOLE"
|
||||
};
|
||||
|
||||
inputbind_t inputBindGetByName(const char_t *name) {
|
||||
assertNotNull(name, "name must not be NULL");
|
||||
for(inputbind_t i = 0; i < INPUT_BIND_COUNT; i++) {
|
||||
if(stringCompareInsensitive(INPUT_BIND_NAMES[i], name) == 0) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return INPUT_BIND_COUNT;
|
||||
}
|
41
src/input/inputbind.h
Normal file
41
src/input/inputbind.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "inputbutton.h"
|
||||
|
||||
#define INPUT_BIND_NAME_MAX 16
|
||||
#define INPUT_BIND_BUTTONS_MAX 32
|
||||
|
||||
typedef enum {
|
||||
INPUT_BIND_UP,
|
||||
INPUT_BIND_DOWN,
|
||||
INPUT_BIND_LEFT,
|
||||
INPUT_BIND_RIGHT,
|
||||
INPUT_BIND_ACCEPT,
|
||||
INPUT_BIND_CANCEL,
|
||||
INPUT_BIND_CONSOLE,
|
||||
|
||||
INPUT_BIND_COUNT
|
||||
} inputbind_t;
|
||||
|
||||
typedef struct {
|
||||
inputbind_t bind;
|
||||
float_t lastValue;
|
||||
float_t currentValue;
|
||||
inputbutton_t buttons[INPUT_BIND_BUTTONS_MAX];
|
||||
} inputbinddata_t;
|
||||
|
||||
extern const char_t INPUT_BIND_NAMES[INPUT_BIND_COUNT][INPUT_BIND_NAME_MAX];
|
||||
|
||||
/**
|
||||
* Gets an input bind by its name.
|
||||
*
|
||||
* @param name The name of the input bind.
|
||||
* @return The input bind, or INPUT_BIND_COUNT if not found.
|
||||
*/
|
||||
inputbind_t inputBindGetByName(const char_t *name);
|
69
src/input/inputbutton.c
Normal file
69
src/input/inputbutton.c
Normal file
@@ -0,0 +1,69 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "inputbutton.h"
|
||||
#include "input.h"
|
||||
#include "assert/assert.h"
|
||||
#include "util/string.h"
|
||||
|
||||
const inputbuttondata_t INPUT_BUTTON_DATA[] = {
|
||||
#if INPUT_SDL2 == 1
|
||||
#if INPUT_GAMEPAD == 1
|
||||
#if PSP
|
||||
#else
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if INPUT_KEYBOARD == 1
|
||||
{ .name = "a", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_A } },
|
||||
{ .name = "`", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_GRAVE } },
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
|
||||
inputbutton_t inputButtonGetByName(const char_t *name) {
|
||||
assertNotNull(name, "name must not be NULL");
|
||||
|
||||
uint32_t len = sizeof(INPUT_BUTTON_DATA) / sizeof(inputbuttondata_t);
|
||||
|
||||
for(uint32_t i = 0; i < len; i++) {
|
||||
if(stringCompareInsensitive(INPUT_BUTTON_DATA[i].name, name) != 0) continue;
|
||||
return INPUT_BUTTON_DATA[i].button;
|
||||
}
|
||||
|
||||
return (inputbutton_t){ .type = INPUT_BUTTON_TYPE_NONE };
|
||||
}
|
||||
|
||||
float_t inputButtonGetValue(const inputbutton_t button) {
|
||||
switch(button.type) {
|
||||
#if INPUT_KEYBOARD == 1
|
||||
case INPUT_BUTTON_TYPE_KEYBOARD: {
|
||||
#if INPUT_SDL2 == 1
|
||||
return INPUT.keyboardState[button.scancode] ? 1.0f : 0.0f;
|
||||
#else
|
||||
return 0.0f;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#if INPUT_GAMEPAD == 1
|
||||
case INPUT_BUTTON_TYPE_GAMEPAD: {
|
||||
#if INPUT_SDL2 == 1
|
||||
if(SDL_GameControllerGetButton(
|
||||
SDL_GameControllerFromInstanceID(0), button.gpButton
|
||||
)) return 1.0f;
|
||||
#endif
|
||||
return 0.0f;
|
||||
}
|
||||
#endif
|
||||
|
||||
default: {
|
||||
assertUnreachable("Unknown input button type");
|
||||
return 0.0f;
|
||||
}
|
||||
}
|
||||
}
|
79
src/input/inputbutton.h
Normal file
79
src/input/inputbutton.h
Normal file
@@ -0,0 +1,79 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "dusk.h"
|
||||
|
||||
#if INPUT_SDL2 == 1
|
||||
#include <SDL2/SDL.h>
|
||||
#else
|
||||
#error "No input backend defined"
|
||||
#endif
|
||||
|
||||
// Keyboard defs
|
||||
#if INPUT_KEYBOARD == 1
|
||||
#if INPUT_SDL2 == 1
|
||||
typedef SDL_Scancode inputscancode_t;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Gamepad defs
|
||||
#if INPUT_GAMEPAD == 1
|
||||
#if INPUT_SDL2 == 1
|
||||
typedef SDL_GameControllerButton inputgamepadbutton_t;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
INPUT_BUTTON_TYPE_NONE,
|
||||
|
||||
#if INPUT_KEYBOARD == 1
|
||||
INPUT_BUTTON_TYPE_KEYBOARD,
|
||||
#endif
|
||||
#if INPUT_GAMEPAD == 1
|
||||
INPUT_BUTTON_TYPE_GAMEPAD,
|
||||
#endif
|
||||
|
||||
INPUT_BUTTON_TYPE_COUNT
|
||||
} inputbuttontype_t;
|
||||
|
||||
typedef struct {
|
||||
inputbuttontype_t type;
|
||||
|
||||
union {
|
||||
#if INPUT_GAMEPAD == 1
|
||||
inputgamepadbutton_t gpButton;
|
||||
#endif
|
||||
|
||||
#if INPUT_KEYBOARD == 1
|
||||
inputscancode_t scancode;
|
||||
#endif
|
||||
};
|
||||
} inputbutton_t;
|
||||
|
||||
typedef struct {
|
||||
const char_t *name;
|
||||
inputbutton_t button;
|
||||
} inputbuttondata_t;
|
||||
|
||||
extern const inputbuttondata_t INPUT_BUTTON_DATA[];
|
||||
|
||||
/**
|
||||
* Gets an input button by its name.
|
||||
*
|
||||
* @param name The name of the input button.
|
||||
* @return The input button, or .type = INPUT_BUTTON_TYPE_NONE if not found.
|
||||
*/
|
||||
inputbutton_t inputButtonGetByName(const char_t *name);
|
||||
|
||||
/**
|
||||
* Gets the current value of an input button.
|
||||
*
|
||||
* @param button The input button.
|
||||
* @return The current value of the input button (0.0f to 1.0f).
|
||||
*/
|
||||
float_t inputButtonGetValue(const inputbutton_t button);
|
@@ -15,3 +15,31 @@
|
||||
* @return The next power of two greater than or equal to the value.
|
||||
*/
|
||||
uint32_t mathNextPowTwo(uint32_t value);
|
||||
|
||||
/**
|
||||
* Returns the maximum of two values.
|
||||
*
|
||||
* @param a The first value.
|
||||
* @param b The second value.
|
||||
* @return The maximum of the two values.
|
||||
*/
|
||||
#define mathMax(a, b) ((a) > (b) ? (a) : (b))
|
||||
|
||||
/**
|
||||
* Returns the minimum of two values.
|
||||
*
|
||||
* @param a The first value.
|
||||
* @param b The second value.
|
||||
* @return The minimum of the two values.
|
||||
*/
|
||||
#define mathMin(a, b) ((a) < (b) ? (a) : (b))
|
||||
|
||||
/**
|
||||
* Clamps a value between a lower and upper bound.
|
||||
*
|
||||
* @param x The value to clamp.
|
||||
* @param lower The lower bound.
|
||||
* @param upper The upper bound.
|
||||
* @return The clamped value.
|
||||
*/
|
||||
#define mathClamp(x, lower, upper) (mathMin(upper, mathMax(lower, x)))
|
Reference in New Issue
Block a user