#include "local.h"
static uint32_t _input_backend_pair_count = 0;
static const struct InputBackendPair * _input_backend_pairs = NULL;
static uint32_t _input_binding_count = 0;
static alias_R * _input_bindings = NULL;
void Engine_set_player_input_backend(uint32_t player_index, const struct InputBackendPair * pairs, uint32_t pair_count) {
(void)player_index;
_input_backend_pair_count = pair_count;
_input_backend_pairs = pairs;
uint32_t max_binding_index = 0;
for(uint32_t i = 0; i < pair_count; i++) {
if(pairs[i].binding > max_binding_index) {
max_binding_index = pairs[i].binding;
}
}
if(max_binding_index + 1 > _input_binding_count) {
_input_bindings = alias_realloc(
alias_default_MemoryCB()
, _input_bindings
, sizeof(*_input_bindings) * _input_binding_count
, sizeof(*_input_bindings) * (max_binding_index + 1)
, alignof(*_input_bindings)
);
_input_binding_count = max_binding_index + 1;
}
}
static struct {
uint32_t count;
struct InputSignal * signals;
} _input_frontends[MAX_INPUT_FRONTEND_SETS] = { 0 };
uint32_t Engine_add_input_frontend(uint32_t player_index, struct InputSignal * signals, uint32_t signal_count) {
(void)player_index;
uint32_t index = 0;
for(; index < MAX_INPUT_FRONTEND_SETS; index++) {
if(_input_frontends[index].count == 0) {
break;
}
}
if(index < MAX_INPUT_FRONTEND_SETS) {
_input_frontends[index].count = signal_count;
_input_frontends[index].signals = signals;
return index;
}
return -1;
}
void Engine_remove_input_frontend(uint32_t player_index, uint32_t index) {
(void)player_index;
if(index < MAX_INPUT_FRONTEND_SETS) {
_input_frontends[index].count = 0;
_input_frontends[index].signals = NULL;
}
}
static int _get_key_down(enum InputSource source) {
static int source_to_key[] = {
[Keyboard_Apostrophe] = GLFW_KEY_APOSTROPHE,
[Keyboard_Comma] = GLFW_KEY_COMMA,
[Keyboard_Minus] = GLFW_KEY_MINUS,
[Keyboard_Period] = GLFW_KEY_PERIOD,
[Keyboard_Slash] = GLFW_KEY_SLASH,
[Keyboard_0] = GLFW_KEY_0,
[Keyboard_1] = GLFW_KEY_1,
[Keyboard_2] = GLFW_KEY_2,
[Keyboard_3] = GLFW_KEY_3,
[Keyboard_4] = GLFW_KEY_4,
[Keyboard_5] = GLFW_KEY_5,
[Keyboard_6] = GLFW_KEY_6,
[Keyboard_7] = GLFW_KEY_7,
[Keyboard_8] = GLFW_KEY_8,
[Keyboard_9] = GLFW_KEY_9,
[Keyboard_Semicolon] = GLFW_KEY_SEMICOLON,
[Keyboard_Equal] = GLFW_KEY_EQUAL,
[Keyboard_A] = GLFW_KEY_A,
[Keyboard_B] = GLFW_KEY_B,
[Keyboard_C] = GLFW_KEY_C,
[Keyboard_D] = GLFW_KEY_D,
[Keyboard_E] = GLFW_KEY_E,
[Keyboard_F] = GLFW_KEY_F,
[Keyboard_G] = GLFW_KEY_G,
[Keyboard_H] = GLFW_KEY_H,
[Keyboard_I] = GLFW_KEY_I,
[Keyboard_J] = GLFW_KEY_J,
[Keyboard_K] = GLFW_KEY_K,
[Keyboard_L] = GLFW_KEY_L,
[Keyboard_M] = GLFW_KEY_M,
[Keyboard_N] = GLFW_KEY_N,
[Keyboard_O] = GLFW_KEY_O,
[Keyboard_P] = GLFW_KEY_P,
[Keyboard_Q] = GLFW_KEY_Q,
[Keyboard_R] = GLFW_KEY_R,
[Keyboard_S] = GLFW_KEY_S,
[Keyboard_T] = GLFW_KEY_T,
[Keyboard_U] = GLFW_KEY_U,
[Keyboard_V] = GLFW_KEY_V,
[Keyboard_W] = GLFW_KEY_W,
[Keyboard_X] = GLFW_KEY_X,
[Keyboard_Y] = GLFW_KEY_Y,
[Keyboard_Z] = GLFW_KEY_Z,
[Keyboard_Space] = GLFW_KEY_SPACE,
[Keyboard_Escape] = GLFW_KEY_ESCAPE,
[Keyboard_Enter] = GLFW_KEY_ENTER,
[Keyboard_Tab] = GLFW_KEY_TAB,
[Keyboard_Backspace] = GLFW_KEY_BACKSPACE,
[Keyboard_Insert] = GLFW_KEY_INSERT,
[Keyboard_Delete] = GLFW_KEY_DELETE,
[Keyboard_Right] = GLFW_KEY_RIGHT,
[Keyboard_Left] = GLFW_KEY_LEFT,
[Keyboard_Down] = GLFW_KEY_DOWN,
[Keyboard_Up] = GLFW_KEY_UP,
[Keyboard_PageUp] = GLFW_KEY_PAGE_UP,
[Keyboard_PageDown] = GLFW_KEY_PAGE_DOWN,
[Keyboard_Home] = GLFW_KEY_HOME,
[Keyboard_End] = GLFW_KEY_END,
[Keyboard_CapsLock] = GLFW_KEY_CAPS_LOCK,
[Keyboard_ScrollLock] = GLFW_KEY_SCROLL_LOCK,
[Keyboard_NumLock] = GLFW_KEY_NUM_LOCK,
[Keyboard_PrintScreen] = GLFW_KEY_PRINT_SCREEN,
[Keyboard_Pause] = GLFW_KEY_PAUSE,
[Keyboard_F1] = GLFW_KEY_F1,
[Keyboard_F2] = GLFW_KEY_F2,
[Keyboard_F3] = GLFW_KEY_F3,
[Keyboard_F4] = GLFW_KEY_F4,
[Keyboard_F5] = GLFW_KEY_F5,
[Keyboard_F6] = GLFW_KEY_F6,
[Keyboard_F7] = GLFW_KEY_F7,
[Keyboard_F8] = GLFW_KEY_F8,
[Keyboard_F9] = GLFW_KEY_F9,
[Keyboard_F10] = GLFW_KEY_F10,
[Keyboard_F11] = GLFW_KEY_F11,
[Keyboard_F12] = GLFW_KEY_F12,
[Keyboard_LeftShift] = GLFW_KEY_LEFT_SHIFT,
[Keyboard_LeftControl] = GLFW_KEY_LEFT_CONTROL,
[Keyboard_LeftAlt] = GLFW_KEY_LEFT_ALT,
[Keyboard_LeftMeta] = GLFW_KEY_LEFT_SUPER,
[Keyboard_RightShift] = GLFW_KEY_RIGHT_SHIFT,
[Keyboard_RightControl] = GLFW_KEY_RIGHT_CONTROL,
[Keyboard_RightAlt] = GLFW_KEY_RIGHT_ALT,
[Keyboard_RightMeta] = GLFW_KEY_RIGHT_SUPER,
[Keyboard_Menu] = GLFW_KEY_MENU,
[Keyboard_LeftBracket] = GLFW_KEY_LEFT_BRACKET,
[Keyboard_Backslash] = GLFW_KEY_BACKSLASH,
[Keyboard_RightBracket] = GLFW_KEY_RIGHT_BRACKET,
[Keyboard_Grave] = GLFW_KEY_GRAVE_ACCENT,
[Keyboard_Pad_0] = GLFW_KEY_UNKNOWN,
[Keyboard_Pad_1] = GLFW_KEY_UNKNOWN,
[Keyboard_Pad_2] = GLFW_KEY_UNKNOWN,
[Keyboard_Pad_3] = GLFW_KEY_UNKNOWN,
[Keyboard_Pad_4] = GLFW_KEY_UNKNOWN,
[Keyboard_Pad_5] = GLFW_KEY_UNKNOWN,
[Keyboard_Pad_6] = GLFW_KEY_UNKNOWN,
[Keyboard_Pad_7] = GLFW_KEY_UNKNOWN,
[Keyboard_Pad_8] = GLFW_KEY_UNKNOWN,
[Keyboard_Pad_9] = GLFW_KEY_UNKNOWN,
[Keyboard_Pad_Period] = GLFW_KEY_UNKNOWN,
[Keyboard_Pad_Divide] = GLFW_KEY_UNKNOWN,
[Keyboard_Pad_Multiply] = GLFW_KEY_UNKNOWN,
[Keyboard_Pad_Minus] = GLFW_KEY_UNKNOWN,
[Keyboard_Pad_Add] = GLFW_KEY_UNKNOWN,
[Keyboard_Pad_Enter] = GLFW_KEY_UNKNOWN,
[Keyboard_Pad_Equal] = GLFW_KEY_UNKNOWN
};
int state = glfwGetKey(run_glfw_window, source_to_key[source]);
return state == GLFW_PRESS;
}
static int _get_mouse_button_down(enum InputSource source) {
int source_to_mouse[] = {
[Mouse_Left_Button] = GLFW_MOUSE_BUTTON_1,
[Mouse_Right_Button] = GLFW_MOUSE_BUTTON_2
};
int state = glfwGetMouseButton(run_glfw_window, source_to_mouse[source]);
return state == GLFW_PRESS;
}
void Engine__update_input(void) {
double xpos, ypos;
glfwGetCursorPos(run_glfw_window, &xpos, &ypos);
alias_memory_clear(_input_bindings, sizeof(*_input_bindings) * _input_binding_count);
for(uint32_t i = 0; i < _input_backend_pair_count; i++) {
enum InputSource source = _input_backend_pairs[i].source;
alias_R * binding = &_input_bindings[_input_backend_pairs[i].binding];
switch(source) {
case Keyboard_Apostrophe ... Keyboard_Pad_Equal:
if(_get_key_down(source)) {
*binding = alias_R_ONE;
}
break;
case Mouse_Left_Button ... Mouse_Right_Button:
if(_get_mouse_button_down(source)) {
*binding = alias_R_ONE;
}
break;
case Mouse_Position_X:
*binding = xpos;
break;
case Mouse_Position_Y:
*binding = ypos;
break;
case InputSource_COUNT:
break;
}
}
for(uint32_t i = 0; i < MAX_INPUT_FRONTEND_SETS; i++) {
for(uint32_t j = 0; j < _input_frontends[i].count; j++) {
struct InputSignal * signal = &_input_frontends[i].signals[j];
switch(signal->type) {
case InputSignal_Pass:
{
signal->boolean = _input_bindings[signal->bindings[0]] > alias_R_ZERO;
break;
}
case InputSignal_Up:
{
bool value = _input_bindings[signal->bindings[0]] > alias_R_ZERO;
signal->boolean = !signal->internal.up && value;
signal->internal.up = value;
break;
}
case InputSignal_Down:
{
bool value = _input_bindings[signal->bindings[0]] > alias_R_ZERO;
signal->boolean = signal->internal.down && !value;
signal->internal.down = value;
break;
}
case InputSignal_Direction:
{
signal->direction = alias_pga2d_direction(_input_bindings[signal->bindings[0]], _input_bindings[signal->bindings[1]]);
break;
}
case InputSignal_Point:
{
signal->point = alias_pga2d_point(_input_bindings[signal->bindings[0]], _input_bindings[signal->bindings[1]]);
break;
}
case InputSignal_ViewportPoint:
{
alias_R px = _input_bindings[signal->bindings[0]];
alias_R py = _input_bindings[signal->bindings[1]];
const struct Camera * camera = Camera_read(signal->click_camera);
const struct alias_LocalToWorld2D * transform = alias_LocalToWorld2D_read(signal->click_camera);
alias_R minx = alias_pga2d_point_x(camera->viewport_min) * Engine_render_get_width();
alias_R miny = alias_pga2d_point_y(camera->viewport_min) * Engine_render_get_height();
alias_R maxx = alias_pga2d_point_x(camera->viewport_max) * Engine_render_get_width();
alias_R maxy = alias_pga2d_point_y(camera->viewport_max) * Engine_render_get_height();
alias_R width = maxx - minx;
alias_R height = maxy - miny;
px -= minx;
py -= miny;
if(px < 0 || py < 0 || px > width || py > height) {
break;
}
px -= width / 2;
py -= height / 2;
alias_R cx = alias_pga2d_point_x(transform->position);
alias_R cy = alias_pga2d_point_y(transform->position);
px += cx;
py += cy;
signal->point = alias_pga2d_point(px, py);
break;
}
}
}
}
}