fencer/core/src/input_axis.c

191 lines
5.9 KiB
C

#include "input_axis.h"
#include "debug.h"
#include "input.h"
KeyBind* keybind_new(SDL_Scancode key) {
KeyBind* self = malloc(sizeof(KeyBind));
ASSERT_RETURN(self != NULL, NULL, "Failed to allocate space for KeyBind instance");
*self = (KeyBind) {
.device = NULL,
.scancode = key,
.state = 0
};
return self;
}
int keybind_is_changed_by(KeyBind* self, SDL_Event event) {
return self->device->type == InputDevice_KBM
&& (event.type == SDL_KEYUP || event.type == SDL_KEYDOWN)
&& event.key.keysym.scancode == self->scancode;
}
InputEvent keybind_evaluate(KeyBind* self, SDL_Event event) {
return (InputEvent) {
.type = InputEvent_Bool,
.as_bool = self->device->keyboard.state[self->scancode]
};
}
void keybind_set_device(KeyBind* self, InputDevice* device) {
self->device = device;
}
ControllerAxis* controlleraxis_new(int axis) {
ControllerAxis* self = malloc(sizeof(ControllerAxis));
ASSERT_RETURN(self != NULL, NULL, "Failed to allocate space for ControllerAxis instance");
*self = (ControllerAxis){
.axis = axis,
.device = NULL
};
return self;
}
int controlleraxis_is_changed_by(ControllerAxis* self, SDL_Event event) {
int r = self->device->type == InputDevice_Gamepad
&& event.type == SDL_CONTROLLERAXISMOTION
&& event.caxis.which == self->device->gamepad.id
&& event.caxis.axis == self->axis;
return r;
}
InputEvent controlleraxis_evaluate(ControllerAxis* self, SDL_Event event) {
float result = (float)event.caxis.value / 32767.0;
return (InputEvent) {
.type = InputEvent_Float,
.as_float = result
};
}
void controlleraxis_set_device(ControllerAxis* self, InputDevice* device) {
self->device = device;
}
ControllerButton* controllerbutton_new(int button) {
ControllerButton* self = malloc(sizeof(ControllerButton));
ASSERT_RETURN(self != NULL, NULL, "Failed to allocate space for ControllerButton instance");
*self = (ControllerButton) {
.button = button,
.device = NULL
};
return self;
}
int controllerbutton_is_changed_by(ControllerButton* self, SDL_Event event) {
return self->device->type == InputDevice_Gamepad
&& event.cbutton.which == self->device->gamepad.id
&& (event.type == SDL_CONTROLLERBUTTONUP || event.type == SDL_CONTROLLERBUTTONDOWN)
&& event.cbutton.button == self->button;
}
InputEvent controllerbutton_evaluate(ControllerButton* self, SDL_Event event) {
return (InputEvent) {
.type = InputEvent_Bool,
.as_bool = event.cbutton.state
};
}
void controllerbutton_set_device(ControllerButton* self, InputDevice* device) {
self->device = device;
}
CompositeAxis1D* compositeaxis1d_new(InputAxis left, InputAxis right, InputEventType type) {
CompositeAxis1D* self = malloc(sizeof(CompositeAxis1D));
ASSERT_RETURN(self != NULL, NULL, "Failed to allocate space for CompositeAxis1D instance");
*self = (CompositeAxis1D) {
.left = left,
.right = right,
.type = type,
};
return self;
}
int compositeaxis1d_is_changed_by(CompositeAxis1D* self, SDL_Event event) {
return self->left.tc->is_changed_by(self->left.data, event)
|| self->right.tc->is_changed_by(self->right.data, event);
}
static inline
InputEvent _internal_event_to_type(InputEventType type, InputEvent event) {
if(type == InputEvent_Vector && event.type == InputEvent_Vector)
return event;
float as_float = 0;
switch(event.type) {
case InputEvent_Vector:
LOG_ERROR("No (1)");
break;
case InputEvent_Bool:
as_float = event.as_bool;
break;
case InputEvent_Float:
as_float = event.as_float;
break;
case InputEvent_Int:
as_float = event.as_int;
break;
}
event.type = type;
switch(type) {
case InputEvent_Int:
event.as_int = round(as_float);
return event;
case InputEvent_Float:
event.as_float = as_float;
return event;
case InputEvent_Bool:
event.as_bool = as_float != 0;
return event;
case InputEvent_Vector:
LOG_ERROR("No (2)");
return event;
}
return event;
}
InputEvent compositeaxis1d_evaluate(CompositeAxis1D* self, SDL_Event event) {
InputEvent left_result = self->left.tc->evaluate(self->left.data, event);
InputEvent right_result = self->right.tc->evaluate(self->right.data, event);
ASSERT_RETURN(self->type != InputEvent_Vector
|| (left_result.type == InputEvent_Vector && right_result.type == InputEvent_Vector),
((InputEvent){.type = 0, .as_bool = 0}), "Composite axis can only output vector if both composite elements output vector.");
InputEvent final = {
.type = self->type
};
// if both outputs are booleans, they will be combined to an int
if(final.type == InputEvent_Bool)
final.type = InputEvent_Int;
left_result = _internal_event_to_type(final.type, left_result);
right_result = _internal_event_to_type(final.type, right_result);
switch(final.type) {
default:
LOG_ERROR("Invalid composite input result");
final.type = InputEvent_Bool;
final.as_bool = 0;
return final;
case InputEvent_Int:
final.as_int = right_result.as_int - left_result.as_int;
return final;
case InputEvent_Float:
final.as_float = right_result.as_float - left_result.as_float;
return final;
case InputEvent_Vector:
final.as_vector = vsubf(right_result.as_vector, left_result.as_vector);
return final;
}
}
void compositeaxis1d_set_device(CompositeAxis1D* self, InputDevice* device) {
self->left.tc->set_device(self->left.data, device);
self->right.tc->set_device(self->right.data, device);
}
void compositeaxis1d_drop(CompositeAxis1D* self) {
self->left.drop->drop(self->left.data);
self->right.drop->drop(self->right.data);
free(self);
}