mirror of
https://github.com/nicbarker/clay.git
synced 2025-04-12 01:08:04 +00:00
186 lines
5.1 KiB
C
186 lines
5.1 KiB
C
|
#define SDL_MAIN_USE_CALLBACKS
|
||
|
#include <SDL3/SDL_main.h>
|
||
|
#include <SDL3/SDL.h>
|
||
|
#include <SDL3_ttf/SDL_ttf.h>
|
||
|
|
||
|
#define CLAY_IMPLEMENTATION
|
||
|
#include "../../clay.h"
|
||
|
|
||
|
#include <stdio.h>
|
||
|
|
||
|
#include "../../renderers/SDL3/clay_renderer_SDL3.c"
|
||
|
|
||
|
static const Uint32 FONT_ID = 0;
|
||
|
|
||
|
static const Clay_Color COLOR_ORANGE = (Clay_Color) {225, 138, 50, 255};
|
||
|
static const Clay_Color COLOR_BLUE = (Clay_Color) {111, 173, 162, 255};
|
||
|
static const Clay_Color COLOR_LIGHT = (Clay_Color) {224, 215, 210, 255};
|
||
|
|
||
|
typedef struct app_state {
|
||
|
SDL_Window *window;
|
||
|
SDL_Renderer *renderer;
|
||
|
} AppState;
|
||
|
|
||
|
static inline Clay_Dimensions SDL_MeasureText(Clay_String *text, Clay_TextElementConfig *config)
|
||
|
{
|
||
|
TTF_Font *font = gFonts[config->fontId];
|
||
|
int width, height;
|
||
|
|
||
|
if (!TTF_GetStringSize(font, text->chars, text->length, &width, &height)) {
|
||
|
SDL_LogError(SDL_LOG_CATEGORY_ERROR, "Failed to measure text: %s", SDL_GetError());
|
||
|
}
|
||
|
|
||
|
return (Clay_Dimensions) { (float) width, (float) height };
|
||
|
}
|
||
|
|
||
|
static void Label(Clay_String text)
|
||
|
{
|
||
|
CLAY(CLAY_LAYOUT({ .padding = {16, 8} }), CLAY_RECTANGLE({ .color = Clay_Hovered() ? COLOR_BLUE : COLOR_ORANGE })) {
|
||
|
CLAY_TEXT(text, CLAY_TEXT_CONFIG({
|
||
|
.textColor = { 255, 255, 255, 255 },
|
||
|
.fontId = FONT_ID,
|
||
|
.fontSize = 24,
|
||
|
}));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static Clay_RenderCommandArray Clay_CreateLayout()
|
||
|
{
|
||
|
Clay_BeginLayout();
|
||
|
CLAY(CLAY_ID("MainContent"),
|
||
|
CLAY_LAYOUT({
|
||
|
.sizing = {
|
||
|
.width = CLAY_SIZING_GROW(),
|
||
|
.height = CLAY_SIZING_GROW(),
|
||
|
},
|
||
|
.childAlignment = {
|
||
|
.x = CLAY_ALIGN_X_CENTER,
|
||
|
.y = CLAY_ALIGN_Y_CENTER,
|
||
|
},
|
||
|
.childGap = 10,
|
||
|
.padding = { 10, 10 },
|
||
|
.layoutDirection = CLAY_TOP_TO_BOTTOM,
|
||
|
}),
|
||
|
CLAY_RECTANGLE({
|
||
|
.color = COLOR_LIGHT,
|
||
|
})
|
||
|
) {
|
||
|
Label(CLAY_STRING("Button 1"));
|
||
|
Label(CLAY_STRING("Button 2"));
|
||
|
Label(CLAY_STRING("Button 3"));
|
||
|
}
|
||
|
return Clay_EndLayout();
|
||
|
}
|
||
|
|
||
|
void HandleClayErrors(Clay_ErrorData errorData) {
|
||
|
printf("%s", errorData.errorText.chars);
|
||
|
}
|
||
|
|
||
|
SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
|
||
|
{
|
||
|
(void) argc;
|
||
|
(void) argv;
|
||
|
|
||
|
if (!TTF_Init()) {
|
||
|
return SDL_APP_FAILURE;
|
||
|
}
|
||
|
|
||
|
AppState *state = SDL_calloc(1, sizeof(AppState));
|
||
|
if (!state) {
|
||
|
return SDL_APP_FAILURE;
|
||
|
}
|
||
|
*appstate = state;
|
||
|
|
||
|
if (!SDL_CreateWindowAndRenderer("Clay Demo", 640, 480, 0, &state->window, &state->renderer)) {
|
||
|
SDL_LogError(SDL_LOG_CATEGORY_ERROR, "Failed to create window and renderer: %s", SDL_GetError());
|
||
|
return SDL_APP_FAILURE;
|
||
|
}
|
||
|
SDL_SetWindowResizable(state->window, true);
|
||
|
|
||
|
TTF_Font *font = TTF_OpenFont("resources/Roboto-Regular.ttf", 24);
|
||
|
if (!font) {
|
||
|
SDL_LogError(SDL_LOG_CATEGORY_ERROR, "Failed to load font: %s", SDL_GetError());
|
||
|
return SDL_APP_FAILURE;
|
||
|
}
|
||
|
|
||
|
gFonts[FONT_ID] = font;
|
||
|
|
||
|
/* Initialize Clay */
|
||
|
uint64_t totalMemorySize = Clay_MinMemorySize();
|
||
|
Clay_Arena clayMemory = (Clay_Arena) {
|
||
|
.memory = SDL_malloc(totalMemorySize),
|
||
|
.capacity = totalMemorySize
|
||
|
};
|
||
|
|
||
|
int width, height;
|
||
|
SDL_GetWindowSize(state->window, &width, &height);
|
||
|
Clay_SetMeasureTextFunction(SDL_MeasureText);
|
||
|
Clay_Initialize(clayMemory, (Clay_Dimensions) { (float) width, (float) height }, (Clay_ErrorHandler) { HandleClayErrors });
|
||
|
|
||
|
*appstate = state;
|
||
|
return SDL_APP_CONTINUE;
|
||
|
}
|
||
|
|
||
|
SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event)
|
||
|
{
|
||
|
SDL_AppResult ret_val = SDL_APP_CONTINUE;
|
||
|
|
||
|
switch (event->type) {
|
||
|
case SDL_EVENT_QUIT:
|
||
|
ret_val = SDL_APP_SUCCESS;
|
||
|
break;
|
||
|
case SDL_EVENT_WINDOW_RESIZED:
|
||
|
Clay_SetLayoutDimensions((Clay_Dimensions) { (float) event->window.data1, (float) event->window.data2 });
|
||
|
break;
|
||
|
case SDL_EVENT_MOUSE_MOTION:
|
||
|
Clay_SetPointerState((Clay_Vector2) { event->motion.x, event->motion.y },
|
||
|
event->motion.state & SDL_BUTTON_LEFT);
|
||
|
break;
|
||
|
case SDL_EVENT_MOUSE_WHEEL:
|
||
|
Clay_UpdateScrollContainers(true, (Clay_Vector2) { event->motion.xrel, event->motion.yrel }, 0.01f);
|
||
|
break;
|
||
|
default:
|
||
|
break;
|
||
|
};
|
||
|
|
||
|
return ret_val;
|
||
|
}
|
||
|
|
||
|
SDL_AppResult SDL_AppIterate(void *appstate)
|
||
|
{
|
||
|
AppState *state = appstate;
|
||
|
|
||
|
Clay_RenderCommandArray render_commands = Clay_CreateLayout();
|
||
|
|
||
|
SDL_SetRenderDrawColor(state->renderer, 0, 0, 0, 255);
|
||
|
SDL_RenderClear(state->renderer);
|
||
|
|
||
|
SDL_RenderClayCommands(state->renderer, &render_commands);
|
||
|
|
||
|
SDL_RenderPresent(state->renderer);
|
||
|
|
||
|
return SDL_APP_CONTINUE;
|
||
|
}
|
||
|
|
||
|
void SDL_AppQuit(void *appstate, SDL_AppResult result)
|
||
|
{
|
||
|
(void) result;
|
||
|
|
||
|
if (result != SDL_APP_SUCCESS) {
|
||
|
SDL_LogError(SDL_LOG_CATEGORY_ERROR, "Application failed to run");
|
||
|
}
|
||
|
|
||
|
AppState *state = appstate;
|
||
|
|
||
|
if (state) {
|
||
|
if (state->renderer)
|
||
|
SDL_DestroyRenderer(state->renderer);
|
||
|
|
||
|
if (state->window)
|
||
|
SDL_DestroyWindow(state->window);
|
||
|
|
||
|
SDL_free(state);
|
||
|
}
|
||
|
TTF_Quit();
|
||
|
}
|