Allowed binds to execute commands.

This commit is contained in:
2025-09-11 12:58:04 -05:00
parent fe9af039fc
commit 8b20f0bf31
13 changed files with 244 additions and 251 deletions

View File

@@ -1,7 +1,8 @@
bind ` console;
echo " = Dawn Init = ";
bind ` toggleconsole;
bind w up;
bind a left;
bind s down;
bind a left;
bind d right;
bind up up;
bind down down;
@@ -9,6 +10,5 @@ bind left left;
bind right right;
bind e accept;
bind enter accept;
bind space accept;
bind esc cancel;
bind q cancel;
bind esc quit;

View File

@@ -26,13 +26,5 @@ void cmdBind(const consolecmdexec_t *exec) {
return;
}
inputbind_t bind = inputBindGetByName(exec->argv[1]);
if(bind == INPUT_BIND_COUNT) {
consolePrint("Unknown bind \"%s\"", exec->argv[1]);
return;
}
// By default I unbind all.
inputUnbindButton(button);
inputBind(bind, button);
inputBind(button, exec->argv[1]);
}

View File

@@ -0,0 +1,13 @@
/**
* Copyright (c) 2025 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "console/console.h"
void cmdToggleConsole(const consolecmdexec_t *exec) {
CONSOLE.visible = !CONSOLE.visible;
}

View File

@@ -9,13 +9,15 @@
#include "assert/assert.h"
#include "util/memory.h"
#include "util/string.h"
#include "input/input.h"
#include "console/cmd/cmdquit.h"
#include "console/cmd/cmdecho.h"
#include "console/cmd/cmdset.h"
#include "console/cmd/cmdget.h"
#include "console/cmd/cmdexec.h"
#include "console/cmd/cmdbind.h"
#include "input/input.h"
#include "console/cmd/cmdtoggleconsole.h"
console_t CONSOLE;
@@ -29,8 +31,7 @@ void consoleInit() {
consoleRegCmd("echo", cmdEcho);
consoleRegCmd("exec", cmdExec);
consoleRegCmd("bind", cmdBind);
consolePrint(" = Dawn Console = ");
consoleRegCmd("toggleconsole", cmdToggleConsole);
#if CONSOLE_POSIX
threadInit(&CONSOLE.thread, consoleInputThread);
@@ -316,9 +317,9 @@ void consoleUpdate() {
#endif
// Toggle console
if(inputPressed(INPUT_BIND_CONSOLE)) {
CONSOLE.visible = !CONSOLE.visible;
}
// if(inputPressed(INPUT_ACTION_CONSOLE)) {
// CONSOLE.visible = !CONSOLE.visible;
// }
// Anything to exec?
if(CONSOLE.execBufferCount == 0) {
@@ -357,8 +358,6 @@ void consoleDispose(void) {
threadStop(&CONSOLE.thread);
threadMutexDispose(&CONSOLE.execMutex);
#endif
consolePrint(" = Console shutting down = ");
}
#if CONSOLE_POSIX

View File

@@ -8,7 +8,7 @@ target_sources(${DUSK_TARGET_NAME}
PRIVATE
input.c
inputbutton.c
inputbind.c
inputaction.c
)
if(DUSK_TARGET_SYSTEM STREQUAL "linux")

View File

@@ -16,11 +16,17 @@ input_t INPUT;
void inputInit(void) {
memoryZero(&INPUT, sizeof(input_t));
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;
for(uint8_t i = 0; i < INPUT_ACTION_COUNT; i++) {
INPUT.actions[i].action = (inputaction_t)i;
INPUT.actions[i].lastValue = 0.0f;
INPUT.actions[i].currentValue = 0.0f;
}
stringCopy(&INPUT_BUTTON_DATA[0].command[0], "echo \"test\";", CONSOLE_LINE_MAX);
INPUT_BUTTON_DATA[0].actionType = INPUT_BUTTON_ACTION_TYPE_COMMAND;
INPUT_BUTTON_DATA[1].actionType = INPUT_BUTTON_ACTION_TYPE_ACTION;
INPUT_BUTTON_DATA[1].action = INPUT_ACTION_UP;
}
void inputUpdate(void) {
@@ -28,111 +34,108 @@ void inputUpdate(void) {
INPUT.keyboardState = SDL_GetKeyboardState(NULL);
#endif
// For each input bind...
inputbinddata_t *data = INPUT.binds;
// Reset all actions
inputactiondata_t *action = &INPUT.actions[0];
do {
data->lastValue = data->currentValue;
data->currentValue = 0.0f;
action->lastValue = action->currentValue;
action->currentValue = 0.0f;
action++;
} while(action < &INPUT.actions[INPUT_ACTION_COUNT]);
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
// For each button...
inputbuttondata_t *cur = &INPUT_BUTTON_DATA[0];
do {
cur->lastVal = cur->curVal;
cur->curVal = inputButtonGetValue(cur->button);
if(cur->curVal == 0.0f) {
cur++;
continue;
}
switch(cur->actionType) {
case INPUT_BUTTON_ACTION_TYPE_NULL: {
break;
}
case INPUT_BUTTON_ACTION_TYPE_COMMAND: {
if(cur->lastVal == 0.0f && cur->command[0] != '\0') {
consoleExec(cur->command);
}
break;
}
case INPUT_BUTTON_ACTION_TYPE_ACTION: {
INPUT.actions[cur->action].currentValue = mathMax(
cur->curVal, INPUT.actions[cur->action].currentValue
);
break;
}
default: {
assertUnreachable("Unknown input button action type");
break;
}
}
cur++;
} while(cur->name);
}
float_t inputGetCurrentValue(const inputaction_t action) {
assertTrue(action < INPUT_ACTION_COUNT, "Input action out of bounds");
return INPUT.actions[action].currentValue;
}
float_t inputGetLast(const inputaction_t action) {
assertTrue(action < INPUT_ACTION_COUNT, "Input action out of bounds");
return INPUT.actions[action].lastValue;
}
bool_t inputIsDown(const inputaction_t action) {
return inputGetCurrentValue(action) > 0.0f;
}
bool_t inputWasDown(const inputaction_t action) {
return inputGetLast(action) > 0.0f;
}
bool_t inputPressed(const inputaction_t action) {
return inputIsDown(action) && !inputWasDown(action);
}
bool_t inputReleased(const inputaction_t action) {
return !inputIsDown(action) && inputWasDown(action);
}
void inputBind(const inputbutton_t button, const char_t *action) {
assertNotNull(action, "Input action is null");
assertStrLenMin(action, 1, "Input action is empty");
assertStrLenMax(action, CONSOLE_LINE_MAX - 1, "Input action is too long");
// Get the button data for this button.
inputbuttondata_t *data = INPUT_BUTTON_DATA;
do {
if(memoryCompare(&data->button, &button, sizeof(inputbutton_t)) == 0) {
break;
}
data++;
} while(data < INPUT.binds + INPUT_BIND_COUNT);
}
} while(data->name != NULL);
assertNotNull(data->name, "Input button not found");
float_t inputGetCurrentValue(const inputbind_t bind) {
assertTrue(bind < INPUT_BIND_COUNT, "Input bind out of bounds");
return INPUT.binds[bind].currentValue;
}
float_t inputGetLast(const inputbind_t bind) {
assertTrue(bind < INPUT_BIND_COUNT, "Input bind out of bounds");
return INPUT.binds[bind].lastValue;
}
bool_t inputIsDown(const inputbind_t bind) {
return inputGetCurrentValue(bind) > 0.0f;
}
bool_t inputWasDown(const inputbind_t bind) {
return inputGetLast(bind) > 0.0f;
}
bool_t inputPressed(const inputbind_t bind) {
return inputIsDown(bind) && !inputWasDown(bind);
}
bool_t inputReleased(const inputbind_t bind) {
return !inputIsDown(bind) && inputWasDown(bind);
}
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;
}
}
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) {
// Try find input action first.
for(inputaction_t act = 0; act < INPUT_ACTION_COUNT; act++) {
if(stringCompareInsensitive(INPUT_ACTION_NAMES[act], action) != 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;
// Action found.
data->actionType = INPUT_BUTTON_ACTION_TYPE_ACTION;
data->action = act;
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
);
// No action found, treat as command.
data->actionType = INPUT_BUTTON_ACTION_TYPE_COMMAND;
stringCopy(data->command, action, CONSOLE_LINE_MAX);
}

View File

@@ -7,10 +7,10 @@
#pragma once
#include "inputbutton.h"
#include "inputbind.h"
#include "inputaction.h"
typedef struct {
inputbinddata_t binds[INPUT_BIND_COUNT];
inputactiondata_t actions[INPUT_ACTION_COUNT];
#if INPUT_SDL2 == 1
#if INPUT_KEYBOARD == 1
@@ -32,85 +32,59 @@ void inputInit(void);
void inputUpdate(void);
/**
* Gets the current value of a specific input bind.
* Gets the current value of a specific input action.
*
* @param bind The input bind to get the value for.
* @return The current value of the bind (0.0f to 1.0f).
* @param action The input action to get the value for.
* @return The current value of the action (0.0f to 1.0f).
*/
float_t inputGetCurrentValue(const inputbind_t bind);
float_t inputGetCurrentValue(const inputaction_t action);
/**
* Gets the last value of a specific input bind.
* Gets the last value of a specific input action.
*
* @param bind The input bind to get the value for.
* @return The last value of the bind (0.0f to 1.0f).
* @param action The input action to get the value for.
* @return The last value of the action (0.0f to 1.0f).
*/
float_t inputGetLast(const inputbind_t bind);
float_t inputGetLast(const inputaction_t action);
/**
* Checks if a specific input bind is currently pressed.
* Checks if a specific input action is currently pressed.
*
* @param bind The input bind to check.
* @return true if the bind is currently pressed, false otherwise.
* @param action The input action to check.
* @return true if the action is currently pressed, false otherwise.
*/
bool_t inputIsDown(const inputbind_t bind);
bool_t inputIsDown(const inputaction_t action);
/**
* Checks if a specific input bind was pressed in the last update.
* Checks if a specific input action was pressed in the last update.
*
* @param bind The input bind to check.
* @return true if the bind was pressed in the last update, false otherwise.
* @param action The input action to check.
* @return true if the action was pressed in the last update, false otherwise.
*/
bool_t inputWasDown(const inputbind_t bind);
bool_t inputWasDown(const inputaction_t action);
/**
* Checks if a specific input bind was down this frame but not in the the
* Checks if a specific input action was down this frame but not in the the
* previous frame.
*
* @param bind The input bind to check.
* @return true if the bind is currently pressed, false otherwise.
* @param action The input action to check.
* @return true if the action is currently pressed, false otherwise.
*/
bool_t inputPressed(const inputbind_t bind);
bool_t inputPressed(const inputaction_t action);
/**
* Checks if a specific input bind was released this frame.
* Checks if a specific input action was released this frame.
*
* @param bind The input bind to check.
* @return true if the bind was released this frame, false otherwise.
* @param action The input action to check.
* @return true if the action was released this frame, false otherwise.
*/
bool_t inputReleased(const inputbind_t bind);
bool_t inputReleased(const inputaction_t action);
/**
* Binds an input button to a specific input bind.
* Binds an input button to an action. Will first check if a matching action
* exists, otherwise it will be treated as a command.
*
* @param bind The input bind to bind the button to.
* @param button The input button to bind.
* @param action The name of the input action or command to bind the button to.
*/
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);
void inputBind(const inputbutton_t data, const char_t *action);

