247 lines
6.4 KiB
C
247 lines
6.4 KiB
C
/**
|
|
* Copyright (c) 2026 Dominic Masters
|
|
*
|
|
* This software is released under the MIT License.
|
|
* https://opensource.org/licenses/MIT
|
|
*/
|
|
|
|
#include "input.h"
|
|
#include "assert/assert.h"
|
|
#include "util/memory.h"
|
|
#include "util/string.h"
|
|
#include "util/math.h"
|
|
#include "time/time.h"
|
|
|
|
input_t INPUT;
|
|
|
|
errorret_t inputInit(void) {
|
|
memoryZero(&INPUT, sizeof(input_t));
|
|
INPUT.deadzone = INPUT_DEADZONE_DEFAULT;
|
|
|
|
for(uint8_t i = 0; i < INPUT_BIND_COUNT; i++) {
|
|
INPUT.actions[i].action = (inputbind_t)i;
|
|
INPUT.actions[i].lastValue = 0.0f;
|
|
INPUT.actions[i].currentValue = 0.0f;
|
|
}
|
|
|
|
#ifdef inputInitPlatform
|
|
errorChain(inputInitPlatform());
|
|
#endif
|
|
|
|
errorOk();
|
|
}
|
|
|
|
void inputUpdate(void) {
|
|
#ifdef inputUpdatePlatform
|
|
inputUpdatePlatform();
|
|
#endif
|
|
|
|
// Reset all actions
|
|
inputactiondata_t *action = &INPUT.actions[0];
|
|
do {
|
|
#ifdef DUSK_TIME_DYNAMIC
|
|
action->lastDynamicValue = action->currentDynamicValue;
|
|
action->currentDynamicValue = 0.0f;
|
|
if(!TIME.dynamicUpdate) {
|
|
action->lastValue = action->currentValue;
|
|
action->currentValue = 0.0f;
|
|
}
|
|
#else
|
|
action->lastValue = action->currentValue;
|
|
action->currentValue = 0.0f;
|
|
#endif
|
|
|
|
action++;
|
|
} while(action < &INPUT.actions[INPUT_BIND_COUNT]);
|
|
|
|
// For each button...
|
|
inputbuttondata_t *cur = &INPUT_BUTTON_DATA[0];
|
|
while(cur->name) {
|
|
cur->lastVal = cur->curVal;
|
|
cur->curVal = inputButtonGetValue(cur->button);
|
|
|
|
if(cur->curVal == 0.0f) {
|
|
cur++;
|
|
continue;
|
|
}
|
|
|
|
// Update current val.
|
|
#ifdef DUSK_TIME_DYNAMIC
|
|
INPUT.actions[cur->action].currentDynamicValue = mathMax(
|
|
cur->curVal, INPUT.actions[cur->action].currentDynamicValue
|
|
);
|
|
if(!TIME.dynamicUpdate) {
|
|
INPUT.actions[cur->action].currentValue = mathMax(
|
|
cur->curVal, INPUT.actions[cur->action].currentValue
|
|
);
|
|
}
|
|
#else
|
|
INPUT.actions[cur->action].currentValue = mathMax(
|
|
cur->curVal, INPUT.actions[cur->action].currentValue
|
|
);
|
|
#endif
|
|
|
|
cur++;
|
|
}
|
|
}
|
|
|
|
float_t inputGetCurrentValue(const inputbind_t action) {
|
|
#ifdef DUSK_TIME_DYNAMIC
|
|
if(TIME.dynamicUpdate) return inputGetCurrentValueDynamic(action);
|
|
#endif
|
|
|
|
assertTrue(action < INPUT_BIND_COUNT, "Input action out of bounds");
|
|
return INPUT.actions[action].currentValue;
|
|
}
|
|
|
|
float_t inputGetLastValue(const inputbind_t action) {
|
|
#ifdef DUSK_TIME_DYNAMIC
|
|
if(TIME.dynamicUpdate) return inputGetLastValueDynamic(action);
|
|
#endif
|
|
|
|
assertTrue(action < INPUT_BIND_COUNT, "Input action out of bounds");
|
|
return INPUT.actions[action].lastValue;
|
|
}
|
|
|
|
#ifdef DUSK_TIME_DYNAMIC
|
|
float_t inputGetCurrentValueDynamic(const inputbind_t action) {
|
|
assertTrue(action < INPUT_BIND_COUNT, "Input action out of bounds");
|
|
return INPUT.actions[action].currentDynamicValue;
|
|
}
|
|
|
|
float_t inputGetLastValueDynamic(const inputbind_t action) {
|
|
assertTrue(action < INPUT_BIND_COUNT, "Input action out of bounds");
|
|
return INPUT.actions[action].lastDynamicValue;
|
|
}
|
|
|
|
bool_t inputIsDownDynamic(const inputbind_t action) {
|
|
return inputGetCurrentValueDynamic(action) > 0.0f;
|
|
}
|
|
|
|
bool_t inputWasDownDynamic(const inputbind_t action) {
|
|
return inputGetLastValueDynamic(action) > 0.0f;
|
|
}
|
|
|
|
bool_t inputPressedDynamic(const inputbind_t action) {
|
|
return inputIsDownDynamic(action) && !inputWasDownDynamic(action);
|
|
}
|
|
|
|
bool_t inputReleasedDynamic(const inputbind_t action) {
|
|
return !inputIsDownDynamic(action) && inputWasDownDynamic(action);
|
|
}
|
|
|
|
float_t inputAxisDynamic(
|
|
const inputbind_t neg,
|
|
const inputbind_t pos
|
|
) {
|
|
return inputGetCurrentValueDynamic(pos) -
|
|
inputGetCurrentValueDynamic(neg);
|
|
}
|
|
|
|
void inputAxis2DDynamic(
|
|
const inputbind_t negX, const inputbind_t posX,
|
|
const inputbind_t negY, const inputbind_t posY,
|
|
vec2 result
|
|
) {
|
|
assertNotNull(result, "Result vector cannot be null");
|
|
result[0] = inputAxisDynamic(negX, posX);
|
|
result[1] = inputAxisDynamic(negY, posY);
|
|
}
|
|
|
|
void inputAngle2DDynamic(
|
|
const inputbind_t negX, const inputbind_t posX,
|
|
const inputbind_t negY, const inputbind_t posY,
|
|
vec2 result
|
|
) {
|
|
assertNotNull(result, "Result vector cannot be null");
|
|
float_t x = inputAxisDynamic(negX, posX);
|
|
float_t y = inputAxisDynamic(negY, posY);
|
|
float_t mag = sqrtf(x * x + y * y);
|
|
if(mag <= 0.0f) {
|
|
result[0] = 0.0f;
|
|
result[1] = 0.0f;
|
|
return;
|
|
}
|
|
if(mag > 1.0f) {
|
|
x /= mag;
|
|
y /= mag;
|
|
}
|
|
result[0] = x;
|
|
result[1] = y;
|
|
}
|
|
#endif
|
|
|
|
bool_t inputIsDown(const inputbind_t action) {
|
|
return inputGetCurrentValue(action) > 0.0f;
|
|
}
|
|
|
|
bool_t inputWasDown(const inputbind_t action) {
|
|
return inputGetLastValue(action) > 0.0f;
|
|
}
|
|
|
|
bool_t inputPressed(const inputbind_t action) {
|
|
return inputIsDown(action) && !inputWasDown(action);
|
|
}
|
|
|
|
bool_t inputReleased(const inputbind_t action) {
|
|
return !inputIsDown(action) && inputWasDown(action);
|
|
}
|
|
|
|
float_t inputAxis(const inputbind_t neg, const inputbind_t pos) {
|
|
assertTrue(neg < INPUT_BIND_COUNT, "Negative input action out of bounds");
|
|
assertTrue(pos < INPUT_BIND_COUNT, "Positive input action out of bounds");
|
|
|
|
return inputGetCurrentValue(pos) - inputGetCurrentValue(neg);
|
|
}
|
|
|
|
void inputAxis2D(
|
|
const inputbind_t negX, const inputbind_t posX,
|
|
const inputbind_t negY, const inputbind_t posY,
|
|
vec2 result
|
|
) {
|
|
assertNotNull(result, "Result vector cannot be null");
|
|
result[0] = inputAxis(negX, posX);
|
|
result[1] = inputAxis(negY, posY);
|
|
}
|
|
|
|
void inputAngle2D(
|
|
const inputbind_t negX, const inputbind_t posX,
|
|
const inputbind_t negY, const inputbind_t posY,
|
|
vec2 result
|
|
) {
|
|
assertNotNull(result, "Result vector cannot be null");
|
|
float_t x = inputAxis(negX, posX);
|
|
float_t y = inputAxis(negY, posY);
|
|
float_t mag = sqrtf(x * x + y * y);
|
|
if(mag <= 0.0f) {
|
|
result[0] = 0.0f;
|
|
result[1] = 0.0f;
|
|
return;
|
|
}
|
|
if(mag > 1.0f) {
|
|
x /= mag;
|
|
y /= mag;
|
|
}
|
|
result[0] = x;
|
|
result[1] = y;
|
|
}
|
|
|
|
void inputBind(const inputbutton_t button, const inputbind_t act) {
|
|
assertTrue(
|
|
act < INPUT_BIND_COUNT,
|
|
"Invalid input action"
|
|
);
|
|
assertTrue(act != INPUT_BIND_NULL, "Cannot bind to NULL action");
|
|
|
|
// Get the button data for this button.
|
|
inputbuttondata_t *data = inputButtonGetData(button);
|
|
assertNotNull(data, "Input button not found");
|
|
|
|
// Bind the action.
|
|
data->action = act;
|
|
}
|
|
|
|
float_t inputDeadzone(const float_t rawValue, const float_t deadzone) {
|
|
if(rawValue < deadzone) return 0.0f;
|
|
return (rawValue - deadzone) / (1.0f - deadzone);
|
|
} |