diff --git a/src/application.c b/src/application.c new file mode 100644 index 0000000..9865492 --- /dev/null +++ b/src/application.c @@ -0,0 +1,74 @@ +#include "application.h" + +#include "defs.h" +#include "style.h" +#include + +static inline +void DiceContainer() { + CLAY({ .id = CLAY_ID("DiceContainer"), + .layout = { + .sizing = { CLAY_SIZING_GROW(0), CLAY_SIZING_PERCENT(0.2) }, + .padding = CLAY_PADDING_ALL(16), + }, + .backgroundColor = containerColors[0], + .cornerRadius = CLAY_CORNER_RADIUS(cornerRadius) + }) { + CLAY_TEXT(CLAY_STRING("Text data"), CLAY_TEXT_CONFIG({ + .textColor = textColors[0], + .fontId = FONT_DEFAULT, + .fontSize = 24, + })); + } +} + +static inline +void DiceLogContainer() { + CLAY({ .id = CLAY_ID("LogContainer"), + .layout = { + .sizing = layoutExpand, + .padding = CLAY_PADDING_ALL(16), + }, + .backgroundColor = containerColors[0], + .cornerRadius = cornerRadiusAll + }) {} +} + +static inline +void InitiativeListContainer() { + CLAY({ .id = CLAY_ID("InitiativeListContainer"), + .layout = { + .sizing = layoutExpand, + .padding = CLAY_PADDING_ALL(16), + }, + .backgroundColor = containerColors[0], + .cornerRadius = cornerRadiusAll, + }) {} +} + +Clay_RenderCommandArray RenderApplication() { + Clay_BeginLayout(); + CLAY({ .id = CLAY_ID("OuterContainer"), + .layout = { + .layoutDirection = CLAY_TOP_TO_BOTTOM, + .sizing = layoutExpand, + .padding = CLAY_PADDING_ALL(windowPadding), + .childGap = containerGap + } + }) { + DiceContainer(); + CLAY({ .id = CLAY_ID("LowerSplitContainer"), + .layout = { + .sizing = layoutExpand, + .childGap = containerGap + }, + }) { + DiceLogContainer(); + InitiativeListContainer(); + } + } + return Clay_EndLayout(); +} + +void HandleEvent(SDL_Event event) { +} diff --git a/src/application.h b/src/application.h new file mode 100644 index 0000000..0dce16d --- /dev/null +++ b/src/application.h @@ -0,0 +1,10 @@ +#ifndef APPLICATION_H +#define APPLICATION_H + +#include +#include + +extern Clay_RenderCommandArray RenderApplication(); +extern void HandleEvent(SDL_Event evt); + +#endif // !APPLICATION_H diff --git a/src/defs.h b/src/defs.h new file mode 100644 index 0000000..d5e3dc1 --- /dev/null +++ b/src/defs.h @@ -0,0 +1,19 @@ +#ifndef DEFS_H +#define DEFS_H + +#include + +#include +#include + +enum Font { + FONT_DEFAULT = 0, + FONT_MAX +}; + +extern SDL_Window *window; +extern SDL_Renderer *renderer; +extern TTF_Font *fonts[FONT_MAX]; +extern TTF_TextEngine *textEngine; + +#endif // !DEFS_H diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..5e88483 --- /dev/null +++ b/src/main.c @@ -0,0 +1,144 @@ +#include +#define CLAY_IMPLEMENTATION +#include +#include + +#include "application.h" +#include "defs.h" + +#define SDL_MAIN_HANDLED +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +SDL_Window *window = nullptr; +SDL_Renderer *renderer = nullptr; +int screenWidth = 1920, screenHeight = 1080; +bool running = true; +uint64_t clayMemorySize = 0; + +Clay_Arena clayPrimaryArena; +TTF_Font *fonts[FONT_MAX]; +TTF_TextEngine *textEngine = nullptr; + +Clay_SDL3RendererData backendData = { + .renderer = nullptr, + .fonts = nullptr, + .textEngine = nullptr +}; + +static inline +Clay_Dimensions MeasureText(Clay_StringSlice text, Clay_TextElementConfig *config, void *userData) { + TTF_Font **fonts = userData; + TTF_Font *font = fonts[config->fontId]; + int width, height; + TTF_SetFontSize(font, config->fontSize); + if (!TTF_GetStringSize(font, text.chars, text.length, &width, &height)) { + SDL_LogError(SDL_LOG_CATEGORY_ERROR, "MeasureText failed to measure text %s", SDL_GetError()); + } + return (Clay_Dimensions) { + .width = text.length * config->fontSize, + .height = config->fontSize + }; +} + +static +void HandleClayErrors(Clay_ErrorData data) { + SDL_LogError(SDL_LOG_CATEGORY_ERROR, "%s", data.errorText.chars); +} + +static inline +void InitSDL() { + if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS)) { + SDL_LogError(SDL_LOG_CATEGORY_ERROR, "SDL_Init failed: %s", SDL_GetError()); + exit(1); + } + if ((window = SDL_CreateWindow("Window", screenWidth, screenHeight, SDL_WINDOW_RESIZABLE)) == nullptr) { + SDL_LogError(SDL_LOG_CATEGORY_ERROR, "SDL_CreateWindow failed: %s", SDL_GetError()); + exit(2); + } + if((renderer = SDL_CreateRenderer(window, NULL)) == nullptr) { + SDL_LogError(SDL_LOG_CATEGORY_ERROR, "SDL_CreateRenderer failed: %s", SDL_GetError()); + exit(3); + } + if (!TTF_Init()) { + SDL_LogError(SDL_LOG_CATEGORY_ERROR, "TTF_Init failed: %s", SDL_GetError()); + exit(4); + } + if((textEngine = TTF_CreateRendererTextEngine(renderer)) == nullptr) { + SDL_LogError(SDL_LOG_CATEGORY_ERROR, "TTF_CreateRendererTextEngine failed: %s", SDL_GetError()); + exit(5); + } + fonts[FONT_DEFAULT] = TTF_OpenFont("assets/AdwaitaSans-Regular.ttf", 24.f); + if (fonts[FONT_DEFAULT] == nullptr) { + SDL_LogError(SDL_LOG_CATEGORY_ERROR, "TTF_OpenFont failed: Failed to load adwaita sans: %s", SDL_GetError()); + } +} + +static +void InitClay() { + clayMemorySize = Clay_MinMemorySize(); + clayPrimaryArena = Clay_CreateArenaWithCapacityAndMemory(clayMemorySize, SDL_malloc(clayMemorySize)); + Clay_Initialize(clayPrimaryArena, (Clay_Dimensions) { screenWidth, screenHeight }, (Clay_ErrorHandler) { HandleClayErrors }); + Clay_SetMeasureTextFunction(MeasureText, fonts); + Clay_SetLayoutDimensions((Clay_Dimensions) { screenWidth, screenHeight }); +} + +extern Clay_RenderCommandArray RenderApplication(); +extern void HandleEvent(SDL_Event event); + +int main(int argc, char *argv[]) { + InitSDL(); + InitClay(); + backendData = (Clay_SDL3RendererData) { + .renderer = renderer, + .fonts = fonts, + .textEngine = textEngine, + }; + SDL_Event event; + while (running) { + while (SDL_PollEvent(&event)) { + HandleEvent(event); + switch (event.type) { + case SDL_EVENT_QUIT: + running = false; + break; + case SDL_EVENT_WINDOW_RESIZED: + Clay_SetLayoutDimensions((Clay_Dimensions){ + event.window.data1, + event.window.data2 + }); + break; + case SDL_EVENT_MOUSE_WHEEL: + Clay_UpdateScrollContainers(true, (Clay_Vector2){ event.wheel.x, event.wheel.y }, 0.01f); + 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_BUTTON_DOWN: + Clay_SetPointerState((Clay_Vector2) { event.button.x, event.button.y }, event.button.button == SDL_BUTTON_LEFT); + default: + break; + } + } + SDL_SetRenderDrawColor(renderer, 10, 10, 10, 255); + SDL_RenderClear(renderer); + Clay_RenderCommandArray array = RenderApplication(); + SDL_Clay_RenderClayCommands(&backendData, &array); + SDL_RenderPresent(renderer); + } + SDL_DestroyRenderer(renderer); + SDL_DestroyWindow(window); + SDL_Quit(); + return 0; +} diff --git a/src/style.c b/src/style.c new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/src/style.c @@ -0,0 +1 @@ + diff --git a/src/style.h b/src/style.h new file mode 100644 index 0000000..28e094d --- /dev/null +++ b/src/style.h @@ -0,0 +1,31 @@ +#ifndef STYLE_H +#define STYLE_H + +#include + +constexpr float cornerRadius = 3.f; +constexpr Clay_CornerRadius cornerRadiusAll = CLAY_CORNER_RADIUS(cornerRadius); +constexpr float containerGap = 3.f; +constexpr float windowPadding = 0.f; + +constexpr Clay_Color windowBackground = { + 210, 210, 210, 255 +}; +constexpr Clay_Color containerColors[] = { + { 200, 200, 200, 255 }, + { 170, 170, 170, 255 }, + { 140, 140, 140, 255 }, +}; + +constexpr Clay_Color textColors[] = { + { 0, 0, 0, 255 }, + { 15, 15, 15, 255 }, + { 30, 30, 30, 255 }, +}; + +constexpr Clay_Sizing layoutExpand = { + .width = CLAY_SIZING_GROW(0), + .height = CLAY_SIZING_GROW(0) +}; + +#endif // !STYLE_H