diff --git a/src/UserInterface.c b/src/UserInterface.c index 966aafc..8a37a9a 100644 --- a/src/UserInterface.c +++ b/src/UserInterface.c @@ -4,6 +4,40 @@ #include "Dengine/Renderer.h" #include "Dengine/Debug.h" +i32 userInterface_window(UiState *const uiState, + MemoryArena *const arena, + AssetManager *const assetManager, + Renderer *const renderer, + Font *const font, + const KeyInput input, + const i32 id, const Rect rect, const char *const title) +{ + if (math_pointInRect(rect, input.mouseP)) + { + uiState->hotItem = id; + if (uiState->activeItem == 0 && input.keys[keycode_mouseLeft].endedDown) + uiState->activeItem = id; + } + + RenderTex nullRenderTex = renderer_createNullRenderTex(assetManager); + renderer_staticRect(renderer, rect.pos, rect.size, V2(0, 0), 0, + nullRenderTex, V4(0.25f, 0.25f, 0.5f, 1.0f)); + + char *menuTitle = "Stat Menu"; + v2 menuTitleP = v2_add(rect.pos, V2(0, rect.size.h - 10)); + renderer_staticString(renderer, arena, font, menuTitle, menuTitleP, + V2(0, 0), 0, V4(0, 0, 0, 1)); + + if (input.keys[keycode_mouseLeft].endedDown && + uiState->hotItem == id && + uiState->activeItem == id) + { + return 1; + } + + return 0; +} + i32 userInterface_button(UiState *const uiState, MemoryArena *const arena, AssetManager *const assetManager, @@ -107,6 +141,8 @@ i32 userInterface_button(UiState *const uiState, uiState->lastWidget = id; + // If button is hot and active, but mouse button is not + // down, the user must have clicked the button. if (!input.keys[keycode_mouseLeft].endedDown && uiState->hotItem == id && uiState->activeItem == id) @@ -238,6 +274,7 @@ i32 userInterface_textField(UiState *const uiState, MemoryArena *const arena, Rect textRect = {0}; textRect.pos = pos; textRect.size = V2(30 * font->maxSize.w, font->maxSize.h); + if (math_pointInRect(textRect, input.mouseP)) { uiState->hotItem = id; diff --git a/src/WorldTraveller.c b/src/WorldTraveller.c index 289b2af..2b38718 100644 --- a/src/WorldTraveller.c +++ b/src/WorldTraveller.c @@ -523,6 +523,12 @@ INTERNAL void parseInput(GameState *state, const f32 dt) state->uiState.keyChar = keycode_space; } + if (getKeyStatus(&keys[keycode_i], readkeytype_delayedRepeat, 0.25f, + dt)) + { + state->uiState.keyChar = keycode_i; + } + if (getKeyStatus(&keys[keycode_backspace], readkeytype_delayedRepeat, 0.1f, dt)) { @@ -1014,8 +1020,9 @@ typedef struct BattleState DamageDisplay damageDisplay[128]; } BattleState; -BattleState battleState = {0}; +GLOBAL_VAR BattleState battleState = {0}; +v2 lastFrameP = {0, 0}; void worldTraveller_gameUpdateAndRender(GameState *state, f32 dt) { if (dt >= 1.0f) dt = 1.0f; @@ -1332,6 +1339,56 @@ void worldTraveller_gameUpdateAndRender(GameState *state, f32 dt) (state->config.showDebugDisplay == TRUE) ? FALSE : TRUE; } + LOCAL_PERSIST toggleShowingStatMenu = FALSE; + if (state->uiState.keyChar == keycode_i) + { + toggleShowingStatMenu = + (toggleShowingStatMenu == TRUE) ? FALSE : TRUE; + } + + if (toggleShowingStatMenu) + { + i32 statMenuID = 99; + + // TODO(doyle): Define pushing/placing text within a coordinate system, + // i.e. relative to an elements position + char *menuTitle = "Stat Menu"; + + LOCAL_PERSIST Rect inventoryRect = {{300, 400}, {300, 400}}; + LOCAL_PERSIST lastFrameWindowWasHeld = FALSE; + + b32 windowClickedAndHeld = userInterface_window( + &state->uiState, &state->arena, assetManager, renderer, font, + state->input, statMenuID, inventoryRect, menuTitle); + + if (windowClickedAndHeld) + { + if (lastFrameWindowWasHeld) + { + // NOTE(doyle): Window clicked and held + v2 deltaP = v2_sub(state->input.mouseP, lastFrameP); + DEBUG_PUSH_VAR("Delta Pos %4.2f, %4.2f", deltaP, "v2"); + + f32 mouseMoveThreshold = 5.0f; + + if (ABS(deltaP.x) <= mouseMoveThreshold) deltaP.x = 0.0f; + if (ABS(deltaP.y) <= mouseMoveThreshold) deltaP.y = 0.0f; + + inventoryRect.pos = v2_add(deltaP, inventoryRect.pos); + } + else + { + lastFrameWindowWasHeld = TRUE; + } + + lastFrameP = state->input.mouseP; + } + else + { + lastFrameWindowWasHeld = FALSE; + } + } + LOCAL_PERSIST i32 scrollValue = 30; Rect scrollRectA = {V2(1500, 600), V2(16, 255)}; userInterface_scrollBar(&state->uiState, assetManager, renderer, diff --git a/src/include/Dengine/Renderer.h b/src/include/Dengine/Renderer.h index c7c3080..e81b0bc 100644 --- a/src/include/Dengine/Renderer.h +++ b/src/include/Dengine/Renderer.h @@ -28,6 +28,7 @@ typedef struct RenderTex v4 texRect; } RenderTex; +// TODO(doyle): Use z-index occluding for rendering RenderTex renderer_createNullRenderTex(AssetManager *const assetManager); // TODO(doyle): Clean up lines diff --git a/src/include/Dengine/UserInterface.h b/src/include/Dengine/UserInterface.h index f80541b..2ac9a0d 100644 --- a/src/include/Dengine/UserInterface.h +++ b/src/include/Dengine/UserInterface.h @@ -42,6 +42,12 @@ typedef struct UiState enum KeyCode keyChar; } UiState; +i32 userInterface_window(UiState *const uiState, MemoryArena *const arena, + AssetManager *const assetManager, + Renderer *const renderer, Font *const font, + const KeyInput input, const i32 id, const Rect rect, + const char *const title); + i32 userInterface_button(UiState *const uiState, MemoryArena *const arena, AssetManager *const assetManager,