#ifndef _fencer_input_axis_h #define _fencer_input_axis_h #include "typeclass_helpers.h" #include "vmath.h" #include "drop.h" #include #include #include 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; typedef void (*InputDelegateFn)(void* self, InputEvent event); #define impl_InputAxis_for(T, is_changed_by_f, evaluate_f, set_device_f)\ 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); decl_typeclass_impl(InputAxis, KeyBind) decl_typeclass_impl(Drop, KeyBind) 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); decl_typeclass_impl(InputAxis, ControllerAxis) decl_typeclass_impl(Drop, ControllerAxis) 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); decl_typeclass_impl(InputAxis, ControllerButton) decl_typeclass_impl(Drop, ControllerButton) 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); extern CompositeAxis1D* compositeaxis1d_from_keys(SDL_Scancode negative, SDL_Scancode positive); extern CompositeAxis1D* compositeaxis1d_from_buttons(int negative, int positive); decl_typeclass_impl(InputAxis, CompositeAxis1D) decl_typeclass_impl(Drop, CompositeAxis1D) #endif // !_fencer_input_axis_h