#ifndef _fencer_input_axis_h #define _fencer_input_axis_h #include "typeclass_helpers.h" #include "vmath.h" #include "drop.h" #include <SDL2/SDL_events.h> #include <SDL2/SDL_keyboard.h> #include <SDL2/SDL_gamecontroller.h> struct InputDevice; typedef enum InputEventType { InputEvent_Vector = 0, InputEvent_Float = 1, InputEvent_Int = 2, InputEvent_Bool = 3, } InputEventType; typedef struct InputEvent { InputEventType type; union { Vector as_vector; float as_float; int as_int; int as_bool; }; } InputEvent; typedef struct { int (*const is_changed_by)(void*, SDL_Event); struct InputEvent (*const evaluate)(void*, SDL_Event); void (*const set_device)(void*, struct InputDevice*); } IInputAxis; typedef struct { void* data; IInputAxis const* tc; IDrop const* drop; } InputAxis; #define impl_InputAxis_for(T, is_changed_by_f, evaluate_f, set_device_f)\ static inline InputAxis T##_as_InputAxis(T* x) {\ TC_FN_TYPECHECK(int, is_changed_by_f, T*, SDL_Event);\ TC_FN_TYPECHECK(struct InputEvent, evaluate_f, T*, SDL_Event);\ TC_FN_TYPECHECK(void, set_device_f, T*, struct InputDevice*);\ static IInputAxis const tc = {\ .is_changed_by = (int(*const)(void*,SDL_Event)) is_changed_by_f,\ .evaluate = (struct InputEvent(*const)(void*,SDL_Event)) evaluate_f,\ .set_device = (void(*const)(void*,struct InputDevice*)) set_device_f\ };\ IDrop const* drop = T##_as_Drop(x).tc;\ return (InputAxis){.data=x, .tc=&tc, .drop = drop};\ } typedef struct KeyBind { int state; SDL_Scancode scancode; struct InputDevice* device; } KeyBind; extern KeyBind* keybind_new(SDL_Scancode bind); extern int keybind_is_changed_by(KeyBind* self, SDL_Event event); extern struct InputEvent keybind_evaluate(KeyBind* self, SDL_Event); extern void keybind_set_device(KeyBind* self, struct InputDevice* device); impl_default_Drop_for(KeyBind) impl_InputAxis_for(KeyBind, keybind_is_changed_by, keybind_evaluate, keybind_set_device ) typedef struct ControllerAxis { struct InputDevice* device; int axis; } ControllerAxis; extern ControllerAxis* controlleraxis_new(int axis); extern int controlleraxis_is_changed_by(ControllerAxis* self, SDL_Event event); extern struct InputEvent controlleraxis_evaluate(ControllerAxis* self, SDL_Event event); extern void controlleraxis_set_device(ControllerAxis* self, struct InputDevice* device); impl_default_Drop_for(ControllerAxis) impl_InputAxis_for(ControllerAxis, controlleraxis_is_changed_by, controlleraxis_evaluate, controlleraxis_set_device ) typedef struct ControllerButton { struct InputDevice* device; int button; } ControllerButton; extern ControllerButton* controllerbutton_new(int button); extern int controllerbutton_is_changed_by(ControllerButton* self, SDL_Event event); extern struct InputEvent controllerbutton_evaluate(ControllerButton* self, SDL_Event event); extern void controllerbutton_set_device(ControllerButton* self, struct InputDevice* device); impl_default_Drop_for(ControllerButton) impl_InputAxis_for(ControllerButton, controllerbutton_is_changed_by, controllerbutton_evaluate, controllerbutton_set_device ) typedef struct CompositeAxis1D { InputAxis left; InputAxis right; InputEventType type; } CompositeAxis1D; extern CompositeAxis1D* compositeaxis1d_new(InputAxis left, InputAxis right, InputEventType type); extern int compositeaxis1d_is_changed_by(CompositeAxis1D* self, SDL_Event event); extern struct InputEvent compositeaxis1d_evaluate(CompositeAxis1D* self, SDL_Event event); extern void compositeaxis1d_set_device(CompositeAxis1D* self, struct InputDevice* device); extern void compositeaxis1d_drop(CompositeAxis1D* self); impl_Drop_for(CompositeAxis1D, compositeaxis1d_drop ) impl_InputAxis_for(CompositeAxis1D, compositeaxis1d_is_changed_by, compositeaxis1d_evaluate, compositeaxis1d_set_device ) #endif // !_fencer_input_axis_h