diff --git a/assets/init.dcf b/assets/init.dcf index 5f6698b..cae331c 100644 --- a/assets/init.dcf +++ b/assets/init.dcf @@ -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; \ No newline at end of file diff --git a/src/console/cmd/cmdbind.h b/src/console/cmd/cmdbind.h index 1a97ad1..5eafd5c 100644 --- a/src/console/cmd/cmdbind.h +++ b/src/console/cmd/cmdbind.h @@ -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]); } \ No newline at end of file diff --git a/src/console/cmd/cmdtoggleconsole.h b/src/console/cmd/cmdtoggleconsole.h new file mode 100644 index 0000000..af366cd --- /dev/null +++ b/src/console/cmd/cmdtoggleconsole.h @@ -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; +} \ No newline at end of file diff --git a/src/console/console.c b/src/console/console.c index 3086cc0..e36e9cd 100644 --- a/src/console/console.c +++ b/src/console/console.c @@ -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 diff --git a/src/input/CMakeLists.txt b/src/input/CMakeLists.txt index 83e5566..6054d57 100644 --- a/src/input/CMakeLists.txt +++ b/src/input/CMakeLists.txt @@ -8,7 +8,7 @@ target_sources(${DUSK_TARGET_NAME} PRIVATE input.c inputbutton.c - inputbind.c + inputaction.c ) if(DUSK_TARGET_SYSTEM STREQUAL "linux") diff --git a/src/input/input.c b/src/input/input.c index cd547ee..f24ce56 100644 --- a/src/input/input.c +++ b/src/input/input.c @@ -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; - - 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 - ); - } - data++; - } while(data < INPUT.binds + INPUT_BIND_COUNT); -} + action->lastValue = action->currentValue; + action->currentValue = 0.0f; + action++; + } while(action < &INPUT.actions[INPUT_ACTION_COUNT]); -float_t inputGetCurrentValue(const inputbind_t bind) { - assertTrue(bind < INPUT_BIND_COUNT, "Input bind out of bounds"); - return INPUT.binds[bind].currentValue; -} + // For each button... + inputbuttondata_t *cur = &INPUT_BUTTON_DATA[0]; + do { + cur->lastVal = cur->curVal; + cur->curVal = inputButtonGetValue(cur->button); -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) { + if(cur->curVal == 0.0f) { + cur++; 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; + 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; } - inputUnbind((inputbind_t)i, button); + 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); } -void inputUnbindBind(const inputbind_t bind) { - assertTrue(bind < INPUT_BIND_COUNT, "Input bind out of bounds"); +float_t inputGetCurrentValue(const inputaction_t action) { + assertTrue(action < INPUT_ACTION_COUNT, "Input action out of bounds"); + return INPUT.actions[action].currentValue; +} - memoryZero( - &INPUT.binds[bind].buttons, - sizeof(inputbutton_t) * INPUT_BIND_BUTTONS_MAX - ); +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->name != NULL); + assertNotNull(data->name, "Input button not found"); + + // Try find input action first. + for(inputaction_t act = 0; act < INPUT_ACTION_COUNT; act++) { + if(stringCompareInsensitive(INPUT_ACTION_NAMES[act], action) != 0) { + continue; + } + + // Action found. + data->actionType = INPUT_BUTTON_ACTION_TYPE_ACTION; + data->action = act; + return; + } + + // No action found, treat as command. + data->actionType = INPUT_BUTTON_ACTION_TYPE_COMMAND; + stringCopy(data->command, action, CONSOLE_LINE_MAX); } \ No newline at end of file diff --git a/src/input/input.h b/src/input/input.h index 705f9ad..0920cf5 100644 --- a/src/input/input.h +++ b/src/input/input.h @@ -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); \ No newline at end of file +void inputBind(const inputbutton_t data, const char_t *action); \ No newline at end of file diff --git a/src/input/inputaction.c b/src/input/inputaction.c new file mode 100644 index 0000000..b795d14 --- /dev/null +++ b/src/input/inputaction.c @@ -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; +} \ No newline at end of file diff --git a/src/input/inputaction.h b/src/input/inputaction.h new file mode 100644 index 0000000..91f5552 --- /dev/null +++ b/src/input/inputaction.h @@ -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); \ No newline at end of file diff --git a/src/input/inputbind.c b/src/input/inputbind.c deleted file mode 100644 index 2d8b870..0000000 --- a/src/input/inputbind.c +++ /dev/null @@ -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; -} \ No newline at end of file diff --git a/src/input/inputbind.h b/src/input/inputbind.h deleted file mode 100644 index 515ab80..0000000 --- a/src/input/inputbind.h +++ /dev/null @@ -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); \ No newline at end of file diff --git a/src/input/inputbutton.c b/src/input/inputbutton.c index 9a860f8..a9e7523 100644 --- a/src/input/inputbutton.c +++ b/src/input/inputbutton.c @@ -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) { diff --git a/src/input/inputbutton.h b/src/input/inputbutton.h index 6402096..06eafa3 100644 --- a/src/input/inputbutton.h +++ b/src/input/inputbutton.h @@ -6,7 +6,8 @@ */ #pragma once -#include "dusk.h" +#include "console/console.h" +#include "inputaction.h" #if INPUT_SDL2 == 1 #include @@ -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.