clay
clay copied to clipboard
[Macros] CLAY_STRING should only be used for constant strings
Environment:
- OS: Windows 11
- Renderer: raylib
- GPU: NVIDIA RTX 3060
I was writing a small demo to test if I can use Clay to create a leaderboard (source code below). However, I noticed that Clay behaves incorrectly approximately 20% of the time, while it works as expected the other 80%. Every variablein my code is constant so I thought it was an issue with clay
Expected behavior:
Same executable 20% of the time
#define CLAY_IMPLEMENTATION
#include "clay.h"
#include "clay_renderer_raylib.c"
const uint32_t FONT_ID_BODY_24 = 0;
const uint32_t FONT_ID_BODY_16 = 1;
#define COLOR_ORANGE (Clay_Color) {225, 138, 50, 255}
#define COLOR_BLUE (Clay_Color) {111, 173, 162, 255}
#define RAYLIB_VECTOR2_TO_CLAY_VECTOR2(vector) (Clay_Vector2) { .x = vector.x, .y = vector.y }
typedef struct {
char rank[20];
char name[20];
char money[20];
} LeaderboardEntry;
LeaderboardEntry leaderboard2[] = {
(LeaderboardEntry){"1", "richman","1000003"},
(LeaderboardEntry){"2", "ali","3100"},
(LeaderboardEntry){"3", "ahmed","1600"},
(LeaderboardEntry){"4", "brokefurk","3"},
(LeaderboardEntry){"5", "richman","1000003"},
(LeaderboardEntry){"6", "ali","3100"},
(LeaderboardEntry){"7", "ahmed","1600"},
(LeaderboardEntry){"8", "brokefurk","3"},
(LeaderboardEntry){"9", "brokefurk","3"},
(LeaderboardEntry){"10", "brokefurk","3"},
(LeaderboardEntry){"1", "richman","1000003"},
(LeaderboardEntry){"2", "ali","3100"},
(LeaderboardEntry){"3", "ahmed","1600"},
(LeaderboardEntry){"4", "brokefurk","3"},
(LeaderboardEntry){"5", "richman","1000003"},
(LeaderboardEntry){"6", "ali","3100"},
(LeaderboardEntry){"7", "ahmed","1600"},
(LeaderboardEntry){"8", "brokefurk","3"},
(LeaderboardEntry){"9", "brokefurk","3"},
(LeaderboardEntry){"10","brokefurk","3"},
(LeaderboardEntry){"1", "richman","1000003"},
(LeaderboardEntry){"2", "ali","3100"},
(LeaderboardEntry){"3", "ahmed","1600"},
(LeaderboardEntry){"4", "brokefurk","3"},
(LeaderboardEntry){"5", "richman","1000003"},
(LeaderboardEntry){"6", "ali","3100"},
(LeaderboardEntry){"7", "ahmed","1600"},
(LeaderboardEntry){"8", "brokefurk","3"},
(LeaderboardEntry){"9", "brokefurk","3"},
(LeaderboardEntry){"10", "brokefurk","3"},
(LeaderboardEntry){"1", "richman","1000003"},
(LeaderboardEntry){"2", "ali","3100"},
(LeaderboardEntry){"3", "ahmed","1600"},
(LeaderboardEntry){"4", "brokefurk","3"},
(LeaderboardEntry){"5", "richman","1000003"},
(LeaderboardEntry){"6", "ali","3100"},
(LeaderboardEntry){"7", "ahmed","1600"},
(LeaderboardEntry){"8", "brokefurk","3"},
(LeaderboardEntry){"9", "brokefurk","3"},
(LeaderboardEntry){"10", "brokefurk","3"},
(LeaderboardEntry){"1", "richman","1000003"},
(LeaderboardEntry){"2", "ali","3100"},
(LeaderboardEntry){"3", "ahmed","1600"},
(LeaderboardEntry){"4", "brokefurk","3"},
(LeaderboardEntry){"5", "richman","1000003"},
(LeaderboardEntry){"6", "ali","3100"},
(LeaderboardEntry){"7", "ahmed","1600"},
(LeaderboardEntry){"8", "brokefurk","3"},
(LeaderboardEntry){"9", "brokefurk","3"},
(LeaderboardEntry){"10","brokefurk","3"},
};
int count = 50;
Clay_RenderCommandArray CreateLayout() {
Clay_BeginLayout();
CLAY(CLAY_LAYOUT({ .sizing = { .width = CLAY_SIZING_GROW(), .height = CLAY_SIZING_GROW() }, .childAlignment = { CLAY_ALIGN_X_CENTER, CLAY_ALIGN_Y_CENTER} }),
CLAY_RECTANGLE({ .color = {200, 200, 200, 255} })) {
CLAY(CLAY_ID("MainContent"),
CLAY_SCROLL({ .vertical = true }),
CLAY_LAYOUT({ .layoutDirection = CLAY_TOP_TO_BOTTOM, .sizing = { CLAY_SIZING_FIXED(600), CLAY_SIZING_FIXED(300) } }),
CLAY_RECTANGLE({ .color = {200, 200, 255, 255} }))
{
for (int i = 0; i < count; i++) {
int rowColor = (i % 2) ? 40 : 60;
CLAY(
CLAY_LAYOUT({ .childGap = 4, .sizing = { CLAY_SIZING_GROW(), CLAY_SIZING_FIXED(40) } }),
CLAY_RECTANGLE({ .color = {0, 0, 0, 255} }))
{
CLAY(
CLAY_LAYOUT({.sizing = { CLAY_SIZING_PERCENT(0.1f), CLAY_SIZING_GROW() }, .childAlignment = { CLAY_ALIGN_X_CENTER, CLAY_ALIGN_Y_CENTER}}),
CLAY_RECTANGLE({ .color = {rowColor, rowColor, rowColor, 255} }))
{
CLAY_TEXT(CLAY_STRING(leaderboard2[i].rank), CLAY_TEXT_CONFIG({ .fontId = FONT_ID_BODY_24, .fontSize = 24, .textColor = {255,255,255,255} }));
}
CLAY(
CLAY_LAYOUT({.sizing = { CLAY_SIZING_PERCENT(0.45f), CLAY_SIZING_GROW() }, .childAlignment = { CLAY_ALIGN_X_CENTER, CLAY_ALIGN_Y_CENTER} }),
CLAY_RECTANGLE({ .color = {rowColor, rowColor, rowColor, 255} }))
{
CLAY_TEXT(CLAY_STRING(leaderboard2[i].name), CLAY_TEXT_CONFIG({ .fontId = FONT_ID_BODY_24, .fontSize = 24, .textColor = {255,255,255,255} }));
}
CLAY(
CLAY_LAYOUT({.sizing = { CLAY_SIZING_PERCENT(0.45f), CLAY_SIZING_GROW() }, .childAlignment = { CLAY_ALIGN_X_CENTER, CLAY_ALIGN_Y_CENTER} }),
CLAY_RECTANGLE({ .color = {rowColor, rowColor, rowColor, 255} }))
{
CLAY_TEXT(CLAY_STRING(leaderboard2[i].money), CLAY_TEXT_CONFIG({ .fontId = FONT_ID_BODY_24, .fontSize = 24, .textColor = {255,255,255,255} }));
}
}
}
}
Clay_ScrollContainerData scrollData = Clay_GetScrollContainerData(Clay_GetElementId(CLAY_STRING("MainContent")));
if (scrollData.found) {
CLAY(CLAY_ID("ScrollBar"),
CLAY_FLOATING({
.offset = { .y = -(scrollData.scrollPosition->y / scrollData.contentDimensions.height) * scrollData.scrollContainerDimensions.height },
.zIndex = 1,
.parentId = Clay_GetElementId(CLAY_STRING("MainContent")).id,
.attachment = {.element = CLAY_ATTACH_POINT_RIGHT_TOP, .parent = CLAY_ATTACH_POINT_RIGHT_TOP}
})
) {
CLAY(CLAY_ID("ScrollBarButton"),
CLAY_LAYOUT({ .sizing = {CLAY_SIZING_FIXED(10), CLAY_SIZING_FIXED((scrollData.scrollContainerDimensions.height / scrollData.contentDimensions.height) * scrollData.scrollContainerDimensions.height) }}),
CLAY_RECTANGLE({ .cornerRadius = {6}, .color = Clay_PointerOver(Clay__HashString(CLAY_STRING("ScrollBar"), 0, 0)) ? (Clay_Color){255, 255, 255, 180} : (Clay_Color){255, 255, 255, 120} })
) {}
}
}
}
return Clay_EndLayout();
}
typedef struct
{
Clay_Vector2 clickOrigin;
Clay_Vector2 positionOrigin;
bool mouseDown;
} ScrollbarData;
ScrollbarData scrollbarData = (ScrollbarData) {};
bool debugEnabled = false;
void UpdateDrawFrame(void)
{
Vector2 mouseWheelDelta = GetMouseWheelMoveV();
float mouseWheelX = mouseWheelDelta.x;
float mouseWheelY = mouseWheelDelta.y;
if (IsKeyPressed(KEY_D)) {
debugEnabled = !debugEnabled;
Clay_SetDebugModeEnabled(debugEnabled);
}
Clay_Vector2 mousePosition = RAYLIB_VECTOR2_TO_CLAY_VECTOR2(GetMousePosition());
Clay_SetPointerState(mousePosition, IsMouseButtonDown(0) && !scrollbarData.mouseDown);
Clay_SetLayoutDimensions((Clay_Dimensions) { (float)GetScreenWidth(), (float)GetScreenHeight() });
if (!IsMouseButtonDown(0)) {
scrollbarData.mouseDown = false;
}
if (IsMouseButtonDown(0) && !scrollbarData.mouseDown && Clay_PointerOver(Clay__HashString(CLAY_STRING("ScrollBar"), 0, 0))) {
Clay_ScrollContainerData scrollContainerData = Clay_GetScrollContainerData(Clay__HashString(CLAY_STRING("MainContent"), 0, 0));
scrollbarData.clickOrigin = mousePosition;
scrollbarData.positionOrigin = *scrollContainerData.scrollPosition;
scrollbarData.mouseDown = true;
} else if (scrollbarData.mouseDown) {
Clay_ScrollContainerData scrollContainerData = Clay_GetScrollContainerData(Clay__HashString(CLAY_STRING("MainContent"), 0, 0));
if (scrollContainerData.contentDimensions.height > 0) {
Clay_Vector2 ratio = (Clay_Vector2) {
scrollContainerData.contentDimensions.width / scrollContainerData.scrollContainerDimensions.width,
scrollContainerData.contentDimensions.height / scrollContainerData.scrollContainerDimensions.height,
};
if (scrollContainerData.config.vertical) {
scrollContainerData.scrollPosition->y = scrollbarData.positionOrigin.y + (scrollbarData.clickOrigin.y - mousePosition.y) * ratio.y;
}
if (scrollContainerData.config.horizontal) {
scrollContainerData.scrollPosition->x = scrollbarData.positionOrigin.x + (scrollbarData.clickOrigin.x - mousePosition.x) * ratio.x;
}
}
}
Clay_UpdateScrollContainers(true, (Clay_Vector2) {mouseWheelX, mouseWheelY}, GetFrameTime());
double currentTime = GetTime();
Clay_RenderCommandArray renderCommands = CreateLayout();
printf("layout time: %f microseconds\n", (GetTime() - currentTime) * 1000 * 1000);
BeginDrawing();
ClearBackground(BLACK);
Clay_Raylib_Render(renderCommands);
EndDrawing();
}
int main() {
uint64_t totalMemorySize = Clay_MinMemorySize();
Clay_Arena clayMemory = (Clay_Arena) {.memory = malloc(totalMemorySize), .capacity = totalMemorySize };
Clay_SetMeasureTextFunction(Raylib_MeasureText);
Clay_Initialize(clayMemory, (Clay_Dimensions) { (float)GetScreenWidth(), (float)GetScreenHeight() });
Clay_Raylib_Initialize(1200, 540, "Clay - Raylib Renderer Example", FLAG_VSYNC_HINT | FLAG_WINDOW_RESIZABLE | FLAG_WINDOW_HIGHDPI | FLAG_MSAA_4X_HINT);
Raylib_fonts[FONT_ID_BODY_24] = (Raylib_Font) {
.font = LoadFontEx("Poppins-Regular.ttf", 48, 0, 400),
.fontId = FONT_ID_BODY_24,
};
SetTextureFilter(Raylib_fonts[FONT_ID_BODY_24].font.texture, TEXTURE_FILTER_BILINEAR);
Raylib_fonts[FONT_ID_BODY_16] = (Raylib_Font) {
.font = LoadFontEx("Poppins-Regular.ttf", 32, 0, 400),
.fontId = FONT_ID_BODY_16,
};
SetTextureFilter(Raylib_fonts[FONT_ID_BODY_16].font.texture, TEXTURE_FILTER_BILINEAR);
while (!WindowShouldClose())
{
UpdateDrawFrame();
}
}