diff --git a/src/input_state.c b/src/input_state.c new file mode 100644 index 0000000..3e54f17 --- /dev/null +++ b/src/input_state.c @@ -0,0 +1,348 @@ +/************************************************************//** +* +* @file: input_state.c +* @author: Martin Fouilleul +* @date: 19/04/2023 +* +*****************************************************************/ +#include"input_state.h" + +//--------------------------------------------------------------- +// Input state updating +//--------------------------------------------------------------- + +static void mp_update_key_state(mp_input_state* state, mp_key_state* key, mp_key_action action) +{ + u64 frameCounter = state->frameCounter; + if(key->lastUpdate != frameCounter) + { + key->transitionCount = 0; + key->repeatCount = 0; + key->sysClicked = false; + key->sysDoubleClicked = false; + key->lastUpdate = frameCounter; + } + + switch(action) + { + case MP_KEY_PRESS: + { + if(!key->down) + { + key->transitionCount++; + } + key->down = true; + } break; + + case MP_KEY_REPEAT: + { + key->repeatCount++; + key->down = true; + } break; + + case MP_KEY_RELEASE: + { + if(key->down) + { + key->transitionCount++; + } + key->down = false; + } break; + + default: + break; + } +} + +static void mp_update_key_mods(mp_input_state* state, mp_keymod_flags mods) +{ + state->keyboard.mods = mods; +} + +static void mp_update_mouse_move(mp_input_state* state, f32 x, f32 y, f32 deltaX, f32 deltaY) +{ + u64 frameCounter = state->frameCounter; + mp_mouse_state* mouse = &state->mouse; + if(mouse->lastUpdate != frameCounter) + { + mouse->delta = (vec2){0, 0}; + mouse->wheel = (vec2){0, 0}; + mouse->lastUpdate = frameCounter; + } + mouse->pos = (vec2){x, y}; + mouse->delta.x += deltaX; + mouse->delta.y += deltaY; +} + +static void mp_update_mouse_wheel(mp_input_state* state, f32 deltaX, f32 deltaY) +{ + u64 frameCounter = state->frameCounter; + mp_mouse_state* mouse = &state->mouse; + if(mouse->lastUpdate != frameCounter) + { + mouse->delta = (vec2){0, 0}; + mouse->wheel = (vec2){0, 0}; + mouse->lastUpdate = frameCounter; + } + mouse->wheel.x += deltaX; + mouse->wheel.y += deltaY; +} + +static void mp_update_text(mp_input_state* state, utf32 codepoint) +{ + u64 frameCounter = state->frameCounter; + mp_text_state* text = &state->text; + + if(text->lastUpdate != frameCounter) + { + text->codePoints.len = 0; + text->lastUpdate = frameCounter; + } + + text->codePoints.ptr = text->backing; + if(text->codePoints.len < MP_INPUT_TEXT_BACKING_SIZE) + { + text->codePoints.ptr[text->codePoints.len] = codepoint; + text->codePoints.len++; + } + else + { + log_warning("too many input codepoints per frame, dropping input"); + } +} + +void mp_input_next_frame(mp_input_state* state) +{ + state->frameCounter++; +} + +void mp_input_process_event(mp_input_state* state, mp_event event) +{ + switch(event.type) + { + case MP_EVENT_KEYBOARD_KEY: + { + mp_key_state* key = &state->keyboard.keys[event.key.code]; + mp_update_key_state(state, key, event.key.action); + mp_update_key_mods(state, event.key.mods); + } break; + + case MP_EVENT_KEYBOARD_CHAR: + mp_update_text(state, event.character.codepoint); + break; + + case MP_EVENT_KEYBOARD_MODS: + mp_update_key_mods(state, event.key.mods); + break; + + case MP_EVENT_MOUSE_MOVE: + mp_update_mouse_move(state, event.move.x, event.move.y, event.move.deltaX, event.move.deltaY); + break; + + case MP_EVENT_MOUSE_WHEEL: + mp_update_mouse_wheel(state, event.move.deltaX, event.move.deltaY); + break; + + case MP_EVENT_MOUSE_BUTTON: + { + mp_key_state* key = &state->mouse.buttons[event.key.code]; + mp_update_key_state(state, key, event.key.action); + + if(event.key.action == MP_KEY_PRESS) + { + if(event.key.clickCount >= 1) + { + key->sysClicked = true; + } + if(event.key.clickCount >= 2) + { + key->sysDoubleClicked = true; + } + } + + mp_update_key_mods(state, event.key.mods); + } break; + + default: + break; + } +} + +//-------------------------------------------------------------------- +// Input state polling +//-------------------------------------------------------------------- + +mp_key_state mp_key_get_state(mp_input_state* input, mp_key_code key) +{ + mp_key_state state = {0}; + if(key <= MP_KEY_COUNT) + { + state = input->keyboard.keys[key]; + } + return(state); +} + +mp_key_state mp_mouse_button_get_state(mp_input_state* input, mp_mouse_button button) +{ + mp_key_state state = {0}; + if(button <= MP_MOUSE_BUTTON_COUNT) + { + state = input->mouse.buttons[button]; + } + return(state); +} + +int mp_key_state_press_count(mp_input_state* input, mp_key_state* key) +{ + int count = 0; + if(key->lastUpdate == input->frameCounter) + { + count = key->transitionCount / 2; + if(key->down) + { + //NOTE: add one if state is down transition count is odd + count += (key->transitionCount & 0x01); + } + } + return(count); +} + +int mp_key_state_release_count(mp_input_state* input, mp_key_state* key) +{ + int count = 0; + if(key->lastUpdate == input->frameCounter) + { + count = key->transitionCount / 2; + if(!key->down) + { + //NOTE: add one if state is up and transition count is odd + count += (key->transitionCount & 0x01); + } + } + return(count); +} + +int mp_key_state_repeat_count(mp_input_state* input, mp_key_state* key) +{ + int count = 0; + if(key->lastUpdate == input->frameCounter) + { + count = key->repeatCount; + } + return(count); +} + +bool mp_key_down(mp_input_state* input, mp_key_code key) +{ + mp_key_state state = mp_key_get_state(input, key); + return(state.down); +} + +int mp_key_pressed(mp_input_state* input, mp_key_code key) +{ + mp_key_state state = mp_key_get_state(input, key); + int res = mp_key_state_press_count(input, &state); + return(res); +} + +int mp_key_released(mp_input_state* input, mp_key_code key) +{ + mp_key_state state = mp_key_get_state(input, key); + int res = mp_key_state_release_count(input, &state); + return(res); +} + +int mp_key_repeated(mp_input_state* input, mp_key_code key) +{ + mp_key_state state = mp_key_get_state(input, key); + int res = mp_key_state_repeat_count(input, &state); + return(res); +} + +bool mp_mouse_down(mp_input_state* input, mp_mouse_button button) +{ + mp_key_state state = mp_mouse_button_get_state(input, button); + return(state.down); +} + +int mp_mouse_pressed(mp_input_state* input, mp_mouse_button button) +{ + mp_key_state state = mp_mouse_button_get_state(input, button); + int res = mp_key_state_press_count(input, &state); + return(res); +} + +int mp_mouse_released(mp_input_state* input, mp_mouse_button button) +{ + mp_key_state state = mp_mouse_button_get_state(input, button); + int res = mp_key_state_release_count(input, &state); + return(res); +} + +bool mp_mouse_clicked(mp_input_state* input, mp_mouse_button button) +{ + mp_key_state state = mp_mouse_button_get_state(input, button); + bool clicked = state.sysClicked && (state.lastUpdate == input->frameCounter); + return(clicked); +} + +bool mp_mouse_double_clicked(mp_input_state* input, mp_mouse_button button) +{ + mp_key_state state = mp_mouse_button_get_state(input, button); + bool doubleClicked = state.sysClicked && (state.lastUpdate == input->frameCounter); + return(doubleClicked); +} + +mp_keymod_flags mp_key_mods(mp_input_state* input) +{ + return(input->keyboard.mods); +} + +vec2 mp_mouse_position(mp_input_state* input) +{ + return(input->mouse.pos); +} + +vec2 mp_mouse_delta(mp_input_state* input) +{ + if(input->mouse.lastUpdate == input->frameCounter) + { + return(input->mouse.delta); + } + else + { + return((vec2){0, 0}); + } +} + +vec2 mp_mouse_wheel(mp_input_state* input) +{ + if(input->mouse.lastUpdate == input->frameCounter) + { + return(input->mouse.wheel); + } + else + { + return((vec2){0, 0}); + } +} + +str32 mp_input_text_utf32(mp_input_state* input, mem_arena* arena) +{ + str32 res = {0}; + if(input->text.lastUpdate == input->frameCounter) + { + res = str32_push_copy(arena, input->text.codePoints); + } + return(res); +} + +str8 mp_input_text_utf8(mp_input_state* input, mem_arena* arena) +{ + str8 res = {0}; + if(input->text.lastUpdate == input->frameCounter) + { + res = utf8_push_from_codepoints(arena, input->text.codePoints); + } + return(res); +} diff --git a/src/input_state.h b/src/input_state.h new file mode 100644 index 0000000..00e8b8e --- /dev/null +++ b/src/input_state.h @@ -0,0 +1,96 @@ +/************************************************************//** +* +* @file: input_state.h +* @author: Martin Fouilleul +* @date: 19/04/2023 +* +*****************************************************************/ +#ifndef __INPUT_STATE_H_ +#define __INPUT_STATE_H_ + +#include"platform/platform.h" +#include"util/typedefs.h" +#include"util/strings.h" +#include"util/utf8.h" +#include"mp_app.h" + +typedef struct mp_key_state +{ + u64 lastUpdate; + u32 transitionCount; + u32 repeatCount; + bool down; + bool sysClicked; + bool sysDoubleClicked; + +} mp_key_state; + +typedef struct mp_keyboard_state +{ + mp_key_state keys[MP_KEY_COUNT]; + mp_keymod_flags mods; +} mp_keyboard_state; + +typedef struct mp_mouse_state +{ + u64 lastUpdate; + bool posValid; + vec2 pos; + vec2 delta; + vec2 wheel; + + union + { + mp_key_state buttons[MP_MOUSE_BUTTON_COUNT]; + struct + { + mp_key_state left; + mp_key_state right; + mp_key_state middle; + mp_key_state ext1; + mp_key_state ext2; + }; + }; +} mp_mouse_state; + +enum { MP_INPUT_TEXT_BACKING_SIZE = 64 }; + +typedef struct mp_text_state +{ + u64 lastUpdate; + utf32 backing[MP_INPUT_TEXT_BACKING_SIZE]; + str32 codePoints; +} mp_text_state; + +typedef struct mp_input_state +{ + u64 frameCounter; + mp_keyboard_state keyboard; + mp_mouse_state mouse; + mp_text_state text; +} mp_input_state; + +MP_API void mp_input_process_event(mp_input_state* state, mp_event event); +MP_API void mp_input_next_frame(mp_input_state* state); + +MP_API bool mp_key_down(mp_input_state* state, mp_key_code key); +MP_API int mp_key_pressed(mp_input_state* state, mp_key_code key); +MP_API int mp_key_released(mp_input_state* state, mp_key_code key); +MP_API int mp_key_repeated(mp_input_state* state, mp_key_code key); + +MP_API bool mp_mouse_down(mp_input_state* state, mp_mouse_button button); +MP_API int mp_mouse_pressed(mp_input_state* state, mp_mouse_button button); +MP_API int mp_mouse_released(mp_input_state* state, mp_mouse_button button); +MP_API bool mp_mouse_clicked(mp_input_state* state, mp_mouse_button button); +MP_API bool mp_mouse_double_clicked(mp_input_state* state, mp_mouse_button button); + +MP_API vec2 mp_mouse_position(mp_input_state* state); +MP_API vec2 mp_mouse_delta(mp_input_state* state); +MP_API vec2 mp_mouse_wheel(mp_input_state* state); + +MP_API str32 mp_input_text_utf32(mp_input_state* state, mem_arena* arena); +MP_API str8 mp_input_text_utf8(mp_input_state* state, mem_arena* arena); + +MP_API mp_keymod_flags mp_key_mods(mp_input_state* state); + +#endif //__INPUT_STATE_H_ diff --git a/src/milepost.c b/src/milepost.c index dd4dddb..a2b0d3f 100644 --- a/src/milepost.c +++ b/src/milepost.c @@ -75,4 +75,5 @@ #error "Unsupported platform" #endif +#include"input_state.c" #include"ui.c" diff --git a/src/milepost.h b/src/milepost.h index 616797d..e3e8bc6 100644 --- a/src/milepost.h +++ b/src/milepost.h @@ -37,6 +37,7 @@ //---------------------------------------------------------------- #include"mp_app.h" #include"graphics.h" +#include"input_state.h" #include"ui.h" #ifdef MG_INCLUDE_GL_API diff --git a/src/mp_app.c b/src/mp_app.c index da9affa..ec1e789 100644 --- a/src/mp_app.c +++ b/src/mp_app.c @@ -122,286 +122,3 @@ bool mp_next_event(mp_event* event) return(false); } } - -//--------------------------------------------------------------- -// Input state updating -//--------------------------------------------------------------- - -static void mp_update_key_state(mp_key_state* key, mp_key_action action) -{ - u64 frameCounter = __mpApp.inputState.frameCounter; - if(key->lastUpdate != frameCounter) - { - key->transitionCount = 0; - key->repeatCount = 0; - key->sysClicked = false; - key->sysDoubleClicked = false; - key->lastUpdate = frameCounter; - } - - switch(action) - { - case MP_KEY_PRESS: - { - if(!key->down) - { - key->transitionCount++; - } - key->down = true; - } break; - - case MP_KEY_REPEAT: - { - key->repeatCount++; - key->down = true; - } break; - - case MP_KEY_RELEASE: - { - if(key->down) - { - key->transitionCount++; - } - key->down = false; - } break; - - default: - break; - } -} - -static void mp_update_key_mods(mp_keymod_flags mods) -{ - __mpApp.inputState.keyboard.mods = mods; -} - -static void mp_update_mouse_move(f32 x, f32 y, f32 deltaX, f32 deltaY) -{ - u64 frameCounter = __mpApp.inputState.frameCounter; - mp_mouse_state* mouse = &__mpApp.inputState.mouse; - if(mouse->lastUpdate != frameCounter) - { - mouse->delta = (vec2){0, 0}; - mouse->wheel = (vec2){0, 0}; - mouse->lastUpdate = frameCounter; - } - mouse->pos = (vec2){x, y}; - mouse->delta.x += deltaX; - mouse->delta.y += deltaY; -} - -static void mp_update_mouse_wheel(f32 deltaX, f32 deltaY) -{ - u64 frameCounter = __mpApp.inputState.frameCounter; - mp_mouse_state* mouse = &__mpApp.inputState.mouse; - if(mouse->lastUpdate != frameCounter) - { - mouse->delta = (vec2){0, 0}; - mouse->wheel = (vec2){0, 0}; - mouse->lastUpdate = frameCounter; - } - mouse->wheel.x += deltaX; - mouse->wheel.y += deltaY; -} - -static void mp_update_text(utf32 codepoint) -{ - u64 frameCounter = __mpApp.inputState.frameCounter; - mp_text_state* text = &__mpApp.inputState.text; - - if(text->lastUpdate != frameCounter) - { - text->codePoints.len = 0; - text->lastUpdate = frameCounter; - } - - text->codePoints.ptr = text->backing; - if(text->codePoints.len < MP_INPUT_TEXT_BACKING_SIZE) - { - text->codePoints.ptr[text->codePoints.len] = codepoint; - text->codePoints.len++; - } - else - { - log_warning("too many input codepoints per frame, dropping input"); - } -} - -//-------------------------------------------------------------------- -// Input state polling -//-------------------------------------------------------------------- - -mp_key_state mp_key_get_state(mp_key_code key) -{ - mp_key_state state = {0}; - if(key <= MP_KEY_COUNT) - { - state = __mpApp.inputState.keyboard.keys[key]; - } - return(state); -} - -mp_key_state mp_mouse_button_get_state(mp_mouse_button button) -{ - mp_key_state state = {0}; - if(button <= MP_MOUSE_BUTTON_COUNT) - { - state = __mpApp.inputState.mouse.buttons[button]; - } - return(state); -} - -int mp_key_state_press_count(mp_key_state* key) -{ - int count = 0; - if(key->lastUpdate == __mpApp.inputState.frameCounter) - { - count = key->transitionCount / 2; - if(key->down) - { - //NOTE: add one if state is down transition count is odd - count += (key->transitionCount & 0x01); - } - } - return(count); -} - -int mp_key_state_release_count(mp_key_state* key) -{ - int count = 0; - if(key->lastUpdate == __mpApp.inputState.frameCounter) - { - count = key->transitionCount / 2; - if(!key->down) - { - //NOTE: add one if state is up and transition count is odd - count += (key->transitionCount & 0x01); - } - } - return(count); -} - -int mp_key_state_repeat_count(mp_key_state* key) -{ - int count = 0; - if(key->lastUpdate == __mpApp.inputState.frameCounter) - { - count = key->repeatCount; - } - return(count); -} - -bool mp_key_down(mp_key_code key) -{ - mp_key_state state = mp_key_get_state(key); - return(state.down); -} - -int mp_key_pressed(mp_key_code key) -{ - mp_key_state state = mp_key_get_state(key); - int res = mp_key_state_press_count(&state); - return(res); -} - -int mp_key_released(mp_key_code key) -{ - mp_key_state state = mp_key_get_state(key); - int res = mp_key_state_release_count(&state); - return(res); -} - -int mp_key_repeated(mp_key_code key) -{ - mp_key_state state = mp_key_get_state(key); - int res = mp_key_state_repeat_count(&state); - return(res); -} - -bool mp_mouse_down(mp_mouse_button button) -{ - mp_key_state state = mp_mouse_button_get_state(button); - return(state.down); -} - -int mp_mouse_pressed(mp_mouse_button button) -{ - mp_key_state state = mp_mouse_button_get_state(button); - int res = mp_key_state_press_count(&state); - return(res); -} - -int mp_mouse_released(mp_mouse_button button) -{ - mp_key_state state = mp_mouse_button_get_state(button); - int res = mp_key_state_release_count(&state); - return(res); -} - -bool mp_mouse_clicked(mp_mouse_button button) -{ - mp_key_state state = mp_mouse_button_get_state(button); - bool clicked = state.sysClicked && (state.lastUpdate == __mpApp.inputState.frameCounter); - return(clicked); -} - -bool mp_mouse_double_clicked(mp_mouse_button button) -{ - mp_key_state state = mp_mouse_button_get_state(button); - bool doubleClicked = state.sysClicked && (state.lastUpdate == __mpApp.inputState.frameCounter); - return(doubleClicked); -} - -mp_keymod_flags mp_key_mods() -{ - return(__mpApp.inputState.keyboard.mods); -} - -vec2 mp_mouse_position() -{ - return(__mpApp.inputState.mouse.pos); -} - -vec2 mp_mouse_delta() -{ - if(__mpApp.inputState.mouse.lastUpdate == __mpApp.inputState.frameCounter) - { - return(__mpApp.inputState.mouse.delta); - } - else - { - return((vec2){0, 0}); - } -} - -vec2 mp_mouse_wheel() -{ - if(__mpApp.inputState.mouse.lastUpdate == __mpApp.inputState.frameCounter) - { - return(__mpApp.inputState.mouse.wheel); - } - else - { - return((vec2){0, 0}); - } -} - -str32 mp_input_text_utf32(mem_arena* arena) -{ - str32 res = {0}; - if(__mpApp.inputState.text.lastUpdate == __mpApp.inputState.frameCounter) - { - res = str32_push_copy(arena, __mpApp.inputState.text.codePoints); - } - return(res); -} - -str8 mp_input_text_utf8(mem_arena* arena) -{ - str8 res = {0}; - if(__mpApp.inputState.text.lastUpdate == __mpApp.inputState.frameCounter) - { - res = utf8_push_from_codepoints(arena, __mpApp.inputState.text.codePoints); - } - return(res); -} diff --git a/src/mp_app.h b/src/mp_app.h index 295299c..728d582 100644 --- a/src/mp_app.h +++ b/src/mp_app.h @@ -319,30 +319,6 @@ MP_API void mp_window_center(mp_window window); MP_API mp_rect mp_window_content_rect_for_frame_rect(mp_rect frameRect, mp_window_style style); MP_API mp_rect mp_window_frame_rect_for_content_rect(mp_rect contentRect, mp_window_style style); -//-------------------------------------------------------------------- -// Input state polling -//-------------------------------------------------------------------- - -MP_API bool mp_key_down(mp_key_code key); -MP_API int mp_key_pressed(mp_key_code key); -MP_API int mp_key_released(mp_key_code key); -MP_API int mp_key_repeated(mp_key_code key); - -MP_API bool mp_mouse_down(mp_mouse_button button); -MP_API int mp_mouse_pressed(mp_mouse_button button); -MP_API int mp_mouse_released(mp_mouse_button button); -MP_API bool mp_mouse_clicked(mp_mouse_button button); -MP_API bool mp_mouse_double_clicked(mp_mouse_button button); - -MP_API vec2 mp_mouse_position(void); -MP_API vec2 mp_mouse_delta(void); -MP_API vec2 mp_mouse_wheel(void); - -MP_API str32 mp_input_text_utf32(mem_arena* arena); -MP_API str8 mp_input_text_utf8(mem_arena* arena); - -MP_API mp_keymod_flags mp_key_mods(); - //-------------------------------------------------------------------- // Clipboard //-------------------------------------------------------------------- diff --git a/src/mp_app_internal.h b/src/mp_app_internal.h index e0d61a2..97b75a5 100644 --- a/src/mp_app_internal.h +++ b/src/mp_app_internal.h @@ -22,72 +22,6 @@ #error "platform not supported yet" #endif -//--------------------------------------------------------------- -// Input State -//--------------------------------------------------------------- - -typedef struct mp_key_utf8 -{ - u8 labelLen; - char label[8]; -} mp_key_utf8; - -typedef struct mp_key_state -{ - u64 lastUpdate; - u32 transitionCount; - u32 repeatCount; - bool down; - bool sysClicked; - bool sysDoubleClicked; - -} mp_key_state; - -typedef struct mp_keyboard_state -{ - mp_key_state keys[MP_KEY_COUNT]; - mp_keymod_flags mods; -} mp_keyboard_state; - -typedef struct mp_mouse_state -{ - u64 lastUpdate; - bool posValid; - vec2 pos; - vec2 delta; - vec2 wheel; - - union - { - mp_key_state buttons[MP_MOUSE_BUTTON_COUNT]; - struct - { - mp_key_state left; - mp_key_state right; - mp_key_state middle; - mp_key_state ext1; - mp_key_state ext2; - }; - }; -} mp_mouse_state; - -enum { MP_INPUT_TEXT_BACKING_SIZE = 64 }; - -typedef struct mp_text_state -{ - u64 lastUpdate; - utf32 backing[MP_INPUT_TEXT_BACKING_SIZE]; - str32 codePoints; -} mp_text_state; - -typedef struct mp_input_state -{ - u64 frameCounter; - mp_keyboard_state keyboard; - mp_mouse_state mouse; - mp_text_state text; -} mp_input_state; - //--------------------------------------------------------------- // Window structure //--------------------------------------------------------------- @@ -121,6 +55,13 @@ typedef struct mp_window_data // Global App State //--------------------------------------------------------------- +typedef struct mp_key_utf8 +{ + u8 labelLen; + char label[8]; +} mp_key_utf8; + + enum { MP_APP_MAX_WINDOWS = 128 }; typedef struct mp_app @@ -142,8 +83,6 @@ typedef struct mp_app mp_live_resize_callback liveResizeCallback; void* liveResizeData; - mp_input_state inputState; - mp_key_utf8 keyLabels[512]; int keyCodes[512]; int nativeKeys[MP_KEY_COUNT]; diff --git a/src/osx_app.m b/src/osx_app.m index 7957594..c76a86d 100644 --- a/src/osx_app.m +++ b/src/osx_app.m @@ -804,19 +804,6 @@ static void mp_process_mouse_button(NSEvent* nsEvent, mp_window_data* window, mp event.key.mods = mp_convert_osx_mods([nsEvent modifierFlags]); event.key.clickCount = [nsEvent clickCount]; - mp_key_state* keyState = &__mpApp.inputState.mouse.buttons[event.key.code]; - mp_update_key_state(keyState, action); - if(action == MP_KEY_PRESS) - { - if(event.key.clickCount >= 1) - { - keyState->sysClicked = true; - } - if(event.key.clickCount >= 2) - { - keyState->sysDoubleClicked = true; - } - } mp_queue_event(&event); } @@ -870,8 +857,6 @@ static void mp_process_mouse_button(NSEvent* nsEvent, mp_window_data* window, mp event.move.deltaY = [nsEvent deltaY]; event.move.mods = mp_convert_osx_mods([nsEvent modifierFlags]); - mp_update_mouse_move(event.move.x, event.move.y, event.move.deltaX, event.move.deltaY); - mp_queue_event(&event); } @@ -888,8 +873,6 @@ static void mp_process_mouse_button(NSEvent* nsEvent, mp_window_data* window, mp event.move.deltaY = -[nsEvent scrollingDeltaY]*factor; event.move.mods = mp_convert_osx_mods([nsEvent modifierFlags]); - mp_update_mouse_wheel(event.move.deltaX, event.move.deltaY); - mp_queue_event(&event); } @@ -924,8 +907,6 @@ static void mp_process_mouse_button(NSEvent* nsEvent, mp_window_data* window, mp event.key.labelLen = label.len; memcpy(event.key.label, label.ptr, label.len); - mp_update_key_state(&__mpApp.inputState.keyboard.keys[event.key.code], action); - mp_queue_event(&event); [self interpretKeyEvents:@[nsEvent]]; @@ -940,8 +921,6 @@ static void mp_process_mouse_button(NSEvent* nsEvent, mp_window_data* window, mp event.key.code = mp_convert_osx_key([nsEvent keyCode]); event.key.mods = mp_convert_osx_mods([nsEvent modifierFlags]); - mp_update_key_state(&__mpApp.inputState.keyboard.keys[event.key.code], MP_KEY_RELEASE); - mp_queue_event(&event); } @@ -952,8 +931,6 @@ static void mp_process_mouse_button(NSEvent* nsEvent, mp_window_data* window, mp event.type = MP_EVENT_KEYBOARD_MODS; event.key.mods = mp_convert_osx_mods([nsEvent modifierFlags]); - mp_update_key_mods(event.key.mods); - mp_queue_event(&event); } @@ -1092,8 +1069,6 @@ static const NSRange kEmptyRange = { NSNotFound, 0 }; str8 seq = utf8_encode(event.character.sequence, event.character.codepoint); event.character.seqLen = seq.len; - mp_update_text(codepoint); - mp_queue_event(&event); } } @@ -1956,8 +1931,6 @@ void mp_set_live_resize_callback(mp_live_resize_callback callback, void* data) void mp_pump_events(f64 timeout) { - __mpApp.inputState.frameCounter++; - @autoreleasepool { bool accumulate = false; @@ -2037,7 +2010,7 @@ void mp_end_input_frame() ////////////////////////////////////////////////////////////////////////////////////////////// //TODO: make sure we call arena clear once per event frame, even when using runloop etc... ////////////////////////////////////////////////////////////////////////////////////////////// - __mpApp.inputState.frameCounter++; + mem_arena_clear(&__mpApp.eventArena); } diff --git a/src/ui.c b/src/ui.c index ed3cdc0..a7968fc 100644 --- a/src/ui.c +++ b/src/ui.c @@ -28,71 +28,6 @@ static ui_style UI_STYLE_DEFAULTS = .color = {0, 0, 0, 1}, .fontSize = 16, }; -//----------------------------------------------------------------------------- -// context -//----------------------------------------------------------------------------- - -enum { UI_MAX_INPUT_CHAR_PER_FRAME = 64 }; - -typedef struct ui_input_text -{ - u8 count; - utf32 codePoints[UI_MAX_INPUT_CHAR_PER_FRAME]; - -} ui_input_text; - -typedef struct ui_stack_elt ui_stack_elt; -struct ui_stack_elt -{ - ui_stack_elt* parent; - union - { - ui_box* box; - ui_size size; - mp_rect clip; - }; -}; - -typedef struct ui_tag_elt -{ - list_elt listElt; - ui_tag tag; -} ui_tag_elt; - -enum { UI_BOX_MAP_BUCKET_COUNT = 1024 }; - -typedef struct ui_context -{ - bool init; - - u64 frameCounter; - f64 frameTime; - f64 lastFrameDuration; - - mem_arena frameArena; - mem_pool boxPool; - list_info boxMap[UI_BOX_MAP_BUCKET_COUNT]; - - ui_box* root; - ui_box* overlay; - list_info overlayList; - ui_stack_elt* boxStack; - ui_stack_elt* clipStack; - - list_info nextBoxBeforeRules; - list_info nextBoxAfterRules; - list_info nextBoxTags; - - u32 z; - ui_box* hovered; - - ui_box* focus; - i32 editCursor; - i32 editMark; - i32 editFirstDisplayedChar; - f64 editCursorBlinkStart; - -} ui_context; mp_thread_local ui_context __uiThreadContext = {0}; mp_thread_local ui_context* __uiCurrentContext = 0; @@ -388,6 +323,37 @@ void ui_style_box_after(ui_box* box, ui_pattern pattern, ui_style* style, ui_sty } } +//----------------------------------------------------------------------------- +// input +//----------------------------------------------------------------------------- + +void ui_process_event(mp_event event) +{ + ui_context* ui = ui_get_context(); + mp_input_process_event(&ui->input, event); +} + +vec2 ui_mouse_position(void) +{ + ui_context* ui = ui_get_context(); + vec2 mousePos = mp_mouse_position(&ui->input); + return(mousePos); +} + +vec2 ui_mouse_delta(void) +{ + ui_context* ui = ui_get_context(); + vec2 delta = mp_mouse_delta(&ui->input); + return(delta); +} + +vec2 ui_mouse_wheel(void) +{ + ui_context* ui = ui_get_context(); + vec2 delta = mp_mouse_wheel(&ui->input); + return(delta); +} + //----------------------------------------------------------------------------- // ui boxes //----------------------------------------------------------------------------- @@ -411,26 +377,6 @@ bool ui_box_hovering(ui_box* box, vec2 p) return(result); } -vec2 ui_mouse_position(void) -{ - vec2 mousePos = mp_mouse_position(); - return(mousePos); -} - -vec2 ui_mouse_delta(void) -{ - ui_context* ui = ui_get_context(); - vec2 delta = mp_mouse_delta(); - return(delta); -} - -vec2 ui_mouse_wheel(void) -{ - ui_context* ui = ui_get_context(); - vec2 delta = mp_mouse_wheel(); - return(delta); -} - ui_box* ui_box_make_str8(str8 string, ui_flags flags) { ui_context* ui = ui_get_context(); @@ -569,6 +515,9 @@ ui_sig ui_box_sig(ui_box* box) //NOTE: compute input signals ui_sig sig = {0}; + ui_context* ui = ui_get_context(); + mp_input_state* input = &ui->input; + sig.box = box; if(!box->closed && !box->parentClosed) @@ -581,16 +530,16 @@ ui_sig ui_box_sig(ui_box* box) { if(sig.hovering) { - sig.pressed = mp_mouse_pressed(MP_MOUSE_LEFT); + sig.pressed = mp_mouse_pressed(input, MP_MOUSE_LEFT); if(sig.pressed) { box->dragging = true; } - sig.doubleClicked = mp_mouse_double_clicked(MP_MOUSE_LEFT); - sig.rightPressed = mp_mouse_pressed(MP_MOUSE_RIGHT); + sig.doubleClicked = mp_mouse_double_clicked(input, MP_MOUSE_LEFT); + sig.rightPressed = mp_mouse_pressed(input, MP_MOUSE_RIGHT); } - sig.released = mp_mouse_released(MP_MOUSE_LEFT); + sig.released = mp_mouse_released(input, MP_MOUSE_LEFT); if(sig.released) { if(box->dragging && sig.hovering) @@ -599,7 +548,7 @@ ui_sig ui_box_sig(ui_box* box) } } - if(!mp_mouse_down(MP_MOUSE_LEFT)) + if(!mp_mouse_down(input, MP_MOUSE_LEFT)) { box->dragging = false; } @@ -1513,23 +1462,23 @@ void ui_end_frame(void) } } } + + mp_input_next_frame(&ui->input); } //----------------------------------------------------------------------------- // Init / cleanup //----------------------------------------------------------------------------- -void ui_init(void) +void ui_init(ui_context* ui) { - ui_context* ui = &__uiThreadContext; - if(!ui->init) - { - __uiCurrentContext = &__uiThreadContext; + __uiCurrentContext = &__uiThreadContext; - memset(ui, 0, sizeof(ui_context)); - mem_arena_init(&ui->frameArena); - mem_pool_init(&ui->boxPool, sizeof(ui_box)); - ui->init = true; - } + memset(ui, 0, sizeof(ui_context)); + mem_arena_init(&ui->frameArena); + mem_pool_init(&ui->boxPool, sizeof(ui_box)); + ui->init = true; + + ui_set_context(ui); } void ui_cleanup(void) @@ -1985,7 +1934,8 @@ void ui_menu_bar_begin(const char* name) ui_box* bar = ui_box_begin(name, UI_FLAG_DRAW_BACKGROUND); ui_sig sig = ui_box_sig(bar); - if(!sig.hovering && mp_mouse_released(MP_MOUSE_LEFT)) + ui_context* ui = ui_get_context(); + if(!sig.hovering && mp_mouse_released(&ui->input, MP_MOUSE_LEFT)) { ui_box_deactivate(bar); } @@ -2247,7 +2197,8 @@ ui_select_popup_info ui_select_popup(const char* name, ui_select_popup_info* inf } ui_box_pop(); - if(ui_box_active(panel) && mp_mouse_pressed(MP_MOUSE_LEFT)) + ui_context* ui = ui_get_context(); + if(ui_box_active(panel) && mp_mouse_pressed(&ui->input, MP_MOUSE_LEFT)) { ui_box_deactivate(panel); } @@ -2753,7 +2704,7 @@ ui_text_box_result ui_text_box(const char* name, mem_arena* arena, str8 text) } //NOTE: set the new cursor, and set or leave the mark depending on mode ui->editCursor = newCursor; - if(sig.pressed && !(mp_key_mods() & MP_KEYMOD_SHIFT)) + if(sig.pressed && !(mp_key_mods(&ui->input) & MP_KEYMOD_SHIFT)) { ui->editMark = ui->editCursor; } @@ -2783,7 +2734,7 @@ ui_text_box_result ui_text_box(const char* name, mem_arena* arena, str8 text) ui->editMark = Clamp(ui->editMark, 0, codepoints.len); //NOTE replace selection with input codepoints - str32 input = mp_input_text_utf32(&ui->frameArena); + str32 input = mp_input_text_utf32(&ui->input, &ui->frameArena); if(input.len) { codepoints = ui_edit_replace_selection_with_codepoints(ui, codepoints, input); @@ -2791,13 +2742,13 @@ ui_text_box_result ui_text_box(const char* name, mem_arena* arena, str8 text) } //NOTE handle shortcuts - mp_keymod_flags mods = mp_key_mods(); + mp_keymod_flags mods = mp_key_mods(&ui->input); for(int i=0; ikey) || mp_key_repeated(command->key)) + if( (mp_key_pressed(&ui->input, command->key) || mp_key_repeated(&ui->input, command->key)) && mods == command->mods) { codepoints = ui_edit_perform_operation(ui, command->operation, command->move, command->direction, codepoints); @@ -2812,7 +2763,7 @@ ui_text_box_result ui_text_box(const char* name, mem_arena* arena, str8 text) result.text = utf8_push_from_codepoints(arena, codepoints); } - if(mp_key_pressed(MP_KEY_ENTER)) + if(mp_key_pressed(&ui->input, MP_KEY_ENTER)) { //TODO(martin): extract in gui_edit_complete() (and use below) result.accepted = true; diff --git a/src/ui.h b/src/ui.h index feb7d33..a32d77b 100644 --- a/src/ui.h +++ b/src/ui.h @@ -11,6 +11,7 @@ #include"typedefs.h" #include"lists.h" +#include"input_state.h" #include"graphics.h" #ifdef __cplusplus @@ -319,15 +320,82 @@ struct ui_box f32 activeTransition; }; -typedef struct ui_context ui_context; +//----------------------------------------------------------------------------- +// context +//----------------------------------------------------------------------------- + +enum { UI_MAX_INPUT_CHAR_PER_FRAME = 64 }; + +typedef struct ui_input_text +{ + u8 count; + utf32 codePoints[UI_MAX_INPUT_CHAR_PER_FRAME]; + +} ui_input_text; + +typedef struct ui_stack_elt ui_stack_elt; +struct ui_stack_elt +{ + ui_stack_elt* parent; + union + { + ui_box* box; + ui_size size; + mp_rect clip; + }; +}; + +typedef struct ui_tag_elt +{ + list_elt listElt; + ui_tag tag; +} ui_tag_elt; + +enum { UI_BOX_MAP_BUCKET_COUNT = 1024 }; + +typedef struct ui_context +{ + bool init; + + mp_input_state input; + + u64 frameCounter; + f64 frameTime; + f64 lastFrameDuration; + + mem_arena frameArena; + mem_pool boxPool; + list_info boxMap[UI_BOX_MAP_BUCKET_COUNT]; + + ui_box* root; + ui_box* overlay; + list_info overlayList; + ui_stack_elt* boxStack; + ui_stack_elt* clipStack; + + list_info nextBoxBeforeRules; + list_info nextBoxAfterRules; + list_info nextBoxTags; + + u32 z; + ui_box* hovered; + + ui_box* focus; + i32 editCursor; + i32 editMark; + i32 editFirstDisplayedChar; + f64 editCursorBlinkStart; + +} ui_context; //------------------------------------------------------------------------------------- // UI context initialization and frame cycle //------------------------------------------------------------------------------------- -MP_API void ui_init(void); +MP_API void ui_init(ui_context* context); MP_API ui_context* ui_get_context(void); MP_API void ui_set_context(ui_context* context); +MP_API void ui_process_event(mp_event event); MP_API void ui_begin_frame(ui_style* defaultStyle, ui_style_mask mask); MP_API void ui_end_frame(void); MP_API void ui_draw(void);