diff --git a/game/systems/s_ui.c b/game/systems/s_ui.c index a3cb9bf..c23fd79 100644 --- a/game/systems/s_ui.c +++ b/game/systems/s_ui.c @@ -203,7 +203,10 @@ void drawGameUI(Game *game, f32 dt) { bool selected = false; bool canAfford = canAffordEntity(slot->entityType, *playerRes); canAfford &= playerRes->pop < playerRes->popCapacity; - uiGameBuild(label, rec, tex, canAfford, &selected); + f32 progress = slot->elapsed / slot->recruitTime; + if (slot->numRecruiting <= 0) progress = -1.0f; + uiGameRecruit(label, rec, tex, slot->numRecruiting, progress, + canAfford, &selected); if (selected) { i32 res[RES_COUNT] = {0,}; getEntityCost(slot->entityType, res); diff --git a/game/ui_widgets.c b/game/ui_widgets.c index 29bc5cb..c60244f 100644 --- a/game/ui_widgets.c +++ b/game/ui_widgets.c @@ -247,6 +247,104 @@ void uiGameResCount(i32 amount, i32 capacity, Rectangle icon, Texture2D texture) bzUIPopParent(UI); } +void uiGameRecruit(const char *label, Rectangle rec, Texture2D tex, i32 numRecruiting, + f32 progress, bool canAfford, bool *selected) { + f32 scl = uiGetScale(); + BzUINode *btn = bzUINodeMake(UI, bzUIKeyFromString(label), &(BzUINodeDesc) { + .flags = BZ_UI_CLICKABLE | BZ_UI_ALIGN_CENTER | BZ_UI_DRAW_BORDER, + .margin[BZ_UI_AXIS_X] = 10.0f * scl, + .margin[BZ_UI_AXIS_Y] = 10.0f * scl, + .margin[BZ_UI_AXIS_Y * 2] = 10.0f * scl, + .semanticSize[BZ_UI_AXIS_X] = {BZ_UI_SIZE_CHILD_MAX}, + .semanticSize[BZ_UI_AXIS_Y] = {BZ_UI_SIZE_CHILD_SUM}, + }); + if (rec.height > 16) + rec.y += 16; + rec.height = rec.width; + + BzUIInteraction inter = bzUIGetInteraction(UI, btn); + + Color bgColor = canAfford ? DARKBROWN : MAROON; + if (*selected || inter.hovering) + bgColor = canAfford ? BROWN : RED; + if (inter.clicked && canAfford) + *selected = true; + + bzUISetBackgroundStyle(UI, btn, (BzUIBackgroundStyle) { + .roundness = 0.2f, + .active = bgColor, + .normal = bgColor, + .hover = bgColor, + }); + bzUISetBorderStyle(UI, btn, (BzUIBorderStyle) { + .roundness = 0.2f, + .thickness = 5.0f * scl, + .normal = BLACK, + .hover = BLACK, + .active = BLACK, + }); + bzUIPushParent(UI, btn); + bzUISetParentLayout(UI, (BzUILayout) { + .type = BZ_UI_LAYOUT_FLEX_BOX, + .flags = BZ_UI_FLEX_DIR_COLUMN | BZ_UI_FLEX_ALIGN_CENTER | BZ_UI_FLEX_JUSTIFY_START + }); + + BzUINode *tileSprite = bzUINodeMake(UI, bzUIGetUniqueKey(UI), &(BzUINodeDesc) { + .flags = BZ_UI_DRAW_SPRITE, + .semanticSize[BZ_UI_AXIS_X] = {BZ_UI_SIZE_PIXELS, rec.width * 5 * scl}, + .semanticSize[BZ_UI_AXIS_Y] = {BZ_UI_SIZE_PIXELS, rec.height * 5 * scl}, + }); + bzUISetSpriteStyle(UI, tileSprite, (BzUISpriteStyle) { + .texture = tex, + .rec = rec, + .tintNormal = WHITE, + .tintHover = WHITE, + .tintActive = WHITE, + }); + + char text[128]; + if (numRecruiting > 0) { + snprintf(text, sizeof(text), "%dx %s", numRecruiting, label); + } else { + snprintf(text, sizeof(text), "%s", label); + } + + BzUINode *labelDisplay = bzUINodeMake(UI, bzUIGetUniqueKey(UI), &(BzUINodeDesc) { + .flags = BZ_UI_DRAW_TEXT | BZ_UI_DRAW_TEXT_SHADOW, + .semanticSize[BZ_UI_AXIS_X] = {BZ_UI_SIZE_FIT}, + .semanticSize[BZ_UI_AXIS_Y] = {BZ_UI_SIZE_FIT}, + }); + bzUISetTextStyle(UI, labelDisplay, (BzUITextStyle) { + .font = getFont(), + .fontSize = 25.0f * scl, + .fontSpacing = 1.0f * scl, + .normal = WHITE, + .hover = WHITE, + .active = WHITE, + .text = text + }); + bzUISetTextShadowStyle(UI, labelDisplay, (BzUITextShadowStyle) { + .offset = {1.0f * scl, 1.0f * scl}, + .normal = BLACK, + .hover = BLACK, + .active = BLACK + }); + + if (progress > 0.0f) { + BzUINode *progressBar = bzUINodeMake(UI, bzUIGetUniqueKey(UI), &(BzUINodeDesc) { + .flags = BZ_UI_DRAW_BACKGROUND | BZ_UI_ALIGN_HORIZ_START, + .semanticSize[BZ_UI_AXIS_X] = {BZ_UI_SIZE_REL_PARENT, progress * 0.8f}, + .semanticSize[BZ_UI_AXIS_Y] = {BZ_UI_SIZE_PIXELS, scl * 4} + }); + bzUISetBackgroundStyle(UI, progressBar, (BzUIBackgroundStyle) { + .active = GREEN, + .hover = GREEN, + .normal = GREEN, + }); + } + + bzUIPopParent(UI); +} void uiGameBuild(const char *label, Rectangle rec, Texture2D tex, bool canAfford, bool *selected) { f32 scl = uiGetScale(); BzUINode *btn = bzUINodeMake(UI, bzUIKeyFromString(label), &(BzUINodeDesc) { @@ -322,7 +420,6 @@ void uiGameBuild(const char *label, Rectangle rec, Texture2D tex, bool canAfford .active = BLACK }); - bzUIPopParent(UI); } bool uiGameUnit(const char *label, i32 count, Rectangle rec, Texture2D tex) { diff --git a/game/ui_widgets.h b/game/ui_widgets.h index da710b9..dab644b 100644 --- a/game/ui_widgets.h +++ b/game/ui_widgets.h @@ -27,6 +27,8 @@ void uiSettingsSlider(const char *txt, f32 *value); void uiGameResCount(i32 amount, i32 capacity, Rectangle icon, Texture2D texture); +void uiGameRecruit(const char *label, Rectangle rec, Texture2D tex, i32 numRecruiting, + f32 progress, bool canAfford, bool *selected); void uiGameBuild(const char *label, Rectangle rec, Texture2D tex, bool canAfford, bool *selected); bool uiGameUnit(const char *label, i32 count, Rectangle rec, Texture2D tex);