Files
PixelDefense/game/systems/s_ui.c
2024-01-23 20:31:23 +01:00

309 lines
11 KiB
C

#include "systems.h"
#include "../game_state.h"
#include "../input.h"
#include "../map_init.h"
#include "../ui_widgets.h"
#include "../buildings.h"
void drawGameUI(Game *game, f32 dt) {
// UI
i32 width = GetScreenWidth();
i32 height = GetScreenHeight();
bzUIBegin(UI, width, height);
bzUISetParentLayout(UI, (BzUILayout) {
.type = BZ_UI_LAYOUT_FLEX_BOX,
.flags = BZ_UI_FLEX_DIR_COLUMN |
BZ_UI_FLEX_JUSTIFY_SPACE_BETWEEN |
BZ_UI_FLEX_ALIGN_CENTER
});
// top bar
BzUINode *topBar = bzUINodeMake(UI, bzUIGetUniqueKey(UI), &(BzUINodeDesc) {
.semanticSize[BZ_UI_AXIS_X] = {BZ_UI_SIZE_AS_PARENT},
.semanticSize[BZ_UI_AXIS_Y] = {BZ_UI_SIZE_CHILD_MAX},
});
bzUIPushParent(UI, topBar);
bzUISetParentLayout(UI, (BzUILayout) {
.type = BZ_UI_LAYOUT_FLEX_BOX,
.flags = BZ_UI_FLEX_DIR_ROW |
BZ_UI_FLEX_ALIGN_CENTER |
BZ_UI_FLEX_JUSTIFY_START
});
Color topBarBG = {0, 0, 0, 50};
bzUISetBackgroundStyle(UI, topBar, (BzUIBackgroundStyle) {
.normal = topBarBG,
.hover = topBarBG,
.active = topBarBG,
});
BzTileset *tileset = &game->tileset;
Rectangle woodRec = bzTilesetGetTileRegion(tileset, getEntityTile(ENTITY_WOOD));
Rectangle foodRec = bzTilesetGetTileRegion(tileset, getEntityTile(ENTITY_APPLE));
Rectangle goldRec = bzTilesetGetTileRegion(tileset, getEntityTile(ENTITY_GOLD));
Rectangle popRec = bzTilesetGetTileRegion(tileset, getEntityTile(ENTITY_POP));
PlayerResources resources = game->playerResources[game->player];
uiGameResCount(resources.wood, -1, woodRec, tileset->tiles);
uiGameResCount(resources.food, -1, foodRec, tileset->tiles);
uiGameResCount(resources.gold, -1, goldRec, tileset->tiles);
uiGameResCount(resources.pop, resources.popCapacity, popRec, tileset->tiles);
bzUIPopParent(UI);
InputState *input = ecs_singleton_get_mut(ECS, InputState);
const BuildingType buildingOrder[] = {
BUILDING_HOUSE_01,
BUILDING_GRANARY,
BUILDING_WAREHOUSE,
BUILDING_MARKET,
BUILDING_MILL,
BUILDING_HOUSE_02, // placeholder for farm
BUILDING_BARRACKS,
BUILDING_ARCHERY_RANGE
};
const char *buildingNames[] = {
"House",
"Granary",
"Warehouse",
"Market",
"Mill",
"Farm",
"Barracks",
"Archery Range"
};
i32 numBuildings = sizeof(buildingOrder) / sizeof(*buildingOrder);
BzUINode *menu = bzUINodeMake(UI, bzUIGetUniqueKey(UI), &(BzUINodeDesc) {
.semanticSize[BZ_UI_AXIS_X] = {BZ_UI_SIZE_REL_PARENT, 0.98f},
.semanticSize[BZ_UI_AXIS_Y] = {BZ_UI_SIZE_PIXELS, 140.0f * uiGetScale()},
.margin[BZ_UI_AXIS_Y + 2] = 10.0f * uiGetScale(),
});
bzUISetBackgroundStyle(UI, menu, (BzUIBackgroundStyle) {
.normal = DARKBROWN,
.hover = DARKBROWN,
.active = DARKBROWN,
.roundness = 0.2f * uiGetScale()
});
bzUISetBorderStyle(UI, menu, (BzUIBorderStyle) {
.roundness = 0.2f * uiGetScale(),
.thickness = 6.0f * uiGetScale(),
.normal = BLACK,
.hover = BLACK,
.active = BLACK,
});
bzUIPushParent(UI, menu);
bzUISetParentLayout(UI, (BzUILayout) {
.type = BZ_UI_LAYOUT_FLEX_BOX,
.flags = BZ_UI_FLEX_DIR_ROW | BZ_UI_FLEX_ALIGN_CENTER | BZ_UI_FLEX_JUSTIFY_START
});
Texture2D tex = tileset->tiles;
switch (input->state) {
case INPUT_NONE:
case INPUT_BUILDING: {
for (i32 i = 0; i < numBuildings; i++) {
BuildingType buildingType = buildingOrder[i];
Rectangle rec = bzTilesetGetTileRegion(tileset, getBuildingTile(buildingType));
// Adjust for size
i32 sizeX = 1, sizeY = 1;
getBuildingSize(buildingType, &sizeX, &sizeY);
rec.width *= sizeX;
rec.height *= sizeY;
bool selected = input->building == buildingOrder[i];
PlayerResources *res = &game->playerResources[game->player];
bool canAfford = canAffordBuilding(buildingType, *res);
uiGameBuild(buildingNames[i], rec, tex, canAfford, &selected);
if (!canAfford)
selected = false;
if (selected) {
input->building = buildingOrder[i];
input->state = INPUT_BUILDING;
}
}
break;
}
case INPUT_SELECTED_UNITS: {
typedef struct UnitPair {
i32 count;
Rectangle rec;
} UnitPair;
UnitPair unitTypes[ENTITY_COUNT] = {0, };
ecs_iter_t it = ecs_query_iter(ECS, input->queries.selected);
while (ecs_query_next(&it)) {
for (i32 i = 0; i < it.count; i++) {
ecs_entity_t entity = it.entities[i];
if (!ecs_has(ECS, entity, Unit))
continue;
Unit unit = *ecs_get(ECS, entity, Unit);
if (unitTypes[unit.unitType].count == 0) {
unitTypes[unit.unitType].rec = ecs_get(ECS, entity, TextureRegion)->rec;
}
unitTypes[unit.unitType].count++;
}
}
i32 filterUnit = -1;
for (i32 i = 0; i < ENTITY_COUNT; i++) {
i32 count = unitTypes[i].count;
if (count == 0) continue;
const char *label = getEntityStr(i);
if (uiGameUnit(label, count, unitTypes[i].rec, tex)) {
filterUnit = i;
}
}
if (filterUnit != -1) {
ecs_defer_begin(ECS);
it = ecs_query_iter(ECS, input->queries.selected);
while (ecs_query_next(&it)) {
for (i32 i = 0; i < it.count; i++) {
ecs_entity_t entity = it.entities[i];
if (ecs_has(ECS, entity, Unit)) {
Unit unit = *ecs_get(ECS, entity, Unit);
if (unit.unitType == filterUnit)
continue;
}
ecs_remove(ECS, entity, Selected);
}
}
ecs_defer_end(ECS);
}
break;
}
case INPUT_SELECTED_OBJECT:
break;
case INPUT_SELECTED_BUILDING:
break;
}
bzUIEnd(UI);
}
void drawPauseUI(Game *game, f32 dt) {
i32 width = GetScreenWidth();
i32 height = GetScreenHeight();
bzUIBegin(UI, width, height);
bzUISetParentLayout(UI, (BzUILayout) {
.type = BZ_UI_LAYOUT_FLEX_BOX,
.flags = BZ_UI_FLEX_DIR_COLUMN
});
uiPushDivParentPercentage(1.0f, 0.4f);
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
});
uiMainMenuLabel("Paused");
bzUIPopParent(UI);
uiPushDivParentPercentage(1.0f, 0.6f);
bzUISetParentLayout(UI, (BzUILayout) {
.type = BZ_UI_LAYOUT_FLEX_BOX,
.flags = BZ_UI_FLEX_DIR_COLUMN | BZ_UI_FLEX_ALIGN_CENTER
});
if (uiMainMenuButton("Resume")) {
setScreen(game, SCREEN_GAME);
}
if (uiMainMenuButton("Exit")) {
setScreen(game, SCREEN_MAIN_MENU);
unloadMap(game);
loadMap(game, "assets/maps/main_menu_01.tmj");
}
bzUIPopParent(UI);
bzUIEnd(UI);
}
void drawMainMenuUI(Game *game, f32 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
});
uiPushDivParentPercentage(1.0f, 0.4f);
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
});
uiMainMenuLabel("Pixel Defense");
bzUIPopParent(UI);
uiPushDivParentPercentage(1.0f, 0.6f);
bzUISetParentLayout(UI, (BzUILayout) {
.type = BZ_UI_LAYOUT_FLEX_BOX,
.flags = BZ_UI_FLEX_DIR_COLUMN | BZ_UI_FLEX_ALIGN_CENTER
});
if (uiMainMenuButton("Play")) {
setScreen(game, SCREEN_GAME);
unloadMap(game);
loadMap(game, "assets/maps/tree_test.tmj");
//loadMap(game, "assets/maps/map_01.tmj");
}
if (uiMainMenuButton("Settings")) {
setScreen(game, SCREEN_SETTINGS);
}
if (uiMainMenuButton("Exit")) {
bzGameExit();
}
bzUIPopParent(UI);
bzUIEnd(UI);
}
void drawSettingsUI(Game *game, f32 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 Options opts;
if (game->screenPrevFrame != SCREEN_SETTINGS)
opts = game->options;
uiSettingsLabel("Video");
uiSettingsCheckbox("Fullscreen", &opts.fullscreen);
uiSettingsCheckbox("V-Sync", &opts.vsync);
uiSettingsLabel("Audio");
uiSettingsSlider("Master: ", &opts.master);
uiSettingsSlider("Music: ", &opts.music);
uiSettingsSlider("Sound: ", &opts.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")) {
setScreen(game, SCREEN_MAIN_MENU);
}
if (uiSettingsButton("Reset")) {
opts = game->options;
}
if (uiSettingsButton("Apply")) {
game->options = opts;
setScreen(game, SCREEN_MAIN_MENU);
}
bzUIEnd(UI);
}