Files
factorygame/util/button.c

213 lines
5.6 KiB
C

//
// Created by bruno on 11.6.2025.
//
#include "button.h"
#include "gamestate.h"
void onStart() {
genInitMap();
screenType = SCREEN_GAME;
}
void onContinue() {
if (loadGameState(autosaveName, &mainPlayer)) {
genInitMap();
}
screenType = SCREEN_GAME;
}
void onCredits() {
screenType = SCREEN_CREDITS;
}
void onNext() {
if (!waveInfo.waveRunning && waveInfo.waveTimer > 60 * 5) {
waveInfo.waveTimer = 60 * 5;
}
}
void onQuit() {
running = false;
}
void onBack() {
screenType = SCREEN_MENU;
}
void onAtlas() {
screenType = SCREEN_ATLAS;
}
void onFont() {
screenType = SCREEN_FONTS;
}
Button buttons[5][BUTTON_COUNT];
void initButtons(void) {
buttons[0][0] = (Button){
.label = "New",
.rect = {110, DISPLAY_HEIGHT / 2, 125, 40},
.color = {100, 100, 0, 255},
.callback = onStart,
.font = &fonts[1]
};
buttons[0][1] = (Button){
.label = "Continue",
.rect = {100, DISPLAY_HEIGHT / 2 + 45, 150, 40},
.color = {0, 100, 0, 255},
.callback = onContinue,
.font = &fonts[1]
};
buttons[0][2] = (Button){
.label = "Credits",
.rect = {DISPLAY_WIDTH - 200, DISPLAY_HEIGHT - 120, 150, 40},
.color = {0, 50, 50, 255},
.callback = onCredits,
.font = &fonts[1]
};
buttons[0][3] = (Button){
.label = "Exit",
.rect = {DISPLAY_WIDTH - 200, DISPLAY_HEIGHT - 40, 100, 40},
.color = {100, 0, 0, 255},
.callback = onQuit,
.font = &fonts[1]
};
buttons[1][0] = (Button){
.label = "Back",
.rect = {DISPLAY_WIDTH / 2 - (100 / 2), DISPLAY_HEIGHT - 40, 100, 40},
.color = {100, 0, 0, 255},
.callback = onBack,
.font = &fonts[1]
};
buttons[1][1] = (Button){
.label = "Font atlas",
.rect = {DISPLAY_WIDTH - 900, DISPLAY_HEIGHT - 40, 200, 40},
.color = {100, 0, 0, 255},
.callback = onFont,
.font = &fonts[1]
};
buttons[1][2] = (Button){
.label = "Texture atlas",
.rect = {DISPLAY_WIDTH - 300, DISPLAY_HEIGHT - 40, 250, 40},
.color = {100, 0, 0, 255},
.callback = onAtlas,
.font = &fonts[1]
};
buttons[2][0] = (Button){
.label = "Next",
.rect = {395, 0, 55, 80},
.color = {64, 64, 64, 64},
.callback = onNext,
.font = &fonts[2]
};
buttons[3][0] = (Button){
.label = "Back",
.rect = {DISPLAY_WIDTH / 2 - (400 / 2), DISPLAY_HEIGHT - 40, 100, 40},
.color = {100, 0, 0, 255},
.callback = onCredits,
.font = &fonts[1]
};
buttons[4][0] = (Button){
.label = "Back",
.rect = {DISPLAY_WIDTH / 2 - (400 / 2), DISPLAY_HEIGHT - 40, 100, 40},
.color = {100, 0, 0, 255},
.callback = onCredits,
.font = &fonts[1]
};
}
void renderButtons(SDL_Renderer *renderer, Player player) {
for (int i = 0; i < BUTTON_COUNT; i++) {
renderButton(renderer, buttons[screenType][i], player);
}
}
void renderButton(SDL_Renderer *renderer, Button btn, Player player) {
if (btn.font == NULL || btn.label == NULL || strlen(btn.label) == 0) {
return;
}
// Check for hover/click
bool hovered = (player.cursor.windowX >= btn.rect.x && player.cursor.windowX <= btn.rect.x + btn.rect.w &&
player.cursor.windowY >= btn.rect.y && player.cursor.windowY <= btn.rect.y + btn.rect.h);
// Set color and draw background
SDL_Color bgColor = btn.color;
if (hovered) {
bgColor.a = btn.color.a / 2;
}
SDL_SetRenderDrawColor(renderer, bgColor.r, bgColor.g, bgColor.b, bgColor.a);
SDL_RenderFillRect(renderer, &btn.rect);
// Split label into lines
const char *label = btn.label;
const int maxLines = 10; // Hard cap for sanity
const char *lines[maxLines];
int lineCount = 0;
lines[lineCount++] = label;
for (const char *p = label; *p && lineCount < maxLines; p++) {
if (*p == '\n') {
lines[lineCount++] = p + 1;
}
}
// Get length of each line and find max width (for centering)
int maxLineWidth = 0;
int lineWidths[maxLines];
int fontSize = btn.font->size;
for (int i = 0; i < lineCount; i++) {
const char *lineStart = lines[i];
const char *lineEnd = strchr(lineStart, '\n');
int lineLen = lineEnd ? (lineEnd - lineStart) : strlen(lineStart);
int lineWidth = lineLen * fontSize;
lineWidths[i] = lineWidth;
if (lineWidth > maxLineWidth) {
maxLineWidth = lineWidth;
}
}
// Calculate starting Y to vertically center all lines
int totalHeight = lineCount * fontSize;
int startY = btn.rect.y + (btn.rect.h - totalHeight) / 2;
// Render each line centered horizontally
for (int i = 0; i < lineCount; i++) {
const char *lineStart = lines[i];
const char *lineEnd = strchr(lineStart, '\n');
int lineLen = lineEnd ? (lineEnd - lineStart) : strlen(lineStart);
char buffer[256];
strncpy(buffer, lineStart, lineLen);
buffer[lineLen] = '\0';
int x = btn.rect.x + (btn.rect.w - lineWidths[i]) / 2;
int y = startY + i * fontSize;
renderText(renderer, *btn.font, buffer, x, y);
}
// Trigger callback if clicked
if (hovered && (player.mouseButtons & SDL_BUTTON_LMASK)) {
if (btn.callback) {
btn.callback();
}
}
}