30
src/input/inputaction.c Normal file
View File

@@ -0,0 +1,30 @@
/**
* Copyright (c) 2025 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "inputaction.h"
#include "assert/assert.h"
#include "util/string.h"
const char_t* INPUT_ACTION_NAMES[INPUT_ACTION_COUNT] = {
[INPUT_ACTION_UP] = "UP",
[INPUT_ACTION_DOWN] = "DOWN",
[INPUT_ACTION_LEFT] = "LEFT",
[INPUT_ACTION_RIGHT] = "RIGHT",
[INPUT_ACTION_ACCEPT] = "ACCEPT",
[INPUT_ACTION_CANCEL] = "CANCEL",
};
inputaction_t inputActionGetByName(const char_t *name) {
assertNotNull(name, "name must not be NULL");
for(inputaction_t i = 0; i < INPUT_ACTION_COUNT; i++) {
if(stringCompareInsensitive(INPUT_ACTION_NAMES[i], name) != 0) continue;
return i;
}
return INPUT_ACTION_COUNT;
}

36
src/input/inputaction.h Normal file
View File

@@ -0,0 +1,36 @@
/**
* Copyright (c) 2025 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "dusk.h"
typedef enum {
INPUT_ACTION_UP,
INPUT_ACTION_DOWN,
INPUT_ACTION_LEFT,
INPUT_ACTION_RIGHT,
INPUT_ACTION_ACCEPT,
INPUT_ACTION_CANCEL,
INPUT_ACTION_COUNT
} inputaction_t;
typedef struct {
inputaction_t action;
float_t lastValue;
float_t currentValue;
} inputactiondata_t;
extern const char_t* INPUT_ACTION_NAMES[INPUT_ACTION_COUNT];
/**
* Gets an input action by its name.
*
* @param name The name of the input action.
* @return The input action, or INPUT_ACTION_COUNT if not found.
*/
inputaction_t inputActionGetByName(const char_t *name);

