feat: implemented die images

This commit is contained in:
Sara 2025-09-18 12:11:13 +02:00
parent bdca66b4fd
commit f9234dc9a2
9 changed files with 200 additions and 73 deletions

View file

@ -6,15 +6,8 @@
#include <SDL3/SDL.h>
#include <SDL3_ttf/SDL_ttf.h>
enum Font {
FONT_DEFAULT = 0,
FONT_BOLD = 1,
FONT_MAX
};
extern SDL_Window *window;
extern SDL_Renderer *renderer;
extern TTF_Font *fonts[FONT_MAX];
extern TTF_TextEngine *textEngine;
#endif // !DEFS_H

View file

@ -1,58 +1,73 @@
#include "dice.h"
#include <memory.h>
int roll_die(enum die_type die) {
int Die_Roll(enum Die_Dice die) {
int const max = die;
return (rand() % max) + 1;
}
static int current_active_count = 0;
static enum die_type active_dice_set[MAX_ACTIVE_DICE];
static enum Die_Dice active_dice_set[MAX_ACTIVE_DICE];
static struct roll_result_type roll_results[MAX_ACTIVE_DICE];
static struct roll_result_type roll_total = {
static struct Die_ResultType roll_results[MAX_ACTIVE_DICE];
static struct Die_ResultType roll_total = {
.roll = 0, .string_len = 0
};
enum die_type const *get_active_dice_set(size_t *out_length) {
static
struct Die_ResultType Die_RollToResultType(int roll, enum Die_Dice die) {
struct Die_ResultType result = { };
result.roll = roll;
if (die == COIN) {
result.string_len = SDL_snprintf(result.string, MAX_ROLL_STR_LEN, roll == 1 ? "H" : "T");
} else {
result.string_len = SDL_snprintf(result.string, MAX_ROLL_STR_LEN, "%d", roll);
}
result.clay_string = (Clay_String) {
.chars = result.string,
.length = result.string_len,
.isStaticallyAllocated = false
};
return result;
}
enum Die_Dice const *Die_GetActiveSet(size_t *out_length) {
if (out_length != nullptr) {
*out_length = current_active_count;
}
return active_dice_set;
}
size_t add_die_to_active(enum die_type die) {
size_t Die_AddToActiveSet(enum Die_Dice die) {
if (current_active_count >= MAX_ACTIVE_DICE) {
return MAX_ACTIVE_DICE;
}
active_dice_set[current_active_count] = die;
roll_results[current_active_count].roll = die;
roll_results[current_active_count].string_len = SDL_snprintf(roll_results[current_active_count].string, MAX_ROLL_STR_LEN, "%d", die);
roll_results[current_active_count] = Die_RollToResultType(die, die);
return current_active_count++;
}
void remove_die_from_active(size_t index) {
void Die_RemoveFromActiveSet(size_t index) {
memcpy(active_dice_set + index, active_dice_set + index + 1, MAX_ACTIVE_DICE - index - 1);
--current_active_count;
}
void roll_active_dice_set() {
void Die_RollActiveSet() {
for (size_t i = 0; i < current_active_count; ++i) {
roll_results[i].roll = roll_die(active_dice_set[i]);
roll_results[i].string_len = SDL_snprintf(roll_results[i].string, MAX_ROLL_STR_LEN, "%d", roll_results[i].roll);
roll_results[i] = Die_RollToResultType(Die_Roll(active_dice_set[i]), active_dice_set[i]);
roll_total.roll += roll_results[i].roll;
}
roll_total.string_len = SDL_snprintf(roll_total.string, MAX_ROLL_STR_LEN, "%d", roll_total.roll);
}
struct roll_result_type *get_current_results(size_t *out_length) {
struct Die_ResultType *Die_GetLastResult(size_t *out_length) {
if (out_length != nullptr) {
*out_length = current_active_count;
}
return roll_results;
}
Clay_String die_to_str(enum die_type die) {
Clay_String Die_ToString(enum Die_Dice die) {
switch (die) {
case COIN: return CLAY_STRING("C");
case D4: return CLAY_STRING("4");

View file

@ -9,10 +9,10 @@
#endif
#ifndef MAX_ROLL_STR_LEN
#define MAX_ROLL_STR_LEN 5
#define MAX_ROLL_STR_LEN 10
#endif
enum die_type {
enum Die_Dice {
COIN = 2,
D4 = 4,
D6 = 6,
@ -23,22 +23,23 @@ enum die_type {
D100 = 100
};
struct roll_result_type {
struct Die_ResultType {
int roll;
size_t string_len;
char string[MAX_ROLL_STR_LEN];
Clay_String clay_string;
};
extern int roll_die(enum die_type die);
extern int Die_Roll(enum Die_Dice die);
extern enum die_type const *get_active_dice_set(size_t *out_length);
extern size_t add_die_to_active(enum die_type die);
extern void remove_die_from_active(size_t index);
extern enum Die_Dice const *Die_GetActiveSet(size_t *out_length);
extern size_t Die_AddToActiveSet(enum Die_Dice die);
extern void Die_RemoveFromActiveSet(size_t index);
extern struct roll_result_type *get_current_results(size_t *out_length);
extern struct Die_ResultType *Die_GetLastResult(size_t *out_length);
extern void roll_active_dice_set();
extern void Die_RollActiveSet();
extern Clay_String die_to_str(enum die_type die);
extern Clay_String Die_ToString(enum Die_Dice die);
#endif // !DICE_H

View file

@ -1,5 +1,6 @@
#include "dice_container.h"
#include <SDL3/SDL_mouse.h>
#include <SDL3_image/SDL_image.h>
#include <clay/clay.h>
#include <stdint.h>
#include "elements.h"
@ -9,7 +10,7 @@
static
void HandleRollSetButtonInteraction(Clay_ElementId element, Clay_PointerData pointer, intptr_t data) {
if (pointer.state == CLAY_POINTER_DATA_PRESSED_THIS_FRAME) {
roll_active_dice_set();
Die_RollActiveSet();
}
}
@ -27,21 +28,21 @@ void RollSetButton() {
static
void HandleAddDieButtonInteraction(Clay_ElementId element, Clay_PointerData pointer, intptr_t die) {
if (pointer.state == CLAY_POINTER_DATA_PRESSED_THIS_FRAME) {
add_die_to_active((enum die_type)die);
Die_AddToActiveSet((enum Die_Dice)die);
}
}
static inline
void AddDieButton(enum die_type die) {
void AddDieButton(enum Die_Dice die) {
CLAY(CLAY_IDI("AddDieButton", die), {
.layout = {
.sizing = { CLAY_SIZING_FIXED(100), CLAY_SIZING_FIXED(100) },
.childAlignment = { CLAY_ALIGN_X_CENTER, CLAY_ALIGN_Y_CENTER },
},
.backgroundColor = DieButtonColor(die, Clay_Hovered()),
.image = { GetDiceImage(die) }
}) {
Clay_OnHover(&HandleAddDieButtonInteraction, die);
CLAY_TEXT(die_to_str(die), CLAY_TEXT_CONFIG({
CLAY_TEXT(Die_ToString(die), CLAY_TEXT_CONFIG({
.textColor = TextColors(0),
.H(2),
}));
@ -84,21 +85,21 @@ void DiceSelectorContainer() {
static
void HandleRemoveDieButtonInteraction(Clay_ElementId element, Clay_PointerData pointer, intptr_t index) {
if (pointer.state == CLAY_POINTER_DATA_PRESSED_THIS_FRAME) {
remove_die_from_active(index);
Die_RemoveFromActiveSet(index);
}
}
static inline
void RemoveDieButton(enum die_type die, int index) {
void RemoveDieButton(enum Die_Dice die, int index) {
CLAY(CLAY_IDI("RemoveDieButton", index), {
.layout = {
.sizing = { CLAY_SIZING_FIXED(200), CLAY_SIZING_FIXED(200) },
.childAlignment = { CLAY_ALIGN_X_CENTER, CLAY_ALIGN_Y_CENTER },
},
.backgroundColor = DieButtonColor(die, Clay_Hovered()),
.image = { GetDiceImage(die) },
}) {
size_t result_length;
struct roll_result_type const *result = get_current_results(&result_length);
struct Die_ResultType const *result = Die_GetLastResult(&result_length);
Clay_String string = {
.chars = result[index].string,
.length = result[index].string_len,
@ -136,7 +137,7 @@ void ActiveDiceContainer() {
},
}) {
size_t dice_count = 0;
enum die_type const *dice = get_active_dice_set(&dice_count);
enum Die_Dice const *dice = Die_GetActiveSet(&dice_count);
for (size_t i = 0; i < dice_count; ++i) {
RemoveDieButton(dice[i], i);
}

View file

@ -7,6 +7,7 @@
#include "application.h"
#include "defs.h"
#include "style.h"
#include "resources.h"
#define SDL_MAIN_HANDLED
#include <SDL3/SDL.h>
@ -33,8 +34,6 @@ bool running = true;
uint64_t clayMemorySize = 0;
Clay_Arena clayPrimaryArena;
TTF_Font *fonts[FONT_MAX];
TTF_TextEngine *textEngine = nullptr;
Clay_SDL3RendererData backendData = {
.renderer = nullptr,
@ -66,22 +65,6 @@ void HandleClayErrors(Clay_ErrorData data) {
SDL_LogError(SDL_LOG_CATEGORY_ERROR, "%s", data.errorText.chars);
}
static inline void InitFonts() {
fonts[FONT_DEFAULT] = TTF_OpenFont("assets/AdwaitaSans-Regular.ttf", baseFontSize * 5);
if (fonts[FONT_DEFAULT] == nullptr) {
SDL_LogError(SDL_LOG_CATEGORY_ERROR, "TTF_OpenFont failed: Failed to load adwaita sans: %s", SDL_GetError());
exit(6);
}
TTF_SetFontHinting(fonts[FONT_DEFAULT], TTF_HINTING_LIGHT_SUBPIXEL);
fonts[FONT_BOLD] = TTF_OpenFont("assets/AdwaitaSans-Regular.ttf", baseFontSize * 5);
if (fonts[FONT_BOLD] == nullptr) {
SDL_LogError(SDL_LOG_CATEGORY_ERROR, "TTF_OpenFont failed: Failed to load adwaita sans bold: %s", SDL_GetError());
exit(7);
}
TTF_SetFontHinting(fonts[FONT_BOLD], TTF_HINTING_LIGHT_SUBPIXEL);
TTF_SetFontStyle(fonts[FONT_BOLD], TTF_STYLE_BOLD);
}
static inline
void InitSDL() {
SDL_SetHint(SDL_HINT_RENDER_LINE_METHOD, "3");
@ -124,7 +107,7 @@ extern void HandleEvent(SDL_Event event);
int main(int argc, char *argv[]) {
InitSDL();
InitFonts();
LoadResources();
LogOutputResolution();
InitClay();
backendData = (Clay_SDL3RendererData) {

89
src/resources.c Normal file
View file

@ -0,0 +1,89 @@
#include "resources.h"
#include "defs.h"
#include "style.h"
#include <SDL3/SDL_log.h>
#include <SDL3/SDL_render.h>
#include <SDL3_image/SDL_image.h>
TTF_Font *fonts[FONT_MAX];
SDL_Texture *diceImages[DICE_IMAGE_MAX];
TTF_TextEngine *textEngine = nullptr;
static inline
void LoadFonts() {
fonts[FONT_DEFAULT] = TTF_OpenFont("assets/AdwaitaSans-Regular.ttf", baseFontSize * 5);
if (fonts[FONT_DEFAULT] == nullptr) {
SDL_LogError(SDL_LOG_CATEGORY_ERROR, "TTF_OpenFont failed: Failed to load adwaita sans: %s", SDL_GetError());
exit(6);
}
TTF_SetFontHinting(fonts[FONT_DEFAULT], TTF_HINTING_LIGHT_SUBPIXEL);
fonts[FONT_BOLD] = TTF_OpenFont("assets/AdwaitaSans-Regular.ttf", baseFontSize * 5);
if (fonts[FONT_BOLD] == nullptr) {
SDL_LogError(SDL_LOG_CATEGORY_ERROR, "TTF_OpenFont failed: Failed to load adwaita sans bold: %s", SDL_GetError());
exit(6);
}
TTF_SetFontHinting(fonts[FONT_BOLD], TTF_HINTING_LIGHT_SUBPIXEL);
TTF_SetFontStyle(fonts[FONT_BOLD], TTF_STYLE_BOLD);
}
static inline
void LoadDiceImages() {
if(!(diceImages[COIN_IMAGE] = IMG_LoadTexture(renderer, "assets/icons/d2.svg"))) {
SDL_LogError(SDL_LOG_CATEGORY_ERROR, "IMG_LoadTexture Failed to load die texture: %s", SDL_GetError());
exit(7);
}
if(!(diceImages[D4_IMAGE] = IMG_LoadTexture(renderer, "assets/icons/d4.svg"))) {
SDL_LogError(SDL_LOG_CATEGORY_ERROR, "IMG_LoadTexture Failed to load die texture: %s", SDL_GetError());
exit(7);
}
if(!(diceImages[D6_IMAGE] = IMG_LoadTexture(renderer, "assets/icons/d6.svg"))) {
SDL_LogError(SDL_LOG_CATEGORY_ERROR, "IMG_LoadTexture Failed to load die texture: %s", SDL_GetError());
exit(7);
}
if(!(diceImages[D8_IMAGE] = IMG_LoadTexture(renderer, "assets/icons/d8.svg"))) {
SDL_LogError(SDL_LOG_CATEGORY_ERROR, "IMG_LoadTexture Failed to load die texture: %s", SDL_GetError());
exit(7);
}
if(!(diceImages[D10_IMAGE] = IMG_LoadTexture(renderer, "assets/icons/d10.svg"))) {
SDL_LogError(SDL_LOG_CATEGORY_ERROR, "IMG_LoadTexture Failed to load die texture: %s", SDL_GetError());
exit(7);
}
if(!(diceImages[D12_IMAGE] = IMG_LoadTexture(renderer, "assets/icons/d12.svg"))) {
SDL_LogError(SDL_LOG_CATEGORY_ERROR, "IMG_LoadTexture Failed to load die texture: %s", SDL_GetError());
exit(7);
}
if(!(diceImages[D20_IMAGE] = IMG_LoadTexture(renderer, "assets/icons/d20.svg"))) {
SDL_LogError(SDL_LOG_CATEGORY_ERROR, "IMG_LoadTexture Failed to load die texture: %s", SDL_GetError());
exit(7);
}
for (size_t i = 0; i < DICE_IMAGE_MAX; ++i) {
Clay_Color color = dieColors[i];
SDL_SetTextureColorMod(diceImages[i], color.r, color.g, color.b);
}
}
void LoadResources() {
LoadFonts();
LoadDiceImages();
}
SDL_Texture *GetDiceImage(enum Die_Dice die) {
switch (die) {
case COIN:
return diceImages[COIN_IMAGE];
case D4:
return diceImages[D4_IMAGE];
case D6:
return diceImages[D6_IMAGE];
case D8:
return diceImages[D8_IMAGE];
case D10:
return diceImages[D10_IMAGE];
case D12:
return diceImages[D12_IMAGE];
case D20:
return diceImages[D20_IMAGE];
case D100:
return diceImages[D10_IMAGE];
}
}

34
src/resources.h Normal file
View file

@ -0,0 +1,34 @@
#ifndef RESOURCES_H
#define RESOURCES_H
#include "dice.h"
#include <SDL3/SDL_render.h>
#include <SDL3_ttf/SDL_ttf.h>
enum Font {
FONT_DEFAULT = 0,
FONT_BOLD = 1,
FONT_MAX
};
enum DiceImages {
COIN_IMAGE = 0,
D4_IMAGE = 1,
D6_IMAGE,
D8_IMAGE,
D10_IMAGE,
D12_IMAGE,
D20_IMAGE,
DICE_IMAGE_MAX
};
extern TTF_TextEngine *textEngine;
extern TTF_Font *fonts[FONT_MAX];
extern SDL_Texture *diceImages[DICE_IMAGE_MAX];
extern void LoadResources();
extern SDL_Texture *GetDiceImage(enum Die_Dice die);
#endif // !RESOURCES_H

View file

@ -45,21 +45,21 @@ Clay_ElementDeclaration WindowStyle() {
};
}
Clay_Color DieColor(enum die_type die) {
Clay_Color DieColor(enum Die_Dice die) {
switch(die) {
case COIN: return (Clay_Color) { 230, 184, 48, 255 };
case D4: return (Clay_Color) { 177, 56, 52, 255 };
case D6: return (Clay_Color) { 115, 177, 52, 255 };
case D8: return (Clay_Color) { 52, 177, 125, 255 };
case D10: return (Clay_Color) { 52, 177, 176, 255 };
case D12: return (Clay_Color) { 52, 93, 177, 255 };
case D20: return (Clay_Color) { 177, 52, 140, 255 };
case D100: return (Clay_Color) { 95, 52, 177, 255 };
case COIN: return dieColors[0];
case D4: return dieColors[1];
case D6: return dieColors[2];
case D8: return dieColors[3];
case D10: return dieColors[4];
case D12: return dieColors[5];
case D20: return dieColors[6];
case D100: return dieColors[7];
default: return (Clay_Color) { 0, 0, 0, 255 };
}
}
Clay_Color DieButtonColor(enum die_type die, bool selected) {
Clay_Color DieButtonColor(enum Die_Dice die, bool selected) {
return selected ? ToHoveredColor(DieColor(die)) : DieColor(die);
}

View file

@ -2,7 +2,7 @@
#define STYLE_H
#include "defs.h"
#include "dice.h"
#include "resources.h"
#include <clay/clay.h>
#include <stdint.h>
@ -81,6 +81,17 @@ constexpr Clay_CornerRadius buttonRadii = {
3, 3, 3, 3
};
constexpr Clay_Color dieColors[] = {
{ 230, 184, 48, 255 },
{ 177, 56, 52, 255 },
{ 115, 177, 52, 255 },
{ 52, 177, 125, 255 },
{ 52, 177, 176, 255 },
{ 52, 93, 177, 255 },
{ 177, 52, 140, 255 },
{ 95, 52, 177, 255 },
};
////////////////////////////////////
// COMPILATIONS
// | Functions and expressions that combine styling data from the settings above.
@ -101,8 +112,8 @@ extern Clay_Color PanelBackground(size_t idx);
extern Clay_Color TextColors(size_t idx);
extern Clay_Color WindowBackground();
extern Clay_ElementDeclaration WindowStyle();
extern Clay_Color DieColor(enum die_type die);
extern Clay_Color DieButtonColor(enum die_type die, bool selected);
extern Clay_Color DieColor(enum Die_Dice die);
extern Clay_Color DieButtonColor(enum Die_Dice die, bool selected);
extern Clay_Color ToHoveredColor(Clay_Color color);
#endif // !STYLE_H