#define MAX_INPUT_FRONTEND_SETS 8
static uint32_t _input_backend_pair_count = 0;
static const struct engine_input_BackendPair * _input_backend_pairs = NULL;
static uint32_t _input_binding_count = 0;
static alias_R * _input_bindings = NULL;
void engine_input_setPlayerBackend(uint32_t player_index, const struct engine_input_BackendPair * 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 engine_input_Signal * signals;
} _input_frontends[MAX_INPUT_FRONTEND_SETS] = { 0 };
uint32_t engine_input_addFrontend(uint32_t player_index, struct engine_input_Signal * 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_input_removeFrontend(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 _input_get_key_down(enum engine_input_Device device) {
static int source_to_key[] = {
[engine_input_Device_keyboardApostrophe] = GLFW_KEY_APOSTROPHE,
[engine_input_Device_keyboardComma] = GLFW_KEY_COMMA,
[engine_input_Device_keyboardMinus] = GLFW_KEY_MINUS,
[engine_input_Device_keyboardPeriod] = GLFW_KEY_PERIOD,
[engine_input_Device_keyboardSlash] = GLFW_KEY_SLASH,
[engine_input_Device_keyboard0] = GLFW_KEY_0,
[engine_input_Device_keyboard1] = GLFW_KEY_1,
[engine_input_Device_keyboard2] = GLFW_KEY_2,
[engine_input_Device_keyboard3] = GLFW_KEY_3,
[engine_input_Device_keyboard4] = GLFW_KEY_4,
[engine_input_Device_keyboard5] = GLFW_KEY_5,
[engine_input_Device_keyboard6] = GLFW_KEY_6,
[engine_input_Device_keyboard7] = GLFW_KEY_7,
[engine_input_Device_keyboard8] = GLFW_KEY_8,
[engine_input_Device_keyboard9] = GLFW_KEY_9,
[engine_input_Device_keyboardSemicolon] = GLFW_KEY_SEMICOLON,
[engine_input_Device_keyboardEqual] = GLFW_KEY_EQUAL,
[engine_input_Device_keyboardA] = GLFW_KEY_A,
[engine_input_Device_keyboardB] = GLFW_KEY_B,
[engine_input_Device_keyboardC] = GLFW_KEY_C,
[engine_input_Device_keyboardD] = GLFW_KEY_D,
[engine_input_Device_keyboardE] = GLFW_KEY_E,
[engine_input_Device_keyboardF] = GLFW_KEY_F,
[engine_input_Device_keyboardG] = GLFW_KEY_G,
[engine_input_Device_keyboardH] = GLFW_KEY_H,
[engine_input_Device_keyboardI] = GLFW_KEY_I,
[engine_input_Device_keyboardJ] = GLFW_KEY_J,
[engine_input_Device_keyboardK] = GLFW_KEY_K,
[engine_input_Device_keyboardL] = GLFW_KEY_L,
[engine_input_Device_keyboardM] = GLFW_KEY_M,
[engine_input_Device_keyboardN] = GLFW_KEY_N,
[engine_input_Device_keyboardO] = GLFW_KEY_O,
[engine_input_Device_keyboardP] = GLFW_KEY_P,
[engine_input_Device_keyboardQ] = GLFW_KEY_Q,
[engine_input_Device_keyboardR] = GLFW_KEY_R,
[engine_input_Device_keyboardS] = GLFW_KEY_S,
[engine_input_Device_keyboardT] = GLFW_KEY_T,
[engine_input_Device_keyboardU] = GLFW_KEY_U,
[engine_input_Device_keyboardV] = GLFW_KEY_V,
[engine_input_Device_keyboardW] = GLFW_KEY_W,
[engine_input_Device_keyboardX] = GLFW_KEY_X,
[engine_input_Device_keyboardY] = GLFW_KEY_Y,
[engine_input_Device_keyboardZ] = GLFW_KEY_Z,
[engine_input_Device_keyboardSpace] = GLFW_KEY_SPACE,
[engine_input_Device_keyboardEscape] = GLFW_KEY_ESCAPE,
[engine_input_Device_keyboardEnter] = GLFW_KEY_ENTER,
[engine_input_Device_keyboardTab] = GLFW_KEY_TAB,
[engine_input_Device_keyboardBackspace] = GLFW_KEY_BACKSPACE,
[engine_input_Device_keyboardInsert] = GLFW_KEY_INSERT,
[engine_input_Device_keyboardDelete] = GLFW_KEY_DELETE,
[engine_input_Device_keyboardRight] = GLFW_KEY_RIGHT,
[engine_input_Device_keyboardLeft] = GLFW_KEY_LEFT,
[engine_input_Device_keyboardDown] = GLFW_KEY_DOWN,
[engine_input_Device_keyboardUp] = GLFW_KEY_UP,
[engine_input_Device_keyboardPageUp] = GLFW_KEY_PAGE_UP,
[engine_input_Device_keyboardPageDown] = GLFW_KEY_PAGE_DOWN,
[engine_input_Device_keyboardHome] = GLFW_KEY_HOME,
[engine_input_Device_keyboardEnd] = GLFW_KEY_END,
[engine_input_Device_keyboardCapsLock] = GLFW_KEY_CAPS_LOCK,
[engine_input_Device_keyboardScrollLock] = GLFW_KEY_SCROLL_LOCK,
[engine_input_Device_keyboardNumLock] = GLFW_KEY_NUM_LOCK,
[engine_input_Device_keyboardPrintScreen] = GLFW_KEY_PRINT_SCREEN,
[engine_input_Device_keyboardPause] = GLFW_KEY_PAUSE,
[engine_input_Device_keyboardF1] = GLFW_KEY_F1,
[engine_input_Device_keyboardF2] = GLFW_KEY_F2,
[engine_input_Device_keyboardF3] = GLFW_KEY_F3,
[engine_input_Device_keyboardF4] = GLFW_KEY_F4,
[engine_input_Device_keyboardF5] = GLFW_KEY_F5,
[engine_input_Device_keyboardF6] = GLFW_KEY_F6,
[engine_input_Device_keyboardF7] = GLFW_KEY_F7,
[engine_input_Device_keyboardF8] = GLFW_KEY_F8,
[engine_input_Device_keyboardF9] = GLFW_KEY_F9,
[engine_input_Device_keyboardF10] = GLFW_KEY_F10,
[engine_input_Device_keyboardF11] = GLFW_KEY_F11,
[engine_input_Device_keyboardF12] = GLFW_KEY_F12,
[engine_input_Device_keyboardLeftShift] = GLFW_KEY_LEFT_SHIFT,
[engine_input_Device_keyboardLeftControl] = GLFW_KEY_LEFT_CONTROL,
[engine_input_Device_keyboardLeftAlt] = GLFW_KEY_LEFT_ALT,
[engine_input_Device_keyboardLeftMeta] = GLFW_KEY_LEFT_SUPER,
[engine_input_Device_keyboardRightShift] = GLFW_KEY_RIGHT_SHIFT,
[engine_input_Device_keyboardRightControl] = GLFW_KEY_RIGHT_CONTROL,
[engine_input_Device_keyboardRightAlt] = GLFW_KEY_RIGHT_ALT,
[engine_input_Device_keyboardRightMeta] = GLFW_KEY_RIGHT_SUPER,
[engine_input_Device_keyboardMenu] = GLFW_KEY_MENU,
[engine_input_Device_keyboardLeftBracket] = GLFW_KEY_LEFT_BRACKET,
[engine_input_Device_keyboardBackslash] = GLFW_KEY_BACKSLASH,
[engine_input_Device_keyboardRightBracket] = GLFW_KEY_RIGHT_BRACKET,
[engine_input_Device_keyboardGrave] = GLFW_KEY_GRAVE_ACCENT,
[engine_input_Device_keyboardPad0] = GLFW_KEY_UNKNOWN,
[engine_input_Device_keyboardPad1] = GLFW_KEY_UNKNOWN,
[engine_input_Device_keyboardPad2] = GLFW_KEY_UNKNOWN,
[engine_input_Device_keyboardPad3] = GLFW_KEY_UNKNOWN,
[engine_input_Device_keyboardPad4] = GLFW_KEY_UNKNOWN,
[engine_input_Device_keyboardPad5] = GLFW_KEY_UNKNOWN,
[engine_input_Device_keyboardPad6] = GLFW_KEY_UNKNOWN,
[engine_input_Device_keyboardPad7] = GLFW_KEY_UNKNOWN,
[engine_input_Device_keyboardPad8] = GLFW_KEY_UNKNOWN,
[engine_input_Device_keyboardPad9] = GLFW_KEY_UNKNOWN,
[engine_input_Device_keyboardPadPeriod] = GLFW_KEY_UNKNOWN,
[engine_input_Device_keyboardPadDivide] = GLFW_KEY_UNKNOWN,
[engine_input_Device_keyboardPadMultiply] = GLFW_KEY_UNKNOWN,
[engine_input_Device_keyboardPadMinus] = GLFW_KEY_UNKNOWN,
[engine_input_Device_keyboardPadAdd] = GLFW_KEY_UNKNOWN,
[engine_input_Device_keyboardPadEnter] = GLFW_KEY_UNKNOWN,
[engine_input_Device_keyboardPadEqual] = GLFW_KEY_UNKNOWN
};
int state = glfwGetKey(_r_window, source_to_key[device]);
return state == GLFW_PRESS;
}
static int _input_get_mouse_button_down(enum engine_input_Device device) {
int source_to_mouse[] = {
[engine_input_Device_mouseLeftButton] = GLFW_MOUSE_BUTTON_1,
[engine_input_Device_mouseRightButton] = GLFW_MOUSE_BUTTON_2
};
int state = glfwGetMouseButton(_r_window, source_to_mouse[device]);
return state == GLFW_PRESS;
}
static void _input_frame(void) {
double xpos, ypos;
glfwGetCursorPos(_r_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 engine_input_Device device = _input_backend_pairs[i].device;
alias_R * binding = &_input_bindings[_input_backend_pairs[i].binding];
switch(device) {
case engine_input_Device_keyboardApostrophe ... engine_input_Device_keyboardPadEqual:
if(_input_get_key_down(device)) {
*binding = alias_R_ONE;
}
break;
case engine_input_Device_mouseLeftButton ... engine_input_Device_mouseRightButton:
if(_input_get_mouse_button_down(device)) {
*binding = alias_R_ONE;
}
break;
case engine_input_Device_mousePositionX:
*binding = xpos;
break;
case engine_input_Device_mousePositionY:
*binding = ypos;
break;
case engine_input_Device_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 engine_input_Signal * signal = &_input_frontends[i].signals[j];
switch(signal->type) {
case engine_input_Signal_pass:
{
signal->boolean = _input_bindings[signal->bindings[0]] > alias_R_ZERO;
break;
}
case engine_input_Signal_up:
{
bool value = _input_bindings[signal->bindings[0]] > alias_R_ZERO;
signal->boolean = !signal->internal.up && value;
signal->internal.up = value;
break;
}
case engine_input_Signal_down:
{
bool value = _input_bindings[signal->bindings[0]] > alias_R_ZERO;
signal->boolean = signal->internal.down && !value;
signal->internal.down = value;
break;
}
case engine_input_Signal_direction:
{
signal->direction = alias_pga2d_direction(_input_bindings[signal->bindings[0]], _input_bindings[signal->bindings[1]]);
break;
}
case engine_input_Signal_point:
{
signal->point = alias_pga2d_point(_input_bindings[signal->bindings[0]], _input_bindings[signal->bindings[1]]);
break;
}
case engine_input_Signal_viewportPoint:
{
alias_R px = _input_bindings[signal->bindings[0]];
alias_R py = _input_bindings[signal->bindings[1]];
const struct engine_Camera * camera = engine_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) * _r_width;
alias_R miny = alias_pga2d_point_y(camera->viewport_min) * _r_height;
alias_R maxx = alias_pga2d_point_x(camera->viewport_max) * _r_width;
alias_R maxy = alias_pga2d_point_y(camera->viewport_max) * _r_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;
}
}
}
}
}