From cef1a458471d44e2112cd5aa567ba719192c2f20 Mon Sep 17 00:00:00 2001 From: Klemen Plestenjak Date: Thu, 28 Dec 2023 08:32:09 +0100 Subject: [PATCH] Add settings menu --- game/game_tileset.h | 4 ++ game/main.c | 63 ++++++++++++++++++++++--- game/ui_widgets.c | 112 +++++++++++++++++++++++++++++++++++++++++++- game/ui_widgets.h | 7 +++ 4 files changed, 179 insertions(+), 7 deletions(-) diff --git a/game/game_tileset.h b/game/game_tileset.h index 65e0045..1d9a265 100644 --- a/game/game_tileset.h +++ b/game/game_tileset.h @@ -314,6 +314,10 @@ static BuildingType getBuildingSize(BuildingType type, BzTileID *outWidth, BzTil typedef enum EntityType { ENTITY_WORKER, + ENTITY_WOOD, + ENTITY_STONE, + ENTITY_GOLD, + ENTITY_POP, ENTITY_COUNT, ENTITY_NONE, } EntityType; diff --git a/game/main.c b/game/main.c index d577d6d..47e84c6 100644 --- a/game/main.c +++ b/game/main.c @@ -311,6 +311,8 @@ static void renderMainMenu(Game *game, float dt) { i32 width = GetScreenWidth(); i32 height = GetScreenHeight(); + game->camera.zoom = 3 * uiGetScale(); + bzUIBegin(UI, width, height); bzUISetParentLayout(UI, (BzUILayout) { .type = BZ_UI_LAYOUT_FLEX_BOX, @@ -345,11 +347,66 @@ static void renderMainMenu(Game *game, float dt) { } static void renderSettings(Game *game, float dt) { + i32 width = GetScreenWidth(); + i32 height = GetScreenHeight(); + + game->camera.zoom = 3 * uiGetScale(); + + bzUIBegin(UI, width, height); + bzUISetParentLayout(UI, (BzUILayout) { + .type = BZ_UI_LAYOUT_FLEX_BOX, + .flags = BZ_UI_FLEX_DIR_COLUMN | BZ_UI_FLEX_JUSTIFY_CENTER | BZ_UI_FLEX_ALIGN_CENTER + }); + + bzUIPushDiv(UI, (BzUISize) { BZ_UI_SIZE_REL_PARENT, 0.8f}, + (BzUISize) { BZ_UI_SIZE_REL_PARENT, 0.8f}); + bzUISetParentLayout(UI, (BzUILayout) { + .type = BZ_UI_LAYOUT_FLEX_BOX, + .flags = BZ_UI_FLEX_DIR_COLUMN | BZ_UI_FLEX_JUSTIFY_CENTER | BZ_UI_FLEX_ALIGN_CENTER + }); + static bool fullscreen = false; + static bool vsync = false; + uiSettingsLabel("Video"); + uiSettingsCheckbox("Fullscreen", &fullscreen); + uiSettingsCheckbox("V-Sync", &vsync); + + static f32 master = 50.0f; + static f32 music = 50.0f; + static f32 sound = 50.0f; + uiSettingsLabel("Audio"); + uiSettingsSlider("Master: ", &master); + uiSettingsSlider("Music: ", &music); + uiSettingsSlider("Sound: ", &sound); + + bzUIPopParent(UI); + bzUIPushDiv(UI, (BzUISize) {BZ_UI_SIZE_REL_PARENT, 0.8f}, + (BzUISize) {BZ_UI_SIZE_REL_PARENT, 0.2f}); + bzUISetParentLayout(UI, (BzUILayout) { + .type = BZ_UI_LAYOUT_FLEX_BOX, + .flags = BZ_UI_FLEX_DIR_ROW | BZ_UI_FLEX_JUSTIFY_CENTER | BZ_UI_FLEX_ALIGN_CENTER + }); + + if (uiSettingsButton("Back")) { + game->screen = SCREEN_MAIN_MENU; + } + if (uiSettingsButton("Reset")) { + + } + if (uiSettingsButton("Apply")) { + game->screen = SCREEN_MAIN_MENU; + } + + bzUIEnd(UI); } void render(float dt, void *userData) { BZ_UNUSED(userData); Game *game = ecs_singleton_get_mut(ECS, Game); + const InputState *input = ecs_singleton_get(ECS, InputState);; + + if (IsKeyReleased(input->mapping.backBtn)) { + game->screen = SCREEN_MAIN_MENU; + } Color shadow = BLACK; shadow.a = 35; @@ -378,14 +435,8 @@ void imguiRender(float dt, void *userData) { Game *game = ecs_singleton_get_mut(ECS, Game); InputState *input = ecs_singleton_get_mut(ECS, InputState); - if (game->screen != SCREEN_GAME) return; - igSetNextWindowSize((ImVec2){300, 400}, ImGuiCond_FirstUseEver); igBegin("Debug Menu", NULL, 0); - if (igSmallButton("Recruit worker [50 food]")) { - createWorker((Position) {1100, 400}, (Size) {10, 10}, game->entityGrid, - &game->map.tilesets[2], 1322); - } igText("PathData pool available: %llu", bzObjectPoolGetNumFree(game->pools.pathData)); igText("Action pool available: %llu", bzObjectPoolGetNumFree(game->pools.actions)); const char *inputState = "NONE"; diff --git a/game/ui_widgets.c b/game/ui_widgets.c index 61d2f18..a054edf 100644 --- a/game/ui_widgets.c +++ b/game/ui_widgets.c @@ -2,6 +2,8 @@ #include "game_state.h" +#include + f32 uiGetScale() { return GetScreenHeight() / 720.0f; } @@ -62,7 +64,7 @@ bool uiBaseTextButton(const char *txt, Font font, f32 scl) { .semanticSize[BZ_UI_AXIS_Y] = { .kind = BZ_UI_SIZE_FIT }, - .padding = {0, 0, 0, 0}, + .padding = {5, 0, 5, 0}, .margin = {5, 5, 5, 5}, }); bzUISetTextStyle(UI, node, (BzUITextStyle) { @@ -83,6 +85,101 @@ bool uiBaseTextButton(const char *txt, Font font, f32 scl) { }); return bzUIGetInteraction(UI, node).clicked; } +void uiBaseCheckbox(const char *txt, Font font, f32 scl, bool *check) { + BZ_ASSERT(check); + bzUIPushDiv(UI, (BzUISize) {BZ_UI_SIZE_CHILD_SUM}, (BzUISize) {BZ_UI_SIZE_CHILD_MAX}); + bzUISetParentLayout(UI, (BzUILayout) { + BZ_UI_LAYOUT_FLEX_BOX, + BZ_UI_FLEX_DIR_ROW | BZ_UI_FLEX_ALIGN_CENTER | BZ_UI_FLEX_JUSTIFY_START + }); + + f32 size = 16 * uiGetScale() * scl; + BzUINode *checkbox = bzUINodeMake(UI, bzUIGetUniqueKey(UI), &(BzUINodeDesc) { + .flags = BZ_UI_CLICKABLE | BZ_UI_DRAW_BACKGROUND | BZ_UI_DRAW_BORDER, + .semanticSize[BZ_UI_AXIS_X] = (BzUISize) { BZ_UI_SIZE_PIXELS, size}, + .semanticSize[BZ_UI_AXIS_Y] = (BzUISize) { BZ_UI_SIZE_PIXELS, size}, + .margin = {0, 0, 10 * uiGetScale() * scl, 0 } + }); + bzUISetBackgroundStyle(UI, checkbox, (BzUIBackgroundStyle) { + .normal = *check ? WHITE : BLACK, + .hover = GRAY, + .active = YELLOW, + }); + bzUISetBorderStyle(UI, checkbox, (BzUIBorderStyle) { + .thickness = 5.0f * uiGetScale() * scl, + .normal = BLACK, + .hover = BLACK, + .active = BLACK, + }); + + if (bzUIGetInteraction(UI, checkbox).clicked) { + *check = !*check; + } + + BzUINode *label = bzUINodeMake(UI, bzUIKeyFromString(txt), &(BzUINodeDesc) { + .flags = BZ_UI_DRAW_TEXT | BZ_UI_DRAW_TEXT_SHADOW | BZ_UI_ALIGN_CENTER, + .semanticSize[BZ_UI_AXIS_X] = { + .kind = BZ_UI_SIZE_FIT, + }, + .semanticSize[BZ_UI_AXIS_Y] = { + .kind = BZ_UI_SIZE_FIT + }, + }); + bzUISetTextStyle(UI, label, (BzUITextStyle) { + .text = txt, + .font = font, + .fontSpacing = 2 * uiGetScale() * scl, + .fontSize = 32 * uiGetScale() * scl, + .normal = WHITE, + .hover = GRAY, + .active = YELLOW + }); + bzUISetTextShadowStyle(UI, label, (BzUITextShadowStyle) { + .offset[BZ_UI_AXIS_X] = 2 * uiGetScale() * scl, + .offset[BZ_UI_AXIS_Y] = 2 * uiGetScale() * scl, + .normal = BLACK, + .hover = BLACK, + .active = BLACK, + }); + if (bzUIGetInteraction(UI, label).clicked) { + *check = !*check; + } + + bzUIPopParent(UI); +} +void uiBaseSlider(const char *txt, Font font, f32 scl, f32 *value, f32 min, f32 max) { + BZ_ASSERT(value); + bzUIPushDiv(UI, (BzUISize) {BZ_UI_SIZE_CHILD_SUM}, (BzUISize) {BZ_UI_SIZE_CHILD_MAX}); + bzUISetParentLayout(UI, (BzUILayout) { + BZ_UI_LAYOUT_FLEX_BOX, + BZ_UI_FLEX_DIR_ROW | BZ_UI_FLEX_ALIGN_CENTER | BZ_UI_FLEX_JUSTIFY_SPACE_BETWEEN + }); + + uiBaseLabel(txt, font, 0.6 * scl); + + bzUIPushDiv(UI, (BzUISize) {BZ_UI_SIZE_CHILD_SUM}, (BzUISize) { BZ_UI_SIZE_CHILD_MAX}); + bzUISetParentLayout(UI, (BzUILayout) { + BZ_UI_LAYOUT_FLEX_BOX, + BZ_UI_FLEX_DIR_ROW | BZ_UI_FLEX_ALIGN_CENTER | BZ_UI_FLEX_JUSTIFY_END + }); + + char buf[32]; + snprintf(buf, sizeof(buf), "-##%s", txt); + if (uiBaseTextButton(buf, font, 0.6 * scl)) + (*value)--; + *value = BZ_MAX(*value, min); + + snprintf(buf, sizeof(buf), "%2.0f##%s", *value, txt); + uiBaseLabel(buf, font, 0.6 * scl); + + snprintf(buf, sizeof(buf), "+##%s", txt); + if (uiBaseTextButton(buf, font, 0.6 * scl)) + (*value)++; + *value = BZ_MIN(*value, max); + bzUIPopParent(UI); + + bzUIPopParent(UI); +} void uiMainMenuLabel(const char *txt) { uiBaseLabel(txt, getFont(), 1.8f); @@ -91,3 +188,16 @@ void uiMainMenuLabel(const char *txt) { bool uiMainMenuButton(const char *txt) { return uiBaseTextButton(txt, getFont(), 0.8f); } + +void uiSettingsLabel(const char *txt) { + uiBaseLabel(txt, getFont(), 0.8f); +} +bool uiSettingsButton(const char *txt) { + return uiBaseTextButton(txt, getFont(), 0.7f); +} +void uiSettingsCheckbox(const char *txt, bool *check) { + uiBaseCheckbox(txt, getFont(), 1.0f, check); +} +void uiSettingsSlider(const char *txt, f32 *value) { + uiBaseSlider(txt, getFont(), 1.0f, value, 0, 10); +} diff --git a/game/ui_widgets.h b/game/ui_widgets.h index 8fa69ea..7d03e06 100644 --- a/game/ui_widgets.h +++ b/game/ui_widgets.h @@ -13,9 +13,16 @@ void uiPushDivParentPercentage(f32 xPercent, f32 yPercent); // Template stuff void uiBaseLabel(const char *txt, Font font, f32 scl); bool uiBaseTextButton(const char *txt, Font font, f32 scl); +void uiBaseCheckbox(const char *txt, Font font, f32 scl, bool *check); +void uiBaseSlider(const char *txt, Font font, f32 scl, f32 *value, f32 min, f32 max); // actual UI void uiMainMenuLabel(const char *txt); bool uiMainMenuButton(const char *txt); +void uiSettingsLabel(const char *txt); +bool uiSettingsButton(const char *txt); +void uiSettingsCheckbox(const char *txt, bool *check); +void uiSettingsSlider(const char *txt, f32 *value); + #endif //PIXELDEFENSE_UI_WIDGETS_H