View File

@@ -1,30 +0,0 @@
/**
* 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;
}

View File

@@ -1,41 +0,0 @@
/**
* 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);

View File

@@ -10,7 +10,7 @@
#include "assert/assert.h"
#include "util/string.h"
const inputbuttondata_t INPUT_BUTTON_DATA[] = {
inputbuttondata_t INPUT_BUTTON_DATA[] = {
#if INPUT_SDL2 == 1
#if INPUT_GAMEPAD == 1
#if PSP
@@ -138,6 +138,8 @@ const inputbuttondata_t INPUT_BUTTON_DATA[] = {
{ .name = "kp_equals", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_KP_EQUALS } },
#endif
#endif
{ .name = NULL }
};
inputbutton_t inputButtonGetByName(const char_t *name) {

View File

@@ -6,7 +6,8 @@
*/
#pragma once
#include "dusk.h"
#include "console/console.h"
#include "inputaction.h"
#if INPUT_SDL2 == 1
#include <SDL2/SDL.h>
@@ -55,12 +56,26 @@ typedef struct {
};
} inputbutton_t;
typedef enum {
INPUT_BUTTON_ACTION_TYPE_NULL,
INPUT_BUTTON_ACTION_TYPE_COMMAND,
INPUT_BUTTON_ACTION_TYPE_ACTION,
} inputbuttonactiontype_t;
typedef struct {
const char_t *name;
inputbutton_t button;
float_t curVal;
float_t lastVal;
inputbuttonactiontype_t actionType;
union {
char_t command[CONSOLE_LINE_MAX];
inputaction_t action;
};
} inputbuttondata_t;
extern const inputbuttondata_t INPUT_BUTTON_DATA[];
extern inputbuttondata_t INPUT_BUTTON_DATA[];
/**
* Gets an input button by its name.