Updates simplifying border config

This commit is contained in:
Nic Barker 2025-02-03 14:07:39 +13:00
parent f7bdffcb8a
commit c71783a08c
11 changed files with 532 additions and 529 deletions

439
clay.h
View File

@ -53,9 +53,9 @@
#define CLAY_TEXT_CONFIG(...) Clay__StoreTextElementConfig(CLAY__CONFIG_WRAPPER(Clay_TextElementConfig, __VA_ARGS__))
#define CLAY_BORDER_OUTSIDE(...) CLAY__CONFIG_WRAPPER(Clay_BorderElementConfig, { .left = __VA_ARGS__, .right = __VA_ARGS__, .top = __VA_ARGS__, .bottom = __VA_ARGS__ })
#define CLAY_BORDER_OUTSIDE(widthValue) {widthValue, widthValue, widthValue, widthValue, 0}
#define CLAY_BORDER_ALL(...) CLAY__CONFIG_WRAPPER(Clay_BorderElementConfig, { .left = __VA_ARGS__, .right = __VA_ARGS__, .top = __VA_ARGS__, .bottom = __VA_ARGS__, .betweenChildren = __VA_ARGS__ })
#define CLAY_BORDER_ALL(widthValue) {widthValue, widthValue, widthValue, widthValue, widthValue}
#define CLAY_CORNER_RADIUS(radius) (CLAY__INIT(Clay_CornerRadius) { radius, radius, radius, radius })
@ -208,14 +208,13 @@ typedef struct {
typedef CLAY_PACKED_ENUM {
CLAY__ELEMENT_CONFIG_TYPE_NONE = 0,
CLAY__ELEMENT_CONFIG_TYPE_RECTANGLE = 1,
CLAY__ELEMENT_CONFIG_TYPE_BORDER = 2,
CLAY__ELEMENT_CONFIG_TYPE_FLOATING = 4,
CLAY__ELEMENT_CONFIG_TYPE_SCROLL = 8,
CLAY__ELEMENT_CONFIG_TYPE_IMAGE = 16,
CLAY__ELEMENT_CONFIG_TYPE_TEXT = 32,
CLAY__ELEMENT_CONFIG_TYPE_CUSTOM = 64,
CLAY__ELEMENT_CONFIG_TYPE_SHARED = 128,
CLAY__ELEMENT_CONFIG_TYPE_BORDER = 1,
CLAY__ELEMENT_CONFIG_TYPE_FLOATING = 2,
CLAY__ELEMENT_CONFIG_TYPE_SCROLL = 4,
CLAY__ELEMENT_CONFIG_TYPE_IMAGE = 8,
CLAY__ELEMENT_CONFIG_TYPE_TEXT = 16,
CLAY__ELEMENT_CONFIG_TYPE_CUSTOM = 32,
CLAY__ELEMENT_CONFIG_TYPE_SHARED = 64,
} Clay__ElementConfigType;
// Element Configs ---------------------------
@ -288,19 +287,8 @@ CLAY__WRAPPER_STRUCT(Clay_LayoutConfig);
extern Clay_LayoutConfig CLAY_LAYOUT_DEFAULT;
// Rectangle
// NOTE: Not declared in the typedef asan ifdef inside macro arguments is UB
typedef struct {
Clay_Color color;
#ifdef CLAY_EXTEND_CONFIG_RECTANGLE
CLAY_EXTEND_CONFIG_RECTANGLE
#endif
} Clay_RectangleElementConfig;
CLAY__WRAPPER_STRUCT(Clay_RectangleElementConfig);
// Text
typedef enum {
typedef CLAY_PACKED_ENUM {
CLAY_TEXT_WRAP_WORDS,
CLAY_TEXT_WRAP_NEWLINES,
CLAY_TEXT_WRAP_NONE,
@ -323,7 +311,7 @@ CLAY__WRAPPER_STRUCT(Clay_TextElementConfig);
// Image
typedef struct {
void *imageData;
void* imageData;
Clay_Dimensions sourceDimensions;
#ifdef CLAY_EXTEND_CONFIG_IMAGE
CLAY_EXTEND_CONFIG_IMAGE
@ -370,7 +358,7 @@ CLAY__WRAPPER_STRUCT(Clay_FloatingElementConfig);
// Custom
typedef struct {
#ifndef CLAY_EXTEND_CONFIG_CUSTOM
void *customData;
void* customData;
#else
CLAY_EXTEND_CONFIG_CUSTOM
#endif
@ -388,6 +376,7 @@ CLAY__WRAPPER_STRUCT(Clay_ScrollElementConfig);
// Scroll
typedef struct {
Clay_Color backgroundColor;
Clay_CornerRadius cornerRadius;
} Clay_SharedElementConfig;
@ -395,16 +384,16 @@ CLAY__WRAPPER_STRUCT(Clay_SharedElementConfig);
// Border
typedef struct {
uint32_t width;
Clay_Color color;
} Clay_Border;
uint16_t left;
uint16_t right;
uint16_t top;
uint16_t bottom;
uint16_t betweenChildren;
} Clay_BorderWidth;
typedef struct {
Clay_Border left;
Clay_Border right;
Clay_Border top;
Clay_Border bottom;
Clay_Border betweenChildren;
Clay_Color color;
Clay_BorderWidth width;
#ifdef CLAY_EXTEND_CONFIG_BORDER
CLAY_EXTEND_CONFIG_BORDER
#endif
@ -412,21 +401,46 @@ typedef struct {
CLAY__WRAPPER_STRUCT(Clay_BorderElementConfig);
typedef union {
Clay_RectangleElementConfig *rectangleElementConfig;
Clay_TextElementConfig *textElementConfig;
Clay_ImageElementConfig *imageElementConfig;
Clay_FloatingElementConfig *floatingElementConfig;
Clay_CustomElementConfig *customElementConfig;
Clay_ScrollElementConfig *scrollElementConfig;
Clay_BorderElementConfig *borderElementConfig;
Clay_SharedElementConfig *sharedElementConfig;
} Clay_ElementConfigUnion;
typedef struct {
Clay_StringSlice stringContents;
Clay_Color textColor;
uint16_t fontId;
uint16_t fontSize;
uint16_t letterSpacing;
uint16_t lineHeight;
} Clay_TextRenderData;
typedef struct {
Clay__ElementConfigType type;
Clay_ElementConfigUnion config;
} Clay_ElementConfig;
Clay_Color backgroundColor;
Clay_CornerRadius cornerRadius;
} Clay_RectangleRenderData;
typedef struct {
Clay_Color backgroundColor;
Clay_CornerRadius cornerRadius;
Clay_Dimensions sourceDimensions;
void* imageData;
} Clay_ImageRenderData;
typedef struct {
Clay_Color backgroundColor;
Clay_CornerRadius cornerRadius;
void* customData;
} Clay_CustomRenderData;
typedef struct {
Clay_Color color;
Clay_CornerRadius cornerRadius;
Clay_BorderWidth width;
} Clay_BorderRenderData;
typedef union {
Clay_RectangleRenderData rectangle;
Clay_TextRenderData text;
Clay_ImageRenderData image;
Clay_CustomRenderData custom;
Clay_BorderRenderData border;
} Clay_RenderData;
// Miscellaneous Structs & Enums ---------------------------------
typedef struct {
@ -460,11 +474,7 @@ typedef CLAY_PACKED_ENUM {
typedef struct {
Clay_BoundingBox boundingBox;
Clay_ElementConfigUnion config;
union {
Clay_StringSlice text; // TODO I wish there was a way to avoid having to have this on every render command
Clay_SharedElementConfig *sharedConfig;
} textOrSharedConfig;
Clay_RenderData renderData;
int32_t zIndex;
uint32_t id;
Clay_RenderCommandType commandType;
@ -491,13 +501,13 @@ typedef struct {
typedef struct {
Clay_ElementId id;
Clay_LayoutConfig layout;
Clay_RectangleElementConfig rectangle;
Clay_Color backgroundColor;
Clay_CornerRadius cornerRadius;
Clay_ImageElementConfig image;
Clay_FloatingElementConfig floating;
Clay_CustomElementConfig custom;
Clay_ScrollElementConfig scroll;
Clay_BorderElementConfig border;
Clay_SharedElementConfig shared;
} Clay_ElementDeclaration;
CLAY__WRAPPER_STRUCT(Clay_ElementDeclaration);
@ -568,6 +578,10 @@ uint32_t Clay__GetParentElementId(void);
extern Clay_Color Clay__debugViewHighlightColor;
extern uint32_t Clay__debugViewWidth;
inline Clay_BorderElementConfig Clay_BorderAll(Clay_Color color, uint16_t width) {
return (Clay_BorderElementConfig) { .color = color, .width = {width, width, width, width, width}};
}
#ifdef __cplusplus
}
#endif
@ -590,6 +604,9 @@ extern uint32_t Clay__debugViewWidth;
Clay_LayoutConfig CLAY_LAYOUT_DEFAULT = CLAY__DEFAULT_STRUCT;
Clay_Color Clay__Color_DEFAULT = CLAY__DEFAULT_STRUCT;
Clay_CornerRadius Clay__CornerRadius_DEFAULT = CLAY__DEFAULT_STRUCT;
#define CLAY__ARRAY_DEFINE_FUNCTIONS(typeName, arrayName) \
\
typedef struct \
@ -692,9 +709,7 @@ CLAY__ARRAY_DEFINE(bool, Clay__boolArray)
CLAY__ARRAY_DEFINE(int32_t, Clay__int32_tArray)
CLAY__ARRAY_DEFINE(char, Clay__charArray)
CLAY__ARRAY_DEFINE(Clay_ElementId, Clay__ElementIdArray)
CLAY__ARRAY_DEFINE(Clay_ElementConfig, Clay__ElementConfigArray)
CLAY__ARRAY_DEFINE(Clay_LayoutConfig, Clay__LayoutConfigArray)
CLAY__ARRAY_DEFINE(Clay_RectangleElementConfig, Clay__RectangleElementConfigArray)
CLAY__ARRAY_DEFINE(Clay_TextElementConfig, Clay__TextElementConfigArray)
CLAY__ARRAY_DEFINE(Clay_ImageElementConfig, Clay__ImageElementConfigArray)
CLAY__ARRAY_DEFINE(Clay_FloatingElementConfig, Clay__FloatingElementConfigArray)
@ -705,6 +720,23 @@ CLAY__ARRAY_DEFINE(Clay_String, Clay__StringArray)
CLAY__ARRAY_DEFINE(Clay_SharedElementConfig, Clay__SharedElementConfigArray)
CLAY__ARRAY_DEFINE_FUNCTIONS(Clay_RenderCommand, Clay_RenderCommandArray)
typedef union {
Clay_TextElementConfig *textElementConfig;
Clay_ImageElementConfig *imageElementConfig;
Clay_FloatingElementConfig *floatingElementConfig;
Clay_CustomElementConfig *customElementConfig;
Clay_ScrollElementConfig *scrollElementConfig;
Clay_BorderElementConfig *borderElementConfig;
Clay_SharedElementConfig *sharedElementConfig;
} Clay_ElementConfigUnion;
typedef struct {
Clay__ElementConfigType type;
Clay_ElementConfigUnion config;
} Clay_ElementConfig;
CLAY__ARRAY_DEFINE(Clay_ElementConfig, Clay__ElementConfigArray)
typedef struct {
Clay_Dimensions dimensions;
Clay_String line;
@ -726,7 +758,7 @@ typedef struct {
uint16_t length;
} Clay__LayoutElementChildren;
typedef struct {
typedef struct ee {
union {
Clay__LayoutElementChildren children;
Clay__TextElementData *textElementData;
@ -735,7 +767,6 @@ typedef struct {
Clay_Dimensions minDimensions;
Clay_LayoutConfig *layoutConfig;
Clay__ElementConfigArraySlice elementConfigs;
uint32_t configsEnabled;
uint32_t id;
} Clay_LayoutElement;
@ -851,7 +882,6 @@ struct Clay_Context {
// Configs
Clay__LayoutConfigArray layoutConfigs;
Clay__ElementConfigArray elementConfigs;
Clay__RectangleElementConfigArray rectangleElementConfigs;
Clay__TextElementConfigArray textElementConfigs;
Clay__ImageElementConfigArray imageElementConfigs;
Clay__FloatingElementConfigArray floatingElementConfigs;
@ -919,12 +949,7 @@ uint32_t Clay__GetParentElementId(void) {
return Clay_LayoutElementArray_Get(&context->layoutElements, Clay__int32_tArray_GetValue(&context->openLayoutElementStack, context->openLayoutElementStack.length - 2))->id;
}
bool Clay__ElementHasConfig(Clay_LayoutElement *element, Clay__ElementConfigType type) {
return (element->configsEnabled & type);
}
Clay_LayoutConfig * Clay__StoreLayoutConfig(Clay_LayoutConfig config) { return Clay_GetCurrentContext()->booleanWarnings.maxElementsExceeded ? &CLAY_LAYOUT_DEFAULT : Clay__LayoutConfigArray_Add(&Clay_GetCurrentContext()->layoutConfigs, config); }
Clay_RectangleElementConfig * Clay__StoreRectangleElementConfig(Clay_RectangleElementConfig config) { return Clay_GetCurrentContext()->booleanWarnings.maxElementsExceeded ? &Clay_RectangleElementConfig_DEFAULT : Clay__RectangleElementConfigArray_Add(&Clay_GetCurrentContext()->rectangleElementConfigs, config); }
Clay_TextElementConfig * Clay__StoreTextElementConfig(Clay_TextElementConfig config) { return Clay_GetCurrentContext()->booleanWarnings.maxElementsExceeded ? &Clay_TextElementConfig_DEFAULT : Clay__TextElementConfigArray_Add(&Clay_GetCurrentContext()->textElementConfigs, config); }
Clay_ImageElementConfig * Clay__StoreImageElementConfig(Clay_ImageElementConfig config) { return Clay_GetCurrentContext()->booleanWarnings.maxElementsExceeded ? &Clay_ImageElementConfig_DEFAULT : Clay__ImageElementConfigArray_Add(&Clay_GetCurrentContext()->imageElementConfigs, config); }
Clay_FloatingElementConfig * Clay__StoreFloatingElementConfig(Clay_FloatingElementConfig config) { return Clay_GetCurrentContext()->booleanWarnings.maxElementsExceeded ? &Clay_FloatingElementConfig_DEFAULT : Clay__FloatingElementConfigArray_Add(&Clay_GetCurrentContext()->floatingElementConfigs, config); }
@ -940,7 +965,6 @@ Clay_ElementConfig Clay__AttachElementConfig(Clay_ElementConfigUnion config, Cla
}
Clay_LayoutElement *openLayoutElement = Clay__GetOpenLayoutElement();
openLayoutElement->elementConfigs.length++;
openLayoutElement->configsEnabled |= type;
return *Clay__ElementConfigArray_Add(&context->elementConfigs, CLAY__INIT(Clay_ElementConfig) { .type = type, .config = config });
}
@ -954,46 +978,6 @@ Clay_ElementConfigUnion Clay__FindElementConfigWithType(Clay_LayoutElement *elem
return CLAY__INIT(Clay_ElementConfigUnion) { NULL };
}
Clay_ElementConfig Clay__CurrentConfigUnion(Clay__ElementConfigType type) {
Clay_Context *context = Clay_GetCurrentContext();
Clay_LayoutElement *openElement = Clay__GetOpenLayoutElement();
if (Clay__ElementHasConfig(openElement, type)) {
return CLAY__INIT(Clay_ElementConfig) { .type = type, .config = Clay__FindElementConfigWithType(openElement, type) };
}
// Unhandled: structural changes to element
switch (type) {
case CLAY__ELEMENT_CONFIG_TYPE_NONE:
return CLAY__INIT(Clay_ElementConfig) CLAY__DEFAULT_STRUCT;
case CLAY__ELEMENT_CONFIG_TYPE_RECTANGLE:
return Clay__AttachElementConfig(CLAY__INIT(Clay_ElementConfigUnion) { .rectangleElementConfig = Clay__RectangleElementConfigArray_Add(&Clay_GetCurrentContext()->rectangleElementConfigs, CLAY__INIT(Clay_RectangleElementConfig) {CLAY__DEFAULT_STRUCT}) }, type);
case CLAY__ELEMENT_CONFIG_TYPE_TEXT:
return Clay__AttachElementConfig(CLAY__INIT(Clay_ElementConfigUnion) { .textElementConfig = Clay__TextElementConfigArray_Add(&Clay_GetCurrentContext()->textElementConfigs, CLAY__INIT(Clay_TextElementConfig) {CLAY__DEFAULT_STRUCT}) }, type);
case CLAY__ELEMENT_CONFIG_TYPE_IMAGE:
return Clay__AttachElementConfig(CLAY__INIT(Clay_ElementConfigUnion) { .imageElementConfig = Clay__ImageElementConfigArray_Add(&Clay_GetCurrentContext()->imageElementConfigs, CLAY__INIT(Clay_ImageElementConfig)CLAY__DEFAULT_STRUCT) }, type);
case CLAY__ELEMENT_CONFIG_TYPE_FLOATING:
return Clay__AttachElementConfig(CLAY__INIT(Clay_ElementConfigUnion) { .floatingElementConfig = Clay__FloatingElementConfigArray_Add(&Clay_GetCurrentContext()->floatingElementConfigs, CLAY__INIT(Clay_FloatingElementConfig) {CLAY__DEFAULT_STRUCT}) }, type);
case CLAY__ELEMENT_CONFIG_TYPE_CUSTOM:
Clay__int32_tArray_Add(&context->imageElementPointers, context->layoutElements.length - 1);return Clay__AttachElementConfig(CLAY__INIT(Clay_ElementConfigUnion) { .customElementConfig = Clay__CustomElementConfigArray_Add(&Clay_GetCurrentContext()->customElementConfigs, CLAY__INIT(Clay_CustomElementConfig)CLAY__DEFAULT_STRUCT) }, type);
case CLAY__ELEMENT_CONFIG_TYPE_SCROLL:
return Clay__AttachElementConfig(CLAY__INIT(Clay_ElementConfigUnion) { .scrollElementConfig = Clay__ScrollElementConfigArray_Add(&Clay_GetCurrentContext()->scrollElementConfigs, CLAY__INIT(Clay_ScrollElementConfig) CLAY__DEFAULT_STRUCT) }, type);
case CLAY__ELEMENT_CONFIG_TYPE_BORDER:
return Clay__AttachElementConfig(CLAY__INIT(Clay_ElementConfigUnion) { .borderElementConfig = Clay__BorderElementConfigArray_Add(&Clay_GetCurrentContext()->borderElementConfigs, CLAY__INIT(Clay_BorderElementConfig) {CLAY__DEFAULT_STRUCT}) }, type);
case CLAY__ELEMENT_CONFIG_TYPE_SHARED:
return Clay__AttachElementConfig(CLAY__INIT(Clay_ElementConfigUnion) { .sharedElementConfig = Clay__SharedElementConfigArray_Add(&Clay_GetCurrentContext()->sharedElementConfigs, CLAY__INIT(Clay_SharedElementConfig) {CLAY__DEFAULT_STRUCT}) }, type);
}
return CLAY__INIT(Clay_ElementConfig) CLAY__DEFAULT_STRUCT;
}
Clay_RectangleElementConfig * Clay_CurrentConfigRectangle(void) { return Clay__CurrentConfigUnion(CLAY__ELEMENT_CONFIG_TYPE_RECTANGLE).config.rectangleElementConfig; }
Clay_TextElementConfig * Clay_CurrentConfigText(void) { return Clay__CurrentConfigUnion(CLAY__ELEMENT_CONFIG_TYPE_TEXT).config.textElementConfig; }
Clay_ImageElementConfig * Clay_CurrentConfigImage(void) { return Clay__CurrentConfigUnion(CLAY__ELEMENT_CONFIG_TYPE_IMAGE).config.imageElementConfig; }
Clay_FloatingElementConfig * Clay_CurrentConfigFloating(void) { return Clay__CurrentConfigUnion(CLAY__ELEMENT_CONFIG_TYPE_FLOATING).config.floatingElementConfig; }
Clay_CustomElementConfig * Clay_CurrentConfigCustom(void) { return Clay__CurrentConfigUnion(CLAY__ELEMENT_CONFIG_TYPE_CUSTOM).config.customElementConfig; }
Clay_ScrollElementConfig * Clay_CurrentConfigScroll(void) { return Clay__CurrentConfigUnion(CLAY__ELEMENT_CONFIG_TYPE_SCROLL).config.scrollElementConfig; }
Clay_BorderElementConfig * Clay_CurrentConfigBorder(void) { return Clay__CurrentConfigUnion(CLAY__ELEMENT_CONFIG_TYPE_BORDER).config.borderElementConfig; }
Clay_SharedElementConfig * Clay_CurrentConfigShared(void) { return Clay__CurrentConfigUnion(CLAY__ELEMENT_CONFIG_TYPE_SHARED).config.sharedElementConfig; }
Clay_ElementId Clay__HashNumber(const uint32_t offset, const uint32_t seed) {
uint32_t hash = seed;
hash += (offset + 48);
@ -1318,6 +1302,15 @@ void Clay__GenerateIdForAnonymousElement(Clay_LayoutElement *openLayoutElement)
Clay__StringArray_Add(&context->layoutElementIdStrings, elementId.stringId);
}
bool Clay__ElementHasConfig(Clay_LayoutElement *layoutElement, Clay__ElementConfigType type) {
for (int32_t i = 0; i < layoutElement->elementConfigs.length; i++) {
if (Clay__ElementConfigArraySlice_Get(&layoutElement->elementConfigs, i)->type == type) {
return true;
}
}
return false;
}
void Clay__CloseElement(void) {
Clay_Context* context = Clay_GetCurrentContext();
if (context->booleanWarnings.maxElementsExceeded) {
@ -1327,11 +1320,14 @@ void Clay__CloseElement(void) {
Clay_LayoutConfig *layoutConfig = openLayoutElement->layoutConfig;
bool elementHasScrollHorizontal = false;
bool elementHasScrollVertical = false;
if (Clay__ElementHasConfig(openLayoutElement, CLAY__ELEMENT_CONFIG_TYPE_SCROLL)) {
Clay_ScrollElementConfig *scrollConfig = Clay__FindElementConfigWithType(openLayoutElement, CLAY__ELEMENT_CONFIG_TYPE_SCROLL).scrollElementConfig;
elementHasScrollHorizontal = scrollConfig->horizontal;
elementHasScrollVertical = scrollConfig->vertical;
context->openClipElementStack.length--;
for (int32_t i = 0; i < openLayoutElement->elementConfigs.length; i++) {
Clay_ElementConfig *config = Clay__ElementConfigArraySlice_Get(&openLayoutElement->elementConfigs, i);
if (config->type == CLAY__ELEMENT_CONFIG_TYPE_SCROLL) {
elementHasScrollHorizontal = config->config.scrollElementConfig->horizontal;
elementHasScrollVertical = config->config.scrollElementConfig->vertical;
context->openClipElementStack.length--;
break;
}
}
// Attach children to the current open element
@ -1525,7 +1521,6 @@ void Clay__OpenTextElement(Clay_String text, Clay_TextElementConfig *textConfig)
.length = 1,
.internalArray = Clay__ElementConfigArray_Add(&context->elementConfigs, CLAY__INIT(Clay_ElementConfig) { .type = CLAY__ELEMENT_CONFIG_TYPE_TEXT, .config = { .textElementConfig = textConfig }})
};
textElement->configsEnabled |= CLAY__ELEMENT_CONFIG_TYPE_TEXT;
textElement->layoutConfig = &CLAY_LAYOUT_DEFAULT;
}
@ -1545,8 +1540,18 @@ void Clay__ConfigureOpenElement(const Clay_ElementDeclaration declaration) {
}
openLayoutElement->elementConfigs.internalArray = &context->elementConfigs.internalArray[context->elementConfigs.length];
if (!Clay__MemCmp((char *)(&declaration.rectangle), (char *)(&Clay_RectangleElementConfig_DEFAULT), sizeof(Clay_RectangleElementConfig))) {
Clay__AttachElementConfig(CLAY__INIT(Clay_ElementConfigUnion) { .rectangleElementConfig = Clay__StoreRectangleElementConfig(declaration.rectangle) }, CLAY__ELEMENT_CONFIG_TYPE_RECTANGLE);
Clay_SharedElementConfig *sharedConfig = NULL;
if (!Clay__MemCmp((char *)(&declaration.backgroundColor), (char *)(&Clay__Color_DEFAULT), sizeof(Clay_Color))) {
sharedConfig = Clay__StoreSharedElementConfig((Clay_SharedElementConfig) { .backgroundColor = declaration.backgroundColor });
Clay__AttachElementConfig(CLAY__INIT(Clay_ElementConfigUnion) { .sharedElementConfig = sharedConfig }, CLAY__ELEMENT_CONFIG_TYPE_SHARED);
}
if (!Clay__MemCmp((char *)(&declaration.cornerRadius), (char *)(&Clay__CornerRadius_DEFAULT), sizeof(Clay_CornerRadius))) {
if (sharedConfig) {
sharedConfig->cornerRadius = declaration.cornerRadius;
} else {
sharedConfig = Clay__StoreSharedElementConfig((Clay_SharedElementConfig) { .cornerRadius = declaration.cornerRadius });
Clay__AttachElementConfig(CLAY__INIT(Clay_ElementConfigUnion) { .sharedElementConfig = sharedConfig }, CLAY__ELEMENT_CONFIG_TYPE_SHARED);
}
}
if (!Clay__MemCmp((char *)(&declaration.image), (char *)(&Clay_ImageElementConfig_DEFAULT), sizeof(Clay_ImageElementConfig))) {
Clay__AttachElementConfig(CLAY__INIT(Clay_ElementConfigUnion) { .imageElementConfig = Clay__StoreImageElementConfig(declaration.image) }, CLAY__ELEMENT_CONFIG_TYPE_IMAGE);
@ -1587,9 +1592,6 @@ void Clay__ConfigureOpenElement(const Clay_ElementDeclaration declaration) {
if (!Clay__MemCmp((char *)(&declaration.custom), (char *)(&Clay_CustomElementConfig_DEFAULT), sizeof(Clay_CustomElementConfig))) {
Clay__AttachElementConfig(CLAY__INIT(Clay_ElementConfigUnion) { .customElementConfig = Clay__StoreCustomElementConfig(declaration.custom) }, CLAY__ELEMENT_CONFIG_TYPE_CUSTOM);
}
if (!Clay__MemCmp((char *)(&declaration.shared), (char *)(&Clay_SharedElementConfig_DEFAULT), sizeof(Clay_SharedElementConfig))) {
Clay__AttachElementConfig(CLAY__INIT(Clay_ElementConfigUnion) { .sharedElementConfig = Clay__StoreSharedElementConfig(declaration.shared) }, CLAY__ELEMENT_CONFIG_TYPE_SHARED);
}
if (!Clay__MemCmp((char *)(&declaration.scroll), (char *)(&Clay_ScrollElementConfig_DEFAULT), sizeof(Clay_ScrollElementConfig))) {
Clay__AttachElementConfig(CLAY__INIT(Clay_ElementConfigUnion) { .scrollElementConfig = Clay__StoreScrollElementConfig(declaration.scroll) }, CLAY__ELEMENT_CONFIG_TYPE_SCROLL);
Clay__int32_tArray_Add(&context->openClipElementStack, (int)openLayoutElement->id);
@ -1627,7 +1629,6 @@ void Clay__InitializeEphemeralMemory(Clay_Context* context) {
context->layoutConfigs = Clay__LayoutConfigArray_Allocate_Arena(maxElementCount, arena);
context->elementConfigs = Clay__ElementConfigArray_Allocate_Arena(maxElementCount, arena);
context->rectangleElementConfigs = Clay__RectangleElementConfigArray_Allocate_Arena(maxElementCount, arena);
context->textElementConfigs = Clay__TextElementConfigArray_Allocate_Arena(maxElementCount, arena);
context->imageElementConfigs = Clay__ImageElementConfigArray_Allocate_Arena(maxElementCount, arena);
context->floatingElementConfigs = Clay__FloatingElementConfigArray_Allocate_Arena(maxElementCount, arena);
@ -1673,7 +1674,6 @@ void Clay__InitializePersistentMemory(Clay_Context* context) {
context->arenaResetOffset = arena->nextAllocation;
}
void Clay__CompressChildrenAlongAxis(bool xAxis, float totalSizeToDistribute, Clay__int32_tArray resizableContainerBuffer) {
Clay_Context* context = Clay_GetCurrentContext();
Clay__int32_tArray largestContainers = context->openClipElementStack;
@ -1684,9 +1684,6 @@ void Clay__CompressChildrenAlongAxis(bool xAxis, float totalSizeToDistribute, Cl
float targetSize = 0;
for (int32_t i = 0; i < resizableContainerBuffer.length; ++i) {
Clay_LayoutElement *childElement = Clay_LayoutElementArray_Get(&context->layoutElements, Clay__int32_tArray_GetValue(&resizableContainerBuffer, i));
if (!xAxis && Clay__ElementHasConfig(childElement, CLAY__ELEMENT_CONFIG_TYPE_IMAGE)) {
continue;
}
float childSize = xAxis ? childElement->dimensions.width : childElement->dimensions.height;
if ((childSize - largestSize) < 0.1 && (childSize - largestSize) > -0.1) {
Clay__int32_tArray_Add(&largestContainers, Clay__int32_tArray_GetValue(&resizableContainerBuffer, i));
@ -1777,7 +1774,11 @@ void Clay__SizeContainersAlongAxis(bool xAxis) {
Clay__int32_tArray_Add(&bfsBuffer, childElementIndex);
}
if (childSizing.type != CLAY__SIZING_TYPE_PERCENT && childSizing.type != CLAY__SIZING_TYPE_FIXED && (!Clay__ElementHasConfig(childElement, CLAY__ELEMENT_CONFIG_TYPE_TEXT) || (Clay__FindElementConfigWithType(childElement, CLAY__ELEMENT_CONFIG_TYPE_TEXT).textElementConfig->wrapMode == CLAY_TEXT_WRAP_WORDS))) {
if (childSizing.type != CLAY__SIZING_TYPE_PERCENT
&& childSizing.type != CLAY__SIZING_TYPE_FIXED
&& (!Clay__ElementHasConfig(childElement, CLAY__ELEMENT_CONFIG_TYPE_TEXT) || (Clay__FindElementConfigWithType(childElement, CLAY__ELEMENT_CONFIG_TYPE_TEXT).textElementConfig->wrapMode == CLAY_TEXT_WRAP_WORDS)) // todo too many loops
&& (xAxis || !Clay__ElementHasConfig(childElement, CLAY__ELEMENT_CONFIG_TYPE_IMAGE))
) {
Clay__int32_tArray_Add(&resizableContainerBuffer, childElementIndex);
}
@ -2148,7 +2149,6 @@ void Clay__CalculateFinalLayout(void) {
}
Clay__AddRenderCommand(CLAY__INIT(Clay_RenderCommand) {
.boundingBox = clipHashMapItem->boundingBox,
.config = { .scrollElementConfig = Clay__StoreScrollElementConfig(CLAY__INIT(Clay_ScrollElementConfig)CLAY__DEFAULT_STRUCT) },
.zIndex = root->zIndex,
.id = Clay__RehashWithNumber(rootElement->id, 10), // TODO need a better strategy for managing derived ids
.commandType = CLAY_RENDER_COMMAND_TYPE_SCISSOR_START,
@ -2227,13 +2227,20 @@ void Clay__CalculateFinalLayout(void) {
sortMax--;
}
bool emitRectangle;
// Create the render commands for this element
Clay_SharedElementConfig *sharedConfig = Clay__FindElementConfigWithType(currentElement, CLAY__ELEMENT_CONFIG_TYPE_SHARED).sharedElementConfig;
if (sharedConfig) {
emitRectangle = true;
}
else if (!sharedConfig) {
emitRectangle = false;
sharedConfig = &Clay_SharedElementConfig_DEFAULT;
}
for (int32_t elementConfigIndex = 0; elementConfigIndex < currentElement->elementConfigs.length; ++elementConfigIndex) {
Clay_ElementConfig *elementConfig = Clay__ElementConfigArraySlice_Get(&currentElement->elementConfigs, sortedConfigIndexes[elementConfigIndex]);
Clay_RenderCommand renderCommand = {
.boundingBox = currentElementBoundingBox,
.config = elementConfig->config,
.textOrSharedConfig = { .sharedConfig = Clay__ElementHasConfig(currentElement, CLAY__ELEMENT_CONFIG_TYPE_SHARED) ? Clay__FindElementConfigWithType(currentElement, CLAY__ELEMENT_CONFIG_TYPE_SHARED).sharedElementConfig : &Clay_SharedElementConfig_DEFAULT },
.id = currentElement->id,
};
@ -2241,27 +2248,27 @@ void Clay__CalculateFinalLayout(void) {
// Culling - Don't bother to generate render commands for rectangles entirely outside the screen - this won't stop their children from being rendered if they overflow
bool shouldRender = !offscreen;
switch (elementConfig->type) {
case CLAY__ELEMENT_CONFIG_TYPE_RECTANGLE: {
renderCommand.commandType = CLAY_RENDER_COMMAND_TYPE_RECTANGLE;
break;
}
case CLAY__ELEMENT_CONFIG_TYPE_FLOATING:
case CLAY__ELEMENT_CONFIG_TYPE_SHARED:
case CLAY__ELEMENT_CONFIG_TYPE_BORDER: {
shouldRender = false;
break;
}
case CLAY__ELEMENT_CONFIG_TYPE_FLOATING: {
renderCommand.commandType = CLAY_RENDER_COMMAND_TYPE_NONE;
shouldRender = false;
break;
}
case CLAY__ELEMENT_CONFIG_TYPE_SCROLL: {
renderCommand.commandType = CLAY_RENDER_COMMAND_TYPE_SCISSOR_START;
shouldRender = true;
break;
}
case CLAY__ELEMENT_CONFIG_TYPE_IMAGE: {
renderCommand.commandType = CLAY_RENDER_COMMAND_TYPE_IMAGE;
renderCommand.renderData = (Clay_RenderData) {
.image = {
.backgroundColor = emitRectangle ? sharedConfig->backgroundColor : CLAY__INIT(Clay_Color) { 255, 255, 255, 255 },
.cornerRadius = sharedConfig->cornerRadius,
.sourceDimensions = elementConfig->config.imageElementConfig->sourceDimensions,
.imageData = elementConfig->config.imageElementConfig->imageData,
}
};
emitRectangle = false;
break;
}
case CLAY__ELEMENT_CONFIG_TYPE_TEXT: {
@ -2282,9 +2289,15 @@ void Clay__CalculateFinalLayout(void) {
continue;
}
Clay__AddRenderCommand(CLAY__INIT(Clay_RenderCommand) {
.boundingBox = { currentElementBoundingBox.x, currentElementBoundingBox.y + yPosition, wrappedLine.dimensions.width, wrappedLine.dimensions.height }, // TODO width
.config = configUnion,
.textOrSharedConfig = { .text = CLAY__INIT(Clay_StringSlice) { .length = wrappedLine.line.length, .chars = wrappedLine.line.chars, .baseChars = currentElement->childrenOrTextContent.textElementData->text.chars } },
.boundingBox = { currentElementBoundingBox.x, currentElementBoundingBox.y + yPosition, wrappedLine.dimensions.width, wrappedLine.dimensions.height },
.renderData = { .text = {
.stringContents = CLAY__INIT(Clay_StringSlice) { .length = wrappedLine.line.length, .chars = wrappedLine.line.chars, .baseChars = currentElement->childrenOrTextContent.textElementData->text.chars },
.textColor = textElementConfig->textColor,
.fontId = textElementConfig->fontId,
.fontSize = textElementConfig->fontSize,
.letterSpacing = textElementConfig->letterSpacing,
.lineHeight = textElementConfig->lineHeight,
}},
.zIndex = root->zIndex,
.id = Clay__HashNumber(lineIndex, currentElement->id).id,
.commandType = CLAY_RENDER_COMMAND_TYPE_TEXT,
@ -2299,6 +2312,14 @@ void Clay__CalculateFinalLayout(void) {
}
case CLAY__ELEMENT_CONFIG_TYPE_CUSTOM: {
renderCommand.commandType = CLAY_RENDER_COMMAND_TYPE_CUSTOM;
renderCommand.renderData = (Clay_RenderData) {
.custom = {
.backgroundColor = sharedConfig->backgroundColor,
.cornerRadius = sharedConfig->cornerRadius,
.customData = elementConfig->config.customElementConfig->customData,
}
};
emitRectangle = false;
break;
}
default: break;
@ -2313,6 +2334,19 @@ void Clay__CalculateFinalLayout(void) {
}
}
if (emitRectangle) {
Clay__AddRenderCommand(CLAY__INIT(Clay_RenderCommand) {
.boundingBox = currentElementBoundingBox,
.renderData = { .rectangle = {
.backgroundColor = sharedConfig->backgroundColor,
.cornerRadius = sharedConfig->cornerRadius,
}},
.zIndex = root->zIndex,
.id = currentElement->id,
.commandType = CLAY_RENDER_COMMAND_TYPE_RECTANGLE,
});
}
// Setup initial on-axis alignment
if (!Clay__ElementHasConfig(currentElementTreeNode->layoutElement, CLAY__ELEMENT_CONFIG_TYPE_TEXT)) {
Clay_Dimensions contentSize = {0,0};
@ -2380,14 +2414,16 @@ void Clay__CalculateFinalLayout(void) {
Clay_BorderElementConfig *borderConfig = Clay__FindElementConfigWithType(currentElement, CLAY__ELEMENT_CONFIG_TYPE_BORDER).borderElementConfig;
Clay_RenderCommand renderCommand = {
.boundingBox = currentElementBoundingBox,
.config = { .borderElementConfig = borderConfig },
.textOrSharedConfig = { .sharedConfig = sharedConfig },
.renderData = { .border = {
.color = borderConfig->color,
.cornerRadius = sharedConfig->cornerRadius,
.width = borderConfig->width
}},
.id = Clay__RehashWithNumber(currentElement->id, 4),
.commandType = CLAY_RENDER_COMMAND_TYPE_BORDER,
};
Clay__AddRenderCommand(renderCommand);
if (borderConfig->betweenChildren.width > 0 && borderConfig->betweenChildren.color.a > 0) {
Clay_RectangleElementConfig *rectangleConfig = Clay__StoreRectangleElementConfig(CLAY__INIT(Clay_RectangleElementConfig) {.color = borderConfig->betweenChildren.color});
if (borderConfig->width.betweenChildren > 0 && borderConfig->color.a > 0) {
float halfGap = layoutConfig->childGap / 2;
Clay_Vector2 borderOffset = { (float)layoutConfig->padding.left - halfGap, (float)layoutConfig->padding.top - halfGap };
if (layoutConfig->layoutDirection == CLAY_LEFT_TO_RIGHT) {
@ -2395,9 +2431,10 @@ void Clay__CalculateFinalLayout(void) {
Clay_LayoutElement *childElement = Clay_LayoutElementArray_Get(&context->layoutElements, currentElement->childrenOrTextContent.children.elements[i]);
if (i > 0) {
Clay__AddRenderCommand(CLAY__INIT(Clay_RenderCommand) {
.boundingBox = { currentElementBoundingBox.x + borderOffset.x + scrollOffset.x, currentElementBoundingBox.y + scrollOffset.y, (float)borderConfig->betweenChildren.width, currentElement->dimensions.height },
.config = { rectangleConfig },
.textOrSharedConfig = { .sharedConfig = sharedConfig },
.boundingBox = { currentElementBoundingBox.x + borderOffset.x + scrollOffset.x, currentElementBoundingBox.y + scrollOffset.y, (float)borderConfig->width.betweenChildren, currentElement->dimensions.height },
.renderData = { .rectangle = {
.backgroundColor = borderConfig->color,
} },
.id = Clay__RehashWithNumber(currentElement->id, 5 + i),
.commandType = CLAY_RENDER_COMMAND_TYPE_RECTANGLE,
});
@ -2409,9 +2446,10 @@ void Clay__CalculateFinalLayout(void) {
Clay_LayoutElement *childElement = Clay_LayoutElementArray_Get(&context->layoutElements, currentElement->childrenOrTextContent.children.elements[i]);
if (i > 0) {
Clay__AddRenderCommand(CLAY__INIT(Clay_RenderCommand) {
.boundingBox = { currentElementBoundingBox.x + scrollOffset.x, currentElementBoundingBox.y + borderOffset.y + scrollOffset.y, currentElement->dimensions.width, (float)borderConfig->betweenChildren.width },
.config = { rectangleConfig },
.textOrSharedConfig = { .sharedConfig = sharedConfig },
.boundingBox = { currentElementBoundingBox.x + scrollOffset.x, currentElementBoundingBox.y + borderOffset.y + scrollOffset.y, currentElement->dimensions.width, (float)borderConfig->width.betweenChildren },
.renderData = { .rectangle = {
.backgroundColor = borderConfig->color,
} },
.id = Clay__RehashWithNumber(currentElement->id, 5 + i),
.commandType = CLAY_RENDER_COMMAND_TYPE_RECTANGLE,
});
@ -2519,7 +2557,7 @@ typedef struct {
Clay__DebugElementConfigTypeLabelConfig Clay__DebugGetElementConfigTypeLabel(Clay__ElementConfigType type) {
switch (type) {
case CLAY__ELEMENT_CONFIG_TYPE_RECTANGLE: return CLAY__INIT(Clay__DebugElementConfigTypeLabelConfig) { CLAY_STRING("Rectangle"), {243,134,48,255} };
case CLAY__ELEMENT_CONFIG_TYPE_SHARED: return CLAY__INIT(Clay__DebugElementConfigTypeLabelConfig) { CLAY_STRING("Shared"), {243,134,48,255} };
case CLAY__ELEMENT_CONFIG_TYPE_TEXT: return CLAY__INIT(Clay__DebugElementConfigTypeLabelConfig) { CLAY_STRING("Text"), {105,210,231,255} };
case CLAY__ELEMENT_CONFIG_TYPE_IMAGE: return CLAY__INIT(Clay__DebugElementConfigTypeLabelConfig) { CLAY_STRING("Image"), {121,189,154,255} };
case CLAY__ELEMENT_CONFIG_TYPE_FLOATING: return CLAY__INIT(Clay__DebugElementConfigTypeLabelConfig) { CLAY_STRING("Floating"), {250,105,0,255} };
@ -2552,7 +2590,7 @@ Clay__RenderDebugLayoutData Clay__RenderDebugLayoutElementsList(int32_t initialR
context->treeNodeVisited.internalArray[0] = false;
if (rootIndex > 0) {
CLAY({ .id = CLAY_IDI("Clay__DebugView_EmptyRowOuter", rootIndex), .layout = { .sizing = {.width = CLAY_SIZING_GROW(0)}, .padding = {CLAY__DEBUGVIEW_INDENT_WIDTH / 2, 0} } }) {
CLAY({ .id = CLAY_IDI("Clay__DebugView_EmptyRow", rootIndex), .layout = { .sizing = { .width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_FIXED((float)CLAY__DEBUGVIEW_ROW_HEIGHT) }}, .border = { .top = { .width = 1, .color = CLAY__DEBUGVIEW_COLOR_3 } } }) {}
CLAY({ .id = CLAY_IDI("Clay__DebugView_EmptyRow", rootIndex), .layout = { .sizing = { .width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_FIXED((float)CLAY__DEBUGVIEW_ROW_HEIGHT) }}, .border = { .color = CLAY__DEBUGVIEW_COLOR_3, .width = { .top = 1 } } }) {}
}
layoutData.rowCount++;
}
@ -2588,25 +2626,25 @@ Clay__RenderDebugLayoutData Clay__RenderDebugLayoutElementsList(int32_t initialR
CLAY({
.id = CLAY_IDI("Clay__DebugView_CollapseElement", currentElement->id),
.layout = { .sizing = {CLAY_SIZING_FIXED(16), CLAY_SIZING_FIXED(16)}, .childAlignment = { CLAY_ALIGN_X_CENTER, CLAY_ALIGN_Y_CENTER} },
.border = CLAY_BORDER_OUTSIDE({ 1, CLAY__DEBUGVIEW_COLOR_3 }),
.shared = { .cornerRadius = CLAY_CORNER_RADIUS(4) }
.cornerRadius = CLAY_CORNER_RADIUS(4),
.border = { .color = CLAY__DEBUGVIEW_COLOR_3, .width = {1, 1, 1, 1} },
}) {
CLAY_TEXT((currentElementData && currentElementData->debugData->collapsed) ? CLAY_STRING("+") : CLAY_STRING("-"), CLAY_TEXT_CONFIG({ .textColor = CLAY__DEBUGVIEW_COLOR_4, .fontSize = 16 }));
}
} else { // Square dot for empty containers
CLAY({ .layout = { .sizing = {CLAY_SIZING_FIXED(16), CLAY_SIZING_FIXED(16)}, .childAlignment = { CLAY_ALIGN_X_CENTER, CLAY_ALIGN_Y_CENTER } } }) {
CLAY({ .layout = { .sizing = {CLAY_SIZING_FIXED(8), CLAY_SIZING_FIXED(8)} }, .rectangle = { .color = CLAY__DEBUGVIEW_COLOR_3 }, .shared = { .cornerRadius = CLAY_CORNER_RADIUS(2) } }) {}
CLAY({ .layout = { .sizing = {CLAY_SIZING_FIXED(8), CLAY_SIZING_FIXED(8)} }, .backgroundColor = CLAY__DEBUGVIEW_COLOR_3, .cornerRadius = CLAY_CORNER_RADIUS(2) }) {}
}
}
// Collisions and offscreen info
if (currentElementData) {
if (currentElementData->debugData->collision) {
CLAY({ .layout = { .padding = { 8, 8, 2, 2 } }, .border = CLAY_BORDER_OUTSIDE({ 1, (CLAY__INIT(Clay_Color){177, 147, 8, 255}) }) }) {
CLAY({ .layout = { .padding = { 8, 8, 2, 2 }}, .border = { .color = {177, 147, 8, 255}, .width = {1, 1, 1, 1} } }) {
CLAY_TEXT(CLAY_STRING("Duplicate ID"), CLAY_TEXT_CONFIG({ .textColor = CLAY__DEBUGVIEW_COLOR_3, .fontSize = 16 }));
}
}
if (offscreen) {
CLAY({ .layout = { .padding = { 8, 8, 2, 2 } }, .border = CLAY_BORDER_OUTSIDE({ 1, CLAY__DEBUGVIEW_COLOR_3 }) }) {
CLAY({ .layout = { .padding = { 8, 8, 2, 2 } }, .border = { .color = CLAY__DEBUGVIEW_COLOR_3, .width = { 1, 1, 1, 1 } } }) {
CLAY_TEXT(CLAY_STRING("Offscreen"), CLAY_TEXT_CONFIG({ .textColor = CLAY__DEBUGVIEW_COLOR_3, .fontSize = 16 }));
}
}
@ -2620,7 +2658,7 @@ Clay__RenderDebugLayoutData Clay__RenderDebugLayoutElementsList(int32_t initialR
Clay__DebugElementConfigTypeLabelConfig config = Clay__DebugGetElementConfigTypeLabel(elementConfig->type);
Clay_Color backgroundColor = config.color;
backgroundColor.a = 90;
CLAY({ .layout = { .padding = { 8, 8, 2, 2 } }, .rectangle = { .color = backgroundColor }, .border = CLAY_BORDER_OUTSIDE({ 1, config.color }), .shared = { .cornerRadius = CLAY_CORNER_RADIUS(4) } }) {
CLAY({ .layout = { .padding = { 8, 8, 2, 2 } }, .backgroundColor = backgroundColor, .cornerRadius = CLAY_CORNER_RADIUS(4), .border = { .color = config.color, .width = { 1, 1, 1, 1 } } }) {
CLAY_TEXT(config.label, CLAY_TEXT_CONFIG({ .textColor = offscreen ? CLAY__DEBUGVIEW_COLOR_3 : CLAY__DEBUGVIEW_COLOR_4, .fontSize = 16 }));
}
}
@ -2644,7 +2682,7 @@ Clay__RenderDebugLayoutData Clay__RenderDebugLayoutElementsList(int32_t initialR
Clay__OpenElement();
Clay__ConfigureOpenElement(CLAY__INIT(Clay_ElementDeclaration) { .layout = { .padding = { 8 } } });
Clay__OpenElement();
Clay__ConfigureOpenElement(CLAY__INIT(Clay_ElementDeclaration) { .layout = { .padding = { .left = CLAY__DEBUGVIEW_INDENT_WIDTH }}, .border = { .left = { .width = 1, .color = CLAY__DEBUGVIEW_COLOR_3 }}});
Clay__ConfigureOpenElement(CLAY__INIT(Clay_ElementDeclaration) { .layout = { .padding = { .left = CLAY__DEBUGVIEW_INDENT_WIDTH }}, .border = { .color = CLAY__DEBUGVIEW_COLOR_3, .width = { .left = 1 } }});
Clay__OpenElement();
Clay__ConfigureOpenElement(CLAY__INIT(Clay_ElementDeclaration) { .layout = { .layoutDirection = CLAY_TOP_TO_BOTTOM } });
}
@ -2673,7 +2711,7 @@ Clay__RenderDebugLayoutData Clay__RenderDebugLayoutElementsList(int32_t initialR
if (highlightedElementId) {
CLAY({ .id = CLAY_ID("Clay__DebugView_ElementHighlight"), .layout = { .sizing = {CLAY_SIZING_GROW(0), CLAY_SIZING_GROW(0)} }, .floating = { .parentId = highlightedElementId, .zIndex = 65535, .pointerCaptureMode = CLAY_POINTER_CAPTURE_MODE_PASSTHROUGH } }) {
CLAY({ .id = CLAY_ID("Clay__DebugView_ElementHighlightRectangle"), .layout = { .sizing = {CLAY_SIZING_GROW(0), CLAY_SIZING_GROW(0)} }, .rectangle = { .color = Clay__debugViewHighlightColor } }) {}
CLAY({ .id = CLAY_ID("Clay__DebugView_ElementHighlightRectangle"), .layout = { .sizing = {CLAY_SIZING_GROW(0), CLAY_SIZING_GROW(0)} }, .backgroundColor = Clay__debugViewHighlightColor }) {}
}
}
return layoutData;
@ -2709,7 +2747,7 @@ void Clay__RenderDebugViewElementConfigHeader(Clay_String elementId, Clay__Eleme
Clay_Color backgroundColor = config.color;
backgroundColor.a = 90;
CLAY({ .layout = { .sizing = { CLAY_SIZING_GROW(0)}, .padding = CLAY_PADDING_ALL(CLAY__DEBUGVIEW_OUTER_PADDING), .childAlignment = { .y = CLAY_ALIGN_Y_CENTER } } }) {
CLAY({ .layout = { .padding = { 8, 8, 2, 2 } }, .rectangle = { .color = backgroundColor }, .border = CLAY_BORDER_OUTSIDE({ 1, config.color }), .shared = { .cornerRadius = CLAY_CORNER_RADIUS(4) }}) {
CLAY({ .layout = { .padding = { 8, 8, 2, 2 } }, .backgroundColor = backgroundColor, .cornerRadius = CLAY_CORNER_RADIUS(4), .border = { .color = config.color, .width = { 1, 1, 1, 1 } } }) {
CLAY_TEXT(config.label, CLAY_TEXT_CONFIG({ .textColor = CLAY__DEBUGVIEW_COLOR_4, .fontSize = 16 }));
}
CLAY({ .layout = { .sizing = { .width = CLAY_SIZING_GROW(0) } } }) {}
@ -2729,7 +2767,7 @@ void Clay__RenderDebugViewColor(Clay_Color color, Clay_TextElementConfig *textCo
CLAY_TEXT(Clay__IntToString(color.a), textConfig);
CLAY_TEXT(CLAY_STRING(" }"), textConfig);
CLAY({ .layout = { .sizing = { CLAY_SIZING_FIXED(10) } } }) {}
CLAY({ .layout = { .sizing = { CLAY_SIZING_FIXED(CLAY__DEBUGVIEW_ROW_HEIGHT - 8), CLAY_SIZING_FIXED(CLAY__DEBUGVIEW_ROW_HEIGHT - 8)} }, .rectangle = { .color = color }, .border = CLAY_BORDER_OUTSIDE({ 1, CLAY__DEBUGVIEW_COLOR_4 }), .shared = { .cornerRadius = CLAY_CORNER_RADIUS(4) } }) {}
CLAY({ .layout = { .sizing = { CLAY_SIZING_FIXED(CLAY__DEBUGVIEW_ROW_HEIGHT - 8), CLAY_SIZING_FIXED(CLAY__DEBUGVIEW_ROW_HEIGHT - 8)} }, .backgroundColor = color, .cornerRadius = CLAY_CORNER_RADIUS(4), .border = { .color = CLAY__DEBUGVIEW_COLOR_4, .width = { 1, 1, 1, 1 } } }) {}
}
}
@ -2747,17 +2785,6 @@ void Clay__RenderDebugViewCornerRadius(Clay_CornerRadius cornerRadius, Clay_Text
}
}
void Clay__RenderDebugViewBorder(int32_t index, Clay_Border border, Clay_TextElementConfig *textConfig) {
(void) index;
CLAY({ .layout = { .childAlignment = {.y = CLAY_ALIGN_Y_CENTER} } }) {
CLAY_TEXT(CLAY_STRING("{ width: "), textConfig);
CLAY_TEXT(Clay__IntToString(border.width), textConfig);
CLAY_TEXT(CLAY_STRING(", color: "), textConfig);
Clay__RenderDebugViewColor(border.color, textConfig);
CLAY_TEXT(CLAY_STRING(" }"), textConfig);
}
}
void HandleDebugViewCloseButtonInteraction(Clay_ElementId elementId, Clay_PointerData pointerInfo, intptr_t userData) {
Clay_Context* context = Clay_GetCurrentContext();
(void) elementId; (void) pointerInfo; (void) userData;
@ -2807,25 +2834,25 @@ void Clay__RenderDebugView(void) {
CLAY({ .id = CLAY_ID("Clay__DebugView"),
.layout = { .sizing = { CLAY_SIZING_FIXED((float)Clay__debugViewWidth) , CLAY_SIZING_FIXED(context->layoutDimensions.height) }, .layoutDirection = CLAY_TOP_TO_BOTTOM },
.floating = { .parentId = Clay__HashString(CLAY_STRING("Clay__RootContainer"), 0, 0).id, .zIndex = 65000, .attachment = { .element = CLAY_ATTACH_POINT_LEFT_CENTER, .parent = CLAY_ATTACH_POINT_RIGHT_CENTER }},
.border = { .bottom = { .width = 1, .color = CLAY__DEBUGVIEW_COLOR_3 }}
.border = { .color = CLAY__DEBUGVIEW_COLOR_3, .width = { .bottom = 1 } }
}) {
CLAY({ .layout = { .sizing = {CLAY_SIZING_GROW(0), CLAY_SIZING_FIXED(CLAY__DEBUGVIEW_ROW_HEIGHT)}, .padding = {CLAY__DEBUGVIEW_OUTER_PADDING, CLAY__DEBUGVIEW_OUTER_PADDING }, .childAlignment = {.y = CLAY_ALIGN_Y_CENTER} }, .rectangle = { .color = CLAY__DEBUGVIEW_COLOR_2 } }) {
CLAY({ .layout = { .sizing = {CLAY_SIZING_GROW(0), CLAY_SIZING_FIXED(CLAY__DEBUGVIEW_ROW_HEIGHT)}, .padding = {CLAY__DEBUGVIEW_OUTER_PADDING, CLAY__DEBUGVIEW_OUTER_PADDING }, .childAlignment = {.y = CLAY_ALIGN_Y_CENTER} }, .backgroundColor = CLAY__DEBUGVIEW_COLOR_2 }) {
CLAY_TEXT(CLAY_STRING("Clay Debug Tools"), infoTextConfig);
CLAY({ .layout = { .sizing = { CLAY_SIZING_GROW(0) } } }) {}
// Close button
CLAY({
.layout = { .sizing = {CLAY_SIZING_FIXED(CLAY__DEBUGVIEW_ROW_HEIGHT - 10), CLAY_SIZING_FIXED(CLAY__DEBUGVIEW_ROW_HEIGHT - 10)}, .childAlignment = {CLAY_ALIGN_X_CENTER, CLAY_ALIGN_Y_CENTER} },
.rectangle = { .color = {217,91,67,80} },
.border = CLAY_BORDER_OUTSIDE({ 1, (CLAY__INIT(Clay_Color){217,91,67,255}) }),
.shared = { .cornerRadius = CLAY_CORNER_RADIUS(4) }
.backgroundColor = {217,91,67,80},
.cornerRadius = CLAY_CORNER_RADIUS(4),
.border = { .color = { 217,91,67,255 }, .width = { 1, 1, 1, 1 } },
}) {
Clay_OnHover(HandleDebugViewCloseButtonInteraction, 0);
CLAY_TEXT(CLAY_STRING("x"), CLAY_TEXT_CONFIG({ .textColor = CLAY__DEBUGVIEW_COLOR_4, .fontSize = 16 }));
}
}
CLAY({ .layout = { .sizing = {CLAY_SIZING_GROW(0), CLAY_SIZING_FIXED(1)} }, .rectangle = { .color = CLAY__DEBUGVIEW_COLOR_3 } }) {}
CLAY({ .layout = { .sizing = {CLAY_SIZING_GROW(0), CLAY_SIZING_FIXED(1)} }, .backgroundColor = CLAY__DEBUGVIEW_COLOR_3 } ) {}
CLAY({ .id = scrollId, .layout = { .sizing = {CLAY_SIZING_GROW(0), CLAY_SIZING_GROW(0)} }, .scroll = { .horizontal = true, .vertical = true } }) {
CLAY({ .layout = { .sizing = {CLAY_SIZING_GROW(0), CLAY_SIZING_GROW(0)}, .layoutDirection = CLAY_TOP_TO_BOTTOM }, .rectangle = { .color = ((initialElementsLength + initialRootsLength) & 1) == 0 ? CLAY__DEBUGVIEW_COLOR_2 : CLAY__DEBUGVIEW_COLOR_1 } }) {
CLAY({ .layout = { .sizing = {CLAY_SIZING_GROW(0), CLAY_SIZING_GROW(0)}, .layoutDirection = CLAY_TOP_TO_BOTTOM }, .backgroundColor = ((initialElementsLength + initialRootsLength) & 1) == 0 ? CLAY__DEBUGVIEW_COLOR_2 : CLAY__DEBUGVIEW_COLOR_1 }) {
Clay_ElementId panelContentsId = Clay__HashString(CLAY_STRING("Clay__DebugViewPaneOuter"), 0, 0);
// Element list
CLAY({ .id = panelContentsId, .layout = { .sizing = {CLAY_SIZING_GROW(0), CLAY_SIZING_GROW(0)} }, .floating = { .zIndex = 65001, .pointerCaptureMode = CLAY_POINTER_CAPTURE_MODE_PASSTHROUGH } }) {
@ -2845,18 +2872,18 @@ void Clay__RenderDebugView(void) {
rowColor.g *= 1.25f;
rowColor.b *= 1.25f;
}
CLAY({ .layout = { .sizing = {CLAY_SIZING_GROW(0), CLAY_SIZING_FIXED(CLAY__DEBUGVIEW_ROW_HEIGHT)}, .layoutDirection = CLAY_TOP_TO_BOTTOM }, .rectangle = { .color = rowColor } }) {}
CLAY({ .layout = { .sizing = {CLAY_SIZING_GROW(0), CLAY_SIZING_FIXED(CLAY__DEBUGVIEW_ROW_HEIGHT)}, .layoutDirection = CLAY_TOP_TO_BOTTOM }, .backgroundColor = rowColor } ) {}
}
}
}
CLAY({ .layout = { .sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_FIXED(1)} }, .rectangle = { .color = CLAY__DEBUGVIEW_COLOR_3 } }) {}
CLAY({ .layout = { .sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_FIXED(1)} }, .backgroundColor = CLAY__DEBUGVIEW_COLOR_3 }) {}
if (context->debugSelectedElementId != 0) {
Clay_LayoutElementHashMapItem *selectedItem = Clay__GetHashMapItem(context->debugSelectedElementId);
CLAY({
.layout = { .sizing = {CLAY_SIZING_GROW(0), CLAY_SIZING_FIXED(300)}, .layoutDirection = CLAY_TOP_TO_BOTTOM },
.rectangle = { .color = CLAY__DEBUGVIEW_COLOR_2 },
.layout = { .sizing = {CLAY_SIZING_GROW(0), CLAY_SIZING_FIXED(300)}, .layoutDirection = CLAY_TOP_TO_BOTTOM },
.backgroundColor = CLAY__DEBUGVIEW_COLOR_2 ,
.scroll = { .vertical = true },
.border = { .betweenChildren = { .width = 1, .color = CLAY__DEBUGVIEW_COLOR_3 }}
.border = { .color = CLAY__DEBUGVIEW_COLOR_3, .width = { .betweenChildren = 1 } }
}) {
CLAY({ .layout = { .sizing = {CLAY_SIZING_GROW(0), CLAY_SIZING_FIXED(CLAY__DEBUGVIEW_ROW_HEIGHT + 8)}, .padding = {CLAY__DEBUGVIEW_OUTER_PADDING, CLAY__DEBUGVIEW_OUTER_PADDING}, .childAlignment = {.y = CLAY_ALIGN_Y_CENTER} } }) {
CLAY_TEXT(CLAY_STRING("Layout Config"), infoTextConfig);
@ -2950,16 +2977,6 @@ void Clay__RenderDebugView(void) {
Clay__RenderDebugViewCornerRadius(sharedConfig->cornerRadius, infoTextConfig);
}
break;
break;
}
case CLAY__ELEMENT_CONFIG_TYPE_RECTANGLE: {
Clay_RectangleElementConfig *rectangleConfig = elementConfig->config.rectangleElementConfig;
CLAY({ .layout = { .padding = attributeConfigPadding, .childGap = 8, .layoutDirection = CLAY_TOP_TO_BOTTOM }}) {
// .color
CLAY_TEXT(CLAY_STRING("Color"), infoTitleConfig);
Clay__RenderDebugViewColor(rectangleConfig->color, infoTextConfig);
}
break;
}
case CLAY__ELEMENT_CONFIG_TYPE_TEXT: {
Clay_TextElementConfig *textConfig = elementConfig->config.textElementConfig;
@ -3055,21 +3072,18 @@ void Clay__RenderDebugView(void) {
case CLAY__ELEMENT_CONFIG_TYPE_BORDER: {
Clay_BorderElementConfig *borderConfig = elementConfig->config.borderElementConfig;
CLAY({ .id = CLAY_ID("Clay__DebugViewElementInfoBorderBody"), .layout = { .padding = attributeConfigPadding, .childGap = 8, .layoutDirection = CLAY_TOP_TO_BOTTOM } }) {
// .left
CLAY_TEXT(CLAY_STRING("Left Border"), infoTitleConfig);
Clay__RenderDebugViewBorder(1, borderConfig->left, infoTextConfig);
// .right
CLAY_TEXT(CLAY_STRING("Right Border"), infoTitleConfig);
Clay__RenderDebugViewBorder(2, borderConfig->right, infoTextConfig);
// .top
CLAY_TEXT(CLAY_STRING("Top Border"), infoTitleConfig);
Clay__RenderDebugViewBorder(3, borderConfig->top, infoTextConfig);
// .bottom
CLAY_TEXT(CLAY_STRING("Bottom Border"), infoTitleConfig);
Clay__RenderDebugViewBorder(4, borderConfig->bottom, infoTextConfig);
// .betweenChildren
CLAY_TEXT(CLAY_STRING("Border Between Children"), infoTitleConfig);
Clay__RenderDebugViewBorder(5, borderConfig->betweenChildren, infoTextConfig);
CLAY_TEXT(CLAY_STRING("Border Widths"), infoTitleConfig);
CLAY({{0}}) {
CLAY_TEXT(CLAY_STRING("{ left: "), infoTextConfig);
CLAY_TEXT(Clay__IntToString(borderConfig->width.left), infoTextConfig);
CLAY_TEXT(CLAY_STRING("{ right: "), infoTextConfig);
CLAY_TEXT(Clay__IntToString(borderConfig->width.right), infoTextConfig);
CLAY_TEXT(CLAY_STRING("{ top: "), infoTextConfig);
CLAY_TEXT(Clay__IntToString(borderConfig->width.top), infoTextConfig);
CLAY_TEXT(CLAY_STRING("{ bottom: "), infoTextConfig);
CLAY_TEXT(Clay__IntToString(borderConfig->width.bottom), infoTextConfig);
CLAY_TEXT(CLAY_STRING(" }"), infoTextConfig);
}
}
break;
}
@ -3079,12 +3093,12 @@ void Clay__RenderDebugView(void) {
}
}
} else {
CLAY({ .id = CLAY_ID("Clay__DebugViewWarningsScrollPane"), .layout = { .sizing = {CLAY_SIZING_GROW(0), CLAY_SIZING_FIXED(300)}, .childGap = 6, .layoutDirection = CLAY_TOP_TO_BOTTOM }, .rectangle = { .color = CLAY__DEBUGVIEW_COLOR_2 }, .scroll = { .horizontal = true, .vertical = true } }) {
CLAY({ .id = CLAY_ID("Clay__DebugViewWarningsScrollPane"), .layout = { .sizing = {CLAY_SIZING_GROW(0), CLAY_SIZING_FIXED(300)}, .childGap = 6, .layoutDirection = CLAY_TOP_TO_BOTTOM }, .backgroundColor = CLAY__DEBUGVIEW_COLOR_2, .scroll = { .horizontal = true, .vertical = true } }) {
Clay_TextElementConfig *warningConfig = CLAY_TEXT_CONFIG({ .textColor = CLAY__DEBUGVIEW_COLOR_4, .fontSize = 16, .wrapMode = CLAY_TEXT_WRAP_NONE });
CLAY({ .id = CLAY_ID("Clay__DebugViewWarningItemHeader"), .layout = { .sizing = {.height = CLAY_SIZING_FIXED(CLAY__DEBUGVIEW_ROW_HEIGHT)}, .padding = {CLAY__DEBUGVIEW_OUTER_PADDING, CLAY__DEBUGVIEW_OUTER_PADDING}, .childGap = 8, .childAlignment = {.y = CLAY_ALIGN_Y_CENTER} } }) {
CLAY_TEXT(CLAY_STRING("Warnings"), warningConfig);
}
CLAY({ .id = CLAY_ID("Clay__DebugViewWarningsTopBorder"), .layout = { .sizing = { .width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_FIXED(1)} }, .rectangle = { .color = {200, 200, 200, 255} } }) {}
CLAY({ .id = CLAY_ID("Clay__DebugViewWarningsTopBorder"), .layout = { .sizing = { .width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_FIXED(1)} }, .backgroundColor = {200, 200, 200, 255} }) {}
int32_t previousWarningsLength = context->warnings.length;
for (int32_t i = 0; i < previousWarningsLength; i++) {
Clay__Warning warning = context->warnings.internalArray[i];
@ -3314,13 +3328,13 @@ void Clay__CreateGarbagePaddingStruct(Clay_Context* context) {
Clay__CalculateDeclarationPaddingMask(CLAY__INIT(Clay_ElementDeclaration) {
.id = { 0 },
.layout = { 0 },
.rectangle = { 0 },
.backgroundColor = { 0 },
.cornerRadius = { 0 },
.image = { 0 },
.floating = { 0 },
.custom = { 0 },
.scroll = { 0 },
.border = { 0 },
.shared = { 0 },
}, context);
}
@ -3502,8 +3516,6 @@ void Clay_BeginLayout(void) {
Clay__LayoutElementTreeRootArray_Add(&context->layoutElementTreeRoots, CLAY__INIT(Clay__LayoutElementTreeRoot) { .layoutElementIndex = 0 });
}
Clay_TextElementConfig Clay__DebugView_ErrorTextConfig = {.textColor = {255, 0, 0, 255}, .fontSize = 16, .wrapMode = CLAY_TEXT_WRAP_NONE };
CLAY_WASM_EXPORT("Clay_EndLayout")
Clay_RenderCommandArray Clay_EndLayout(void) {
Clay_Context* context = Clay_GetCurrentContext();
@ -3517,8 +3529,7 @@ Clay_RenderCommandArray Clay_EndLayout(void) {
Clay_String message = CLAY_STRING("Clay Error: Layout elements exceeded Clay__maxElementCount");
Clay__AddRenderCommand(CLAY__INIT(Clay_RenderCommand ) {
.boundingBox = { context->layoutDimensions.width / 2 - 59 * 4, context->layoutDimensions.height / 2, 0, 0 },
.config = { .textElementConfig = &Clay__DebugView_ErrorTextConfig },
.textOrSharedConfig = { .text = CLAY__INIT(Clay_StringSlice) { .length = message.length, .chars = message.chars, .baseChars = message.chars } },
.renderData = { .text = { .stringContents = CLAY__INIT(Clay_StringSlice) { .length = message.length, .chars = message.chars, .baseChars = message.chars }, .textColor = {255, 0, 0, 255}, .fontSize = 16 } },
.commandType = CLAY_RENDER_COMMAND_TYPE_TEXT
});
} else {

View File

@ -18,14 +18,6 @@ void HandleClayErrors(Clay_ErrorData errorData) {
}
int main(int argc, char *argv[]) {
documents.documents = (Document[]) {
{ .title = CLAY_STRING("Squirrels"), .contents = CLAY_STRING("The Secret Life of Squirrels: Nature's Clever Acrobats\n""Squirrels are often overlooked creatures, dismissed as mere park inhabitants or backyard nuisances. Yet, beneath their fluffy tails and twitching noses lies an intricate world of cunning, agility, and survival tactics that are nothing short of fascinating. As one of the most common mammals in North America, squirrels have adapted to a wide range of environments from bustling urban centers to tranquil forests and have developed a variety of unique behaviors that continue to intrigue scientists and nature enthusiasts alike.\n""\n""Master Tree Climbers\n""At the heart of a squirrel's skill set is its impressive ability to navigate trees with ease. Whether they're darting from branch to branch or leaping across wide gaps, squirrels possess an innate talent for acrobatics. Their powerful hind legs, which are longer than their front legs, give them remarkable jumping power. With a tail that acts as a counterbalance, squirrels can leap distances of up to ten times the length of their body, making them some of the best aerial acrobats in the animal kingdom.\n""But it's not just their agility that makes them exceptional climbers. Squirrels' sharp, curved claws allow them to grip tree bark with precision, while the soft pads on their feet provide traction on slippery surfaces. Their ability to run at high speeds and scale vertical trunks with ease is a testament to the evolutionary adaptations that have made them so successful in their arboreal habitats.\n""\n""Food Hoarders Extraordinaire\n""Squirrels are often seen frantically gathering nuts, seeds, and even fungi in preparation for winter. While this behavior may seem like instinctual hoarding, it is actually a survival strategy that has been honed over millions of years. Known as \"scatter hoarding,\" squirrels store their food in a variety of hidden locations, often burying it deep in the soil or stashing it in hollowed-out tree trunks.\n""Interestingly, squirrels have an incredible memory for the locations of their caches. Research has shown that they can remember thousands of hiding spots, often returning to them months later when food is scarce. However, they don't always recover every stash some forgotten caches eventually sprout into new trees, contributing to forest regeneration. This unintentional role as forest gardeners highlights the ecological importance of squirrels in their ecosystems.\n""\n""The Great Squirrel Debate: Urban vs. Wild\n""While squirrels are most commonly associated with rural or wooded areas, their adaptability has allowed them to thrive in urban environments as well. In cities, squirrels have become adept at finding food sources in places like parks, streets, and even garbage cans. However, their urban counterparts face unique challenges, including traffic, predators, and the lack of natural shelters. Despite these obstacles, squirrels in urban areas are often observed using human infrastructure such as buildings, bridges, and power lines as highways for their acrobatic escapades.\n""There is, however, a growing concern regarding the impact of urban life on squirrel populations. Pollution, deforestation, and the loss of natural habitats are making it more difficult for squirrels to find adequate food and shelter. As a result, conservationists are focusing on creating squirrel-friendly spaces within cities, with the goal of ensuring these resourceful creatures continue to thrive in both rural and urban landscapes.\n""\n""A Symbol of Resilience\n""In many cultures, squirrels are symbols of resourcefulness, adaptability, and preparation. Their ability to thrive in a variety of environments while navigating challenges with agility and grace serves as a reminder of the resilience inherent in nature. Whether you encounter them in a quiet forest, a city park, or your own backyard, squirrels are creatures that never fail to amaze with their endless energy and ingenuity.\n""In the end, squirrels may be small, but they are mighty in their ability to survive and thrive in a world that is constantly changing. So next time you spot one hopping across a branch or darting across your lawn, take a moment to appreciate the remarkable acrobat at work a true marvel of the natural world.\n") },
{ .title = CLAY_STRING("Lorem Ipsum"), .contents = CLAY_STRING("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.") },
{ .title = CLAY_STRING("Vacuum Instructions"), .contents = CLAY_STRING("Chapter 3: Getting Started - Unpacking and Setup\n""\n""Congratulations on your new SuperClean Pro 5000 vacuum cleaner! In this section, we will guide you through the simple steps to get your vacuum up and running. Before you begin, please ensure that you have all the components listed in the \"Package Contents\" section on page 2.\n""\n""1. Unboxing Your Vacuum\n""Carefully remove the vacuum cleaner from the box. Avoid using sharp objects that could damage the product. Once removed, place the unit on a flat, stable surface to proceed with the setup. Inside the box, you should find:\n""\n"" The main vacuum unit\n"" A telescoping extension wand\n"" A set of specialized cleaning tools (crevice tool, upholstery brush, etc.)\n"" A reusable dust bag (if applicable)\n"" A power cord with a 3-prong plug\n"" A set of quick-start instructions\n""\n""2. Assembling Your Vacuum\n""Begin by attaching the extension wand to the main body of the vacuum cleaner. Line up the connectors and twist the wand into place until you hear a click. Next, select the desired cleaning tool and firmly attach it to the wand's end, ensuring it is securely locked in.\n""\n""For models that require a dust bag, slide the bag into the compartment at the back of the vacuum, making sure it is properly aligned with the internal mechanism. If your vacuum uses a bagless system, ensure the dust container is correctly seated and locked in place before use.\n""\n""3. Powering On\n""To start the vacuum, plug the power cord into a grounded electrical outlet. Once plugged in, locate the power switch, usually positioned on the side of the handle or body of the unit, depending on your model. Press the switch to the \"On\" position, and you should hear the motor begin to hum. If the vacuum does not power on, check that the power cord is securely plugged in, and ensure there are no blockages in the power switch.\n""\n""Note: Before first use, ensure that the vacuum filter (if your model has one) is properly installed. If unsure, refer to \"Section 5: Maintenance\" for filter installation instructions.") },
{ .title = CLAY_STRING("Article 4"), .contents = CLAY_STRING("Article 4") },
{ .title = CLAY_STRING("Article 5"), .contents = CLAY_STRING("Article 5") },
};
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
fprintf(stderr, "Error: could not initialize SDL: %s\n", SDL_GetError());
return 1;

View File

@ -31,53 +31,64 @@
// e.g. render PNGs.
#include <cairo/cairo-pdf.h>
const uint16_t FONT_CALLISTOGA = 0;
const uint16_t FONT_QUICKSAND = 0;
// Layout the first page.
void Layout() {
static Clay_Color PRIMARY = { 0xa8, 0x42, 0x1c, 255 };
static Clay_Color BACKGROUND = { 0xF4, 0xEB, 0xE6, 255 };
static Clay_Color ACCENT = { 0xFA, 0xE0, 0xD4, 255 };
CLAY({ .layout = { .sizing = { CLAY_SIZING_GROW(0), CLAY_SIZING_GROW(0) },
.layoutDirection = CLAY_TOP_TO_BOTTOM },
.rectangle = { .color = BACKGROUND } }) {
CLAY({
.layout = { .sizing = { CLAY_SIZING_GROW(0), CLAY_SIZING_GROW(0) },
.layoutDirection = CLAY_TOP_TO_BOTTOM },
.backgroundColor = BACKGROUND
}) {
CLAY({ .id = CLAY_ID("PageMargins"), .layout = { .sizing = { CLAY_SIZING_GROW(0), CLAY_SIZING_GROW(0) },
.padding = { 70, 70, 50, 50 }, // Some nice looking page margins
.layoutDirection = CLAY_TOP_TO_BOTTOM,
.childGap = 10}
}) {
// Section Title
CLAY_TEXT(CLAY_STRING("Features Overview"), CLAY_TEXT_CONFIG({.fontFamily = CLAY_STRING("Calistoga"), .textColor = PRIMARY, .fontSize = 24}));
CLAY_TEXT(CLAY_STRING("Features Overview"), CLAY_TEXT_CONFIG({ .fontId = FONT_CALLISTOGA, .textColor = PRIMARY, .fontSize = 24 }));
// Feature Box
CLAY({ .layout = { .sizing = { CLAY_SIZING_GROW(0), CLAY_SIZING_FIT(0) }, .childGap = 10 }}) {
CLAY({ .layout = { .sizing = { CLAY_SIZING_GROW(0), CLAY_SIZING_FIT(0) }}, .rectangle = { .color = ACCENT }, .shared = { .cornerRadius = CLAY_CORNER_RADIUS(12) } }) {
CLAY({ .layout = { .sizing = { CLAY_SIZING_GROW(0), CLAY_SIZING_FIT(0) }}, .backgroundColor = ACCENT, .cornerRadius = CLAY_CORNER_RADIUS(12) }) {
CLAY({ .layout = {.padding = CLAY_PADDING_ALL(20), .childGap = 4, .layoutDirection = CLAY_TOP_TO_BOTTOM }}) {
CLAY_TEXT(CLAY_STRING("- High performance"),
CLAY_TEXT_CONFIG({ .textColor = PRIMARY, .fontSize = 14, .fontFamily = CLAY_STRING("Quicksand SemiBold") }));
CLAY_TEXT_CONFIG({ .textColor = PRIMARY, .fontSize = 14, .fontId = FONT_QUICKSAND }));
CLAY_TEXT(CLAY_STRING("- Declarative syntax"),
CLAY_TEXT_CONFIG({ .textColor = PRIMARY, .fontSize = 14, .fontFamily = CLAY_STRING("Quicksand SemiBold") }));
CLAY_TEXT_CONFIG({ .textColor = PRIMARY, .fontSize = 14, .fontId = FONT_QUICKSAND }));
CLAY_TEXT(CLAY_STRING("- Flexbox-style responsive layout"),
CLAY_TEXT_CONFIG({ .textColor = PRIMARY, .fontSize = 14, .fontFamily = CLAY_STRING("Quicksand SemiBold") }));
CLAY_TEXT_CONFIG({ .textColor = PRIMARY, .fontSize = 14, .fontId = FONT_QUICKSAND }));
CLAY_TEXT(CLAY_STRING("- Single .h file for C/C++"),
CLAY_TEXT_CONFIG({ .textColor = PRIMARY, .fontSize = 14, .fontFamily = CLAY_STRING("Quicksand SemiBold") }));
CLAY_TEXT_CONFIG({ .textColor = PRIMARY, .fontSize = 14, .fontId = FONT_QUICKSAND }));
CLAY_TEXT(CLAY_STRING("- And now with cairo!"),
CLAY_TEXT_CONFIG({ .textColor = PRIMARY, .fontSize = 14, .fontFamily = CLAY_STRING("Quicksand SemiBold") }));
CLAY_TEXT_CONFIG({ .textColor = PRIMARY, .fontSize = 14, .fontId = FONT_QUICKSAND }));
}
}
CLAY({ .layout = {
.sizing = {CLAY_SIZING_FIT(0), CLAY_SIZING_GROW(0)},
.padding = CLAY_PADDING_ALL(10),
.layoutDirection = CLAY_TOP_TO_BOTTOM,
.childAlignment = { CLAY_ALIGN_X_CENTER, CLAY_ALIGN_Y_CENTER },
.childGap = 4
}, .rectangle = { .color = ACCENT }, .shared = {.cornerRadius = CLAY_CORNER_RADIUS(8)}}) {
CLAY({
.layout = {
.sizing = {CLAY_SIZING_FIT(0), CLAY_SIZING_GROW(0)},
.padding = CLAY_PADDING_ALL(10),
.layoutDirection = CLAY_TOP_TO_BOTTOM,
.childAlignment = { CLAY_ALIGN_X_CENTER, CLAY_ALIGN_Y_CENTER },
.childGap = 4
},
.backgroundColor = ACCENT,
.cornerRadius = CLAY_CORNER_RADIUS(8)
}) {
// Profile picture
CLAY({ .layout = {
.sizing = {CLAY_SIZING_FIT(0), CLAY_SIZING_GROW(0)},
.padding = { 30, 30, 0, 0 },
.layoutDirection = CLAY_TOP_TO_BOTTOM,
.childAlignment = { CLAY_ALIGN_X_CENTER, CLAY_ALIGN_Y_CENTER }}, .border = CLAY_BORDER_OUTSIDE(2, PRIMARY), .shared = { .cornerRadius = 10 }}) {
CLAY({ .layout = { .sizing = { CLAY_SIZING_FIXED(32), CLAY_SIZING_FIXED(32) } }, .image = { .sourceDimensions = { 32, 32 }, .path = CLAY_STRING("resources/check.png") }});
.sizing = {CLAY_SIZING_FIT(0), CLAY_SIZING_GROW(0)},
.padding = { 30, 30, 0, 0 },
.layoutDirection = CLAY_TOP_TO_BOTTOM,
.childAlignment = { CLAY_ALIGN_X_CENTER, CLAY_ALIGN_Y_CENTER }},
.border = { .color = PRIMARY, .width = 2, 2, 2, 2 }, .cornerRadius = 10
}) {
CLAY({ .layout = { .sizing = { CLAY_SIZING_FIXED(32), CLAY_SIZING_FIXED(32) } }, .image = { .sourceDimensions = { 32, 32 }, .imageData = "resources/check.png" }});
}
}
}
@ -85,13 +96,13 @@ void Layout() {
CLAY({ .layout = { .sizing = { CLAY_SIZING_GROW(0), CLAY_SIZING_FIXED(16) } }});
CLAY({ .layout = { .sizing = { CLAY_SIZING_GROW(0), CLAY_SIZING_GROW(0) }, .childGap = 10, .layoutDirection = CLAY_TOP_TO_BOTTOM }}) {
CLAY_TEXT(CLAY_STRING("Cairo"), CLAY_TEXT_CONFIG({ .fontFamily = CLAY_STRING("Calistoga"), .fontSize = 24, .textColor = PRIMARY }));
CLAY({ .layout = { .padding = CLAY_PADDING_ALL(10) }, .rectangle = { .color = ACCENT }, .shared = { .cornerRadius = 10 } }) {
CLAY_TEXT(CLAY_STRING("Cairo"), CLAY_TEXT_CONFIG({ .fontId = FONT_CALLISTOGA, .fontSize = 24, .textColor = PRIMARY }));
CLAY({ .layout = { .padding = CLAY_PADDING_ALL(10) }, .backgroundColor = ACCENT, .cornerRadius = 10 }) {
CLAY_TEXT(CLAY_STRING("Officiis quia quia qui inventore ratione voluptas et. Quidem sunt unde similique. Qui est et exercitationem cumque harum illum. Numquam placeat aliquid quo voluptatem. "
"Deleniti saepe nihil exercitationem nemo illo. Consequatur beatae repellat provident similique. Provident qui exercitationem deserunt sapiente. Quam qui dolor corporis odit. "
"Assumenda corrupti sunt culpa pariatur. Vero sit ut minima. In est consequatur minus et cum sint illum aperiam. Qui ipsa quas nisi omnis aut quia nobis. "
"Corporis deserunt eum mollitia modi rerum voluptas. Expedita non ab esse. Sit voluptates eos voluptatem labore aspernatur quia eum. Modi cumque atque non. Sunt officiis corrupti neque ut inventore excepturi rem minima. Possimus sed soluta qui ea aut ipsum laborum fugit. "
"Voluptate eum consectetur non. Quo autem voluptate soluta atque dolorum maxime. Officiis inventore omnis eveniet beatae ipsa optio. Unde voluptatum ut autem quia sit sit et. Ut inventore qui quia totam consequatur. Sit ea consequatur omnis rerum nulla aspernatur deleniti."), CLAY_TEXT_CONFIG({ .fontFamily = CLAY_STRING("Quicksand SemiBold"), .fontSize = 16, .textColor = PRIMARY, .lineHeight = 16 }));
"Voluptate eum consectetur non. Quo autem voluptate soluta atque dolorum maxime. Officiis inventore omnis eveniet beatae ipsa optio. Unde voluptatum ut autem quia sit sit et. Ut inventore qui quia totam consequatur. Sit ea consequatur omnis rerum nulla aspernatur deleniti."), CLAY_TEXT_CONFIG({ .fontId = FONT_QUICKSAND, .fontSize = 16, .textColor = PRIMARY, .lineHeight = 16 }));
}
}
}
@ -129,7 +140,12 @@ int main(void) {
// We initialize Clay with the same size
Clay_Initialize(clayMemory, (Clay_Dimensions) { width, height }, (Clay_ErrorHandler) { HandleClayErrors });
Clay_SetMeasureTextFunction(Clay_Cairo_MeasureText, 0);
char** fonts = (char*[]) {
"Callistoga",
"Quicksand Semibold"
};
Clay_SetMeasureTextFunction(Clay_Cairo_MeasureText, (uintptr_t)fonts);
Clay_BeginLayout();
@ -139,7 +155,7 @@ int main(void) {
Clay_RenderCommandArray commands = Clay_EndLayout();
// Pass our layout to the cairo backend
Clay_Cairo_Render(commands);
Clay_Cairo_Render(commands, fonts);
// To keep this example short, we will not emit a second page in the PDF.
// But to do so, you have to

View File

@ -1,6 +1,3 @@
#define CLAY_EXTEND_CONFIG_RECTANGLE Clay_String link; bool cursorPointer;
#define CLAY_EXTEND_CONFIG_IMAGE Clay_String sourceURL;
#define CLAY_EXTEND_CONFIG_TEXT bool disablePointerEvents;
#define CLAY_IMPLEMENTATION
#include "../../clay.h"
@ -40,27 +37,46 @@ const Clay_Color COLOR_BLOB_BORDER_5 = (Clay_Color) {240, 189, 100, 255};
Clay_TextElementConfig headerTextConfig = (Clay_TextElementConfig) { .fontId = 2, .fontSize = 24, .textColor = {61, 26, 5, 255} };
Clay_TextElementConfig blobTextConfig = (Clay_TextElementConfig) { .fontId = 2, .fontSize = 30, .textColor = {244, 235, 230, 255} };
void LandingPageBlob(int index, int fontSize, Clay_Color color, Clay_String text, Clay_String imageURL) {
CLAY({ .id = CLAY_IDI("HeroBlob", index), .layout = { .sizing = { CLAY_SIZING_GROW(.max = 480) }, .padding = CLAY_PADDING_ALL(16), .childGap = 16, .childAlignment = {.y = CLAY_ALIGN_Y_CENTER} }, .border = CLAY_BORDER_OUTSIDE({ 2, color }), .shared = { .cornerRadius = CLAY_CORNER_RADIUS(10) } }) {
CLAY({ .id = CLAY_IDI("CheckImage", index), .layout = { .sizing = { CLAY_SIZING_FIXED(32) } }, .image = { .sourceDimensions = { 128, 128 }, .sourceURL = imageURL } }) {}
typedef struct {
void* memory;
uintptr_t offset;
} Arena;
Arena frameArena = {};
typedef struct {
Clay_String link;
bool cursorPointer;
bool disablePointerEvents;
} CustomHTMLData;
CustomHTMLData* FrameAllocateCustomData(CustomHTMLData data) {
CustomHTMLData *customData = (CustomHTMLData *)(frameArena.memory + frameArena.offset);
frameArena.offset += sizeof(CustomHTMLData);
return customData;
}
void LandingPageBlob(int index, int fontSize, Clay_Color color, Clay_String text, char* imageURL) {
CLAY({ .id = CLAY_IDI("HeroBlob", index), .layout = { .sizing = { CLAY_SIZING_GROW(.max = 480) }, .padding = CLAY_PADDING_ALL(16), .childGap = 16, .childAlignment = {.y = CLAY_ALIGN_Y_CENTER} }, .border = { .color = color, .width = { 2, 2, 2, 2 }}, .cornerRadius = CLAY_CORNER_RADIUS(10) }) {
CLAY({ .id = CLAY_IDI("CheckImage", index), .layout = { .sizing = { CLAY_SIZING_FIXED(32) } }, .image = { .sourceDimensions = { 128, 128 }, .imageData = imageURL } }) {}
CLAY_TEXT(text, CLAY_TEXT_CONFIG({ .fontSize = fontSize, .fontId = FONT_ID_BODY_24, .textColor = color }));
}
}
void LandingPageDesktop() {
CLAY({ .id = CLAY_ID("LandingPage1Desktop"), .layout = { .sizing = { .width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_FIT(.min = windowHeight - 70) }, .childAlignment = {.y = CLAY_ALIGN_Y_CENTER}, .padding = { 50, 50 } } }) {
CLAY({ .id = CLAY_ID("LandingPage1"), .layout = { .sizing = { CLAY_SIZING_GROW(0), CLAY_SIZING_GROW(0) }, .childAlignment = {.y = CLAY_ALIGN_Y_CENTER}, .padding = CLAY_PADDING_ALL(32), .childGap = 32 }, .border = { .left = { 2, COLOR_RED }, .right = { 2, COLOR_RED } } }) {
CLAY({ .id = CLAY_ID("LandingPage1"), .layout = { .sizing = { CLAY_SIZING_GROW(0), CLAY_SIZING_GROW(0) }, .childAlignment = {.y = CLAY_ALIGN_Y_CENTER}, .padding = CLAY_PADDING_ALL(32), .childGap = 32 }, .border = { .width = { .left = 2, .right = 2 }, .color = COLOR_RED } }) {
CLAY({ .id = CLAY_ID("LeftText"), .layout = { .sizing = { .width = CLAY_SIZING_PERCENT(0.55f) }, .layoutDirection = CLAY_TOP_TO_BOTTOM, .childGap = 8 } }) {
CLAY_TEXT(CLAY_STRING("Clay is a flex-box style UI auto layout library in C, with declarative syntax and microsecond performance."), CLAY_TEXT_CONFIG({ .fontSize = 56, .fontId = FONT_ID_TITLE_56, .textColor = COLOR_RED }));
CLAY({ .id = CLAY_ID("LandingPageSpacer"), .layout = { .sizing = { .width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_FIXED(32) } } }) {}
CLAY_TEXT(CLAY_STRING("Clay is laying out this webpage right now!"), CLAY_TEXT_CONFIG({ .fontSize = 36, .fontId = FONT_ID_TITLE_36, .textColor = COLOR_ORANGE }));
}
CLAY({ .id = CLAY_ID("HeroImageOuter"), .layout = { .layoutDirection = CLAY_TOP_TO_BOTTOM, .sizing = { .width = CLAY_SIZING_PERCENT(0.45f) }, .childAlignment = { CLAY_ALIGN_X_CENTER }, .childGap = 16 } }) {
LandingPageBlob(1, 32, COLOR_BLOB_BORDER_5, CLAY_STRING("High performance"), CLAY_STRING("/clay/images/check_5.png"));
LandingPageBlob(2, 32, COLOR_BLOB_BORDER_4, CLAY_STRING("Flexbox-style responsive layout"), CLAY_STRING("/clay/images/check_4.png"));
LandingPageBlob(3, 32, COLOR_BLOB_BORDER_3, CLAY_STRING("Declarative syntax"), CLAY_STRING("/clay/images/check_3.png"));
LandingPageBlob(4, 32, COLOR_BLOB_BORDER_2, CLAY_STRING("Single .h file for C/C++"), CLAY_STRING("/clay/images/check_2.png"));
LandingPageBlob(5, 32, COLOR_BLOB_BORDER_1, CLAY_STRING("Compile to 15kb .wasm"), CLAY_STRING("/clay/images/check_1.png"));
LandingPageBlob(1, 32, COLOR_BLOB_BORDER_5, CLAY_STRING("High performance"), "/clay/images/check_5.png");
LandingPageBlob(2, 32, COLOR_BLOB_BORDER_4, CLAY_STRING("Flexbox-style responsive layout"), "/clay/images/check_4.png");
LandingPageBlob(3, 32, COLOR_BLOB_BORDER_3, CLAY_STRING("Declarative syntax"), "/clay/images/check_3.png");
LandingPageBlob(4, 32, COLOR_BLOB_BORDER_2, CLAY_STRING("Single .h file for C/C++"), "/clay/images/check_2.png");
LandingPageBlob(5, 32, COLOR_BLOB_BORDER_1, CLAY_STRING("Compile to 15kb .wasm"), "/clay/images/check_1.png");
}
}
}
@ -74,21 +90,21 @@ void LandingPageMobile() {
CLAY_TEXT(CLAY_STRING("Clay is laying out this webpage right now!"), CLAY_TEXT_CONFIG({ .fontSize = 32, .fontId = FONT_ID_TITLE_36, .textColor = COLOR_ORANGE }));
}
CLAY({ .id = CLAY_ID("HeroImageOuter"), .layout = { .layoutDirection = CLAY_TOP_TO_BOTTOM, .sizing = { .width = CLAY_SIZING_GROW(0) }, .childAlignment = { CLAY_ALIGN_X_CENTER }, .childGap = 16 } }) {
LandingPageBlob(1, 28, COLOR_BLOB_BORDER_5, CLAY_STRING("High performance"), CLAY_STRING("/clay/images/check_5.png"));
LandingPageBlob(2, 28, COLOR_BLOB_BORDER_4, CLAY_STRING("Flexbox-style responsive layout"), CLAY_STRING("/clay/images/check_4.png"));
LandingPageBlob(3, 28, COLOR_BLOB_BORDER_3, CLAY_STRING("Declarative syntax"), CLAY_STRING("/clay/images/check_3.png"));
LandingPageBlob(4, 28, COLOR_BLOB_BORDER_2, CLAY_STRING("Single .h file for C/C++"), CLAY_STRING("/clay/images/check_2.png"));
LandingPageBlob(5, 28, COLOR_BLOB_BORDER_1, CLAY_STRING("Compile to 15kb .wasm"), CLAY_STRING("/clay/images/check_1.png"));
LandingPageBlob(1, 28, COLOR_BLOB_BORDER_5, CLAY_STRING("High performance"), "/clay/images/check_5.png");
LandingPageBlob(2, 28, COLOR_BLOB_BORDER_4, CLAY_STRING("Flexbox-style responsive layout"), "/clay/images/check_4.png");
LandingPageBlob(3, 28, COLOR_BLOB_BORDER_3, CLAY_STRING("Declarative syntax"), "/clay/images/check_3.png");
LandingPageBlob(4, 28, COLOR_BLOB_BORDER_2, CLAY_STRING("Single .h file for C/C++"), "/clay/images/check_2.png");
LandingPageBlob(5, 28, COLOR_BLOB_BORDER_1, CLAY_STRING("Compile to 15kb .wasm"), "/clay/images/check_1.png");
}
}
}
void FeatureBlocksDesktop() {
CLAY({ .id = CLAY_ID("FeatureBlocksOuter"), .layout = { .sizing = { CLAY_SIZING_GROW(0) } } }) {
CLAY({ .id = CLAY_ID("FeatureBlocksInner"), .layout = { .sizing = { CLAY_SIZING_GROW(0) }, .childAlignment = { .y = CLAY_ALIGN_Y_CENTER } }, .border = { .betweenChildren = { .width = 2, .color = COLOR_RED } }}) {
CLAY({ .id = CLAY_ID("FeatureBlocksInner"), .layout = { .sizing = { CLAY_SIZING_GROW(0) }, .childAlignment = { .y = CLAY_ALIGN_Y_CENTER } }, .border = { .width = { .betweenChildren = 2 }, .color = COLOR_RED } }) {
Clay_TextElementConfig *textConfig = CLAY_TEXT_CONFIG({ .fontSize = 24, .fontId = FONT_ID_BODY_24, .textColor = COLOR_RED });
CLAY({ .id = CLAY_ID("HFileBoxOuter"), .layout = { .layoutDirection = CLAY_TOP_TO_BOTTOM, .sizing = { CLAY_SIZING_PERCENT(0.5f) }, .childAlignment = {0, CLAY_ALIGN_Y_CENTER}, .padding = {50, 50, 32, 32}, .childGap = 8 } }) {
CLAY({ .id = CLAY_ID("HFileIncludeOuter"), .layout = { .padding = {8, 4} }, .rectangle = { .color = COLOR_RED }, .shared = { .cornerRadius = CLAY_CORNER_RADIUS(8) } }) {
CLAY({ .id = CLAY_ID("HFileIncludeOuter"), .layout = { .padding = {8, 4} }, .backgroundColor = COLOR_RED, .cornerRadius = CLAY_CORNER_RADIUS(8) }) {
CLAY_TEXT(CLAY_STRING("#include clay.h"), CLAY_TEXT_CONFIG({ .fontSize = 24, .fontId = FONT_ID_BODY_24, .textColor = COLOR_LIGHT }));
}
CLAY_TEXT(CLAY_STRING("~2000 lines of C99."), textConfig);
@ -104,10 +120,10 @@ void FeatureBlocksDesktop() {
}
void FeatureBlocksMobile() {
CLAY({ .id = CLAY_ID("FeatureBlocksInner"), .layout = { .layoutDirection = CLAY_TOP_TO_BOTTOM, .sizing = { CLAY_SIZING_GROW(0) } }, .border = { .betweenChildren = { .width = 2, .color = COLOR_RED } } }) {
CLAY({ .id = CLAY_ID("FeatureBlocksInner"), .layout = { .layoutDirection = CLAY_TOP_TO_BOTTOM, .sizing = { CLAY_SIZING_GROW(0) } }, .border = { .width = { .betweenChildren = 2 }, .color = COLOR_RED } }) {
Clay_TextElementConfig *textConfig = CLAY_TEXT_CONFIG({ .fontSize = 24, .fontId = FONT_ID_BODY_24, .textColor = COLOR_RED });
CLAY({ .id = CLAY_ID("HFileBoxOuter"), .layout = { .layoutDirection = CLAY_TOP_TO_BOTTOM, .sizing = { CLAY_SIZING_GROW(0) }, .childAlignment = {0, CLAY_ALIGN_Y_CENTER}, .padding = {16, 16, 32, 32}, .childGap = 8 } }) {
CLAY({ .id = CLAY_ID("HFileIncludeOuter"), .layout = { .padding = {8, 4} }, .rectangle = { .color = COLOR_RED }, .shared = { .cornerRadius = CLAY_CORNER_RADIUS(8) } }) {
CLAY({ .id = CLAY_ID("HFileIncludeOuter"), .layout = { .padding = {8, 4} }, .backgroundColor = COLOR_RED, .cornerRadius = CLAY_CORNER_RADIUS(8) }) {
CLAY_TEXT(CLAY_STRING("#include clay.h"), CLAY_TEXT_CONFIG({ .fontSize = 24, .fontId = FONT_ID_BODY_24, .textColor = COLOR_LIGHT }));
}
CLAY_TEXT(CLAY_STRING("~2000 lines of C99."), textConfig);
@ -123,7 +139,7 @@ void FeatureBlocksMobile() {
void DeclarativeSyntaxPageDesktop() {
CLAY({ .id = CLAY_ID("SyntaxPageDesktop"), .layout = { .sizing = { CLAY_SIZING_GROW(0), CLAY_SIZING_FIT(.min = windowHeight - 50) }, .childAlignment = {0, CLAY_ALIGN_Y_CENTER}, .padding = { 50, 50 } } }) {
CLAY({ .id = CLAY_ID("SyntaxPage"), .layout = { .sizing = { CLAY_SIZING_GROW(0), CLAY_SIZING_GROW(0) }, .childAlignment = { 0, CLAY_ALIGN_Y_CENTER }, .padding = CLAY_PADDING_ALL(32), .childGap = 32 }, .border = { .left = { 2, COLOR_RED }, .right = { 2, COLOR_RED } } }) {
CLAY({ .id = CLAY_ID("SyntaxPage"), .layout = { .sizing = { CLAY_SIZING_GROW(0), CLAY_SIZING_GROW(0) }, .childAlignment = { 0, CLAY_ALIGN_Y_CENTER }, .padding = CLAY_PADDING_ALL(32), .childGap = 32 }, .border = { .width = { .left = 2, .right = 2 }, .color = COLOR_RED }}) {
CLAY({ .id = CLAY_ID("SyntaxPageLeftText"), .layout = { .sizing = { CLAY_SIZING_PERCENT(0.5) }, .layoutDirection = CLAY_TOP_TO_BOTTOM, .childGap = 8 } }) {
CLAY_TEXT(CLAY_STRING("Declarative Syntax"), CLAY_TEXT_CONFIG({ .fontSize = 52, .fontId = FONT_ID_TITLE_56, .textColor = COLOR_RED }));
CLAY({ .id = CLAY_ID("SyntaxSpacer"), .layout = { .sizing = { CLAY_SIZING_GROW(.max = 16) } } }) {}
@ -132,7 +148,7 @@ void DeclarativeSyntaxPageDesktop() {
CLAY_TEXT(CLAY_STRING("Create your own library of re-usable components from UI primitives like text, images and rectangles."), CLAY_TEXT_CONFIG({ .fontSize = 28, .fontId = FONT_ID_BODY_36, .textColor = COLOR_RED }));
}
CLAY({ .id = CLAY_ID("SyntaxPageRightImage"), .layout = { .sizing = { CLAY_SIZING_PERCENT(0.50) }, .childAlignment = {.x = CLAY_ALIGN_X_CENTER} } }) {
CLAY({ .id = CLAY_ID("SyntaxPageRightImageInner"), .layout = { .sizing = { CLAY_SIZING_GROW(.max = 568) } }, .image = { .sourceDimensions = {1136, 1194}, .sourceURL = CLAY_STRING("/clay/images/declarative.png") } }) {}
CLAY({ .id = CLAY_ID("SyntaxPageRightImageInner"), .layout = { .sizing = { CLAY_SIZING_GROW(.max = 568) } }, .image = { .sourceDimensions = {1136, 1194}, .imageData = "/clay/images/declarative.png" } }) {}
}
}
}
@ -148,7 +164,7 @@ void DeclarativeSyntaxPageMobile() {
CLAY_TEXT(CLAY_STRING("Create your own library of re-usable components from UI primitives like text, images and rectangles."), CLAY_TEXT_CONFIG({ .fontSize = 28, .fontId = FONT_ID_BODY_36, .textColor = COLOR_RED }));
}
CLAY({ .id = CLAY_ID("SyntaxPageRightImage"), .layout = { .sizing = { CLAY_SIZING_GROW(0) }, .childAlignment = {.x = CLAY_ALIGN_X_CENTER} } }) {
CLAY({ .id = CLAY_ID("SyntaxPageRightImageInner"), .layout = { .sizing = { CLAY_SIZING_GROW(.max = 568) } }, .image = { .sourceDimensions = {1136, 1194}, .sourceURL = CLAY_STRING("/clay/images/declarative.png") } }) {}
CLAY({ .id = CLAY_ID("SyntaxPageRightImageInner"), .layout = { .sizing = { CLAY_SIZING_GROW(.max = 568) } }, .image = { .sourceDimensions = {1136, 1194}, .imageData = "/clay/images/declarative.png" } }) {}
}
}
}
@ -165,7 +181,7 @@ Clay_Color ColorLerp(Clay_Color a, Clay_Color b, float amount) {
Clay_String LOREM_IPSUM_TEXT = CLAY_STRING("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.");
void HighPerformancePageDesktop(float lerpValue) {
CLAY({ .id = CLAY_ID("PerformanceOuter"), .layout = { .sizing = { CLAY_SIZING_GROW(0), CLAY_SIZING_FIT(.min = windowHeight - 50) }, .childAlignment = {0, CLAY_ALIGN_Y_CENTER}, .padding = {82, 82, 32, 32}, .childGap = 64 }, .rectangle = { .color = COLOR_RED } }) {
CLAY({ .id = CLAY_ID("PerformanceOuter"), .layout = { .sizing = { CLAY_SIZING_GROW(0), CLAY_SIZING_FIT(.min = windowHeight - 50) }, .childAlignment = {0, CLAY_ALIGN_Y_CENTER}, .padding = {82, 82, 32, 32}, .childGap = 64 }, .backgroundColor = COLOR_RED }) {
CLAY({ .id = CLAY_ID("PerformanceLeftText"), .layout = { .sizing = { CLAY_SIZING_PERCENT(0.5) }, .layoutDirection = CLAY_TOP_TO_BOTTOM, .childGap = 8 } }) {
CLAY_TEXT(CLAY_STRING("High Performance"), CLAY_TEXT_CONFIG({ .fontSize = 52, .fontId = FONT_ID_TITLE_56, .textColor = COLOR_LIGHT }));
CLAY({ .id = CLAY_ID("PerformanceSpacer"), .layout = { .sizing = { CLAY_SIZING_GROW(.max = 16) }} }) {}
@ -174,11 +190,11 @@ void HighPerformancePageDesktop(float lerpValue) {
CLAY_TEXT(CLAY_STRING("Simplify animations and reactive UI design by avoiding the standard performance hacks."), CLAY_TEXT_CONFIG({ .fontSize = 28, .fontId = FONT_ID_BODY_36, .textColor = COLOR_LIGHT }));
}
CLAY({ .id = CLAY_ID("PerformanceRightImageOuter"), .layout = { .sizing = { CLAY_SIZING_PERCENT(0.50) }, .childAlignment = {CLAY_ALIGN_X_CENTER} } }) {
CLAY({ .layout = { .sizing = { CLAY_SIZING_GROW(0), CLAY_SIZING_FIXED(400) } }, .border = CLAY_BORDER_ALL({ .width = 2, .color = COLOR_LIGHT }) }) {
CLAY({ .id = CLAY_ID("AnimationDemoContainerLeft"), .layout = { .sizing = { CLAY_SIZING_PERCENT(0.3f + 0.4f * lerpValue), CLAY_SIZING_GROW(0) }, .childAlignment = {.y = CLAY_ALIGN_Y_CENTER}, .padding = CLAY_PADDING_ALL(32) }, .rectangle = { .color = ColorLerp(COLOR_RED, COLOR_ORANGE, lerpValue) } }) {
CLAY({ .layout = { .sizing = { CLAY_SIZING_GROW(0), CLAY_SIZING_FIXED(400) } }, .border = { .width = {2, 2, 2, 2}, .color = COLOR_LIGHT } }) {
CLAY({ .id = CLAY_ID("AnimationDemoContainerLeft"), .layout = { .sizing = { CLAY_SIZING_PERCENT(0.3f + 0.4f * lerpValue), CLAY_SIZING_GROW(0) }, .childAlignment = {.y = CLAY_ALIGN_Y_CENTER}, .padding = CLAY_PADDING_ALL(32) }, .backgroundColor = ColorLerp(COLOR_RED, COLOR_ORANGE, lerpValue) }) {
CLAY_TEXT(LOREM_IPSUM_TEXT, CLAY_TEXT_CONFIG({ .fontSize = 24, .fontId = FONT_ID_TITLE_56, .textColor = COLOR_LIGHT }));
}
CLAY({ .id = CLAY_ID("AnimationDemoContainerRight"), .layout = { .sizing = { CLAY_SIZING_GROW(0), CLAY_SIZING_GROW(0) }, .childAlignment = {.y = CLAY_ALIGN_Y_CENTER}, .padding = CLAY_PADDING_ALL(32) }, .rectangle = { .color = ColorLerp(COLOR_ORANGE, COLOR_RED, lerpValue) } }) {
CLAY({ .id = CLAY_ID("AnimationDemoContainerRight"), .layout = { .sizing = { CLAY_SIZING_GROW(0), CLAY_SIZING_GROW(0) }, .childAlignment = {.y = CLAY_ALIGN_Y_CENTER}, .padding = CLAY_PADDING_ALL(32) }, .backgroundColor = ColorLerp(COLOR_ORANGE, COLOR_RED, lerpValue) }) {
CLAY_TEXT(LOREM_IPSUM_TEXT, CLAY_TEXT_CONFIG({ .fontSize = 24, .fontId = FONT_ID_TITLE_56, .textColor = COLOR_LIGHT }));
}
}
@ -187,7 +203,7 @@ void HighPerformancePageDesktop(float lerpValue) {
}
void HighPerformancePageMobile(float lerpValue) {
CLAY({ .id = CLAY_ID("PerformanceOuter"), .layout = { .layoutDirection = CLAY_TOP_TO_BOTTOM, .sizing = { CLAY_SIZING_GROW(0), CLAY_SIZING_FIT(.min = windowHeight - 50) }, .childAlignment = {CLAY_ALIGN_X_CENTER, CLAY_ALIGN_Y_CENTER}, .padding = {16, 16, 32, 32}, .childGap = 32 }, .rectangle = { .color = COLOR_RED } }) {
CLAY({ .id = CLAY_ID("PerformanceOuter"), .layout = { .layoutDirection = CLAY_TOP_TO_BOTTOM, .sizing = { CLAY_SIZING_GROW(0), CLAY_SIZING_FIT(.min = windowHeight - 50) }, .childAlignment = {CLAY_ALIGN_X_CENTER, CLAY_ALIGN_Y_CENTER}, .padding = {16, 16, 32, 32}, .childGap = 32 }, .backgroundColor = COLOR_RED }) {
CLAY({ .id = CLAY_ID("PerformanceLeftText"), .layout = { .sizing = { CLAY_SIZING_GROW(0) }, .layoutDirection = CLAY_TOP_TO_BOTTOM, .childGap = 8 } }) {
CLAY_TEXT(CLAY_STRING("High Performance"), CLAY_TEXT_CONFIG({ .fontSize = 48, .fontId = FONT_ID_TITLE_56, .textColor = COLOR_LIGHT }));
CLAY({ .id = CLAY_ID("PerformanceSpacer"), .layout = { .sizing = { CLAY_SIZING_GROW(.max = 16) }} }) {}
@ -196,11 +212,11 @@ void HighPerformancePageMobile(float lerpValue) {
CLAY_TEXT(CLAY_STRING("Simplify animations and reactive UI design by avoiding the standard performance hacks."), CLAY_TEXT_CONFIG({ .fontSize = 28, .fontId = FONT_ID_BODY_36, .textColor = COLOR_LIGHT }));
}
CLAY({ .id = CLAY_ID("PerformanceRightImageOuter"), .layout = { .sizing = { CLAY_SIZING_GROW(0) }, .childAlignment = {CLAY_ALIGN_X_CENTER} } }) {
CLAY({ .id = CLAY_ID(""), .layout = { .sizing = { CLAY_SIZING_GROW(0), CLAY_SIZING_FIXED(400) } }, .border = CLAY_BORDER_ALL({ .width = 2, .color = COLOR_LIGHT }) }) {
CLAY({ .id = CLAY_ID("AnimationDemoContainerLeft"), .layout = { .sizing = { CLAY_SIZING_PERCENT(0.35f + 0.3f * lerpValue), CLAY_SIZING_GROW(0) }, .childAlignment = {.y = CLAY_ALIGN_Y_CENTER}, .padding = CLAY_PADDING_ALL(16) }, .rectangle = { .color = ColorLerp(COLOR_RED, COLOR_ORANGE, lerpValue) } }) {
CLAY({ .id = CLAY_ID(""), .layout = { .sizing = { CLAY_SIZING_GROW(0), CLAY_SIZING_FIXED(400) } }, .border = { .width = { 2, 2, 2, 2 }, .color = COLOR_LIGHT }}) {
CLAY({ .id = CLAY_ID("AnimationDemoContainerLeft"), .layout = { .sizing = { CLAY_SIZING_PERCENT(0.35f + 0.3f * lerpValue), CLAY_SIZING_GROW(0) }, .childAlignment = {.y = CLAY_ALIGN_Y_CENTER}, .padding = CLAY_PADDING_ALL(16) }, .backgroundColor = ColorLerp(COLOR_RED, COLOR_ORANGE, lerpValue) }) {
CLAY_TEXT(LOREM_IPSUM_TEXT, CLAY_TEXT_CONFIG({ .fontSize = 24, .fontId = FONT_ID_TITLE_56, .textColor = COLOR_LIGHT }));
}
CLAY({ .id = CLAY_ID("AnimationDemoContainerRight"), .layout = { .sizing = { CLAY_SIZING_GROW(0), CLAY_SIZING_GROW(0) }, .childAlignment = {.y = CLAY_ALIGN_Y_CENTER}, .padding = CLAY_PADDING_ALL(16) }, .rectangle = { .color = ColorLerp(COLOR_ORANGE, COLOR_RED, lerpValue) } }) {
CLAY({ .id = CLAY_ID("AnimationDemoContainerRight"), .layout = { .sizing = { CLAY_SIZING_GROW(0), CLAY_SIZING_GROW(0) }, .childAlignment = {.y = CLAY_ALIGN_Y_CENTER}, .padding = CLAY_PADDING_ALL(16) }, .backgroundColor = ColorLerp(COLOR_ORANGE, COLOR_RED, lerpValue) }) {
CLAY_TEXT(LOREM_IPSUM_TEXT, CLAY_TEXT_CONFIG({ .fontSize = 24, .fontId = FONT_ID_TITLE_56, .textColor = COLOR_LIGHT }));
}
}
@ -219,28 +235,30 @@ void HandleRendererButtonInteraction(Clay_ElementId elementId, Clay_PointerData
void RendererButtonActive(Clay_String text) {
CLAY({
.layout = { .sizing = {CLAY_SIZING_FIXED(300) }, .padding = CLAY_PADDING_ALL(16) },
.rectangle = { .color = Clay_Hovered() ? COLOR_RED_HOVER : COLOR_RED },
.shared = { .cornerRadius = CLAY_CORNER_RADIUS(10) }
.backgroundColor = Clay_Hovered() ? COLOR_RED_HOVER : COLOR_RED,
.cornerRadius = CLAY_CORNER_RADIUS(10),
.custom = { .customData = FrameAllocateCustomData((CustomHTMLData) { .disablePointerEvents = true, .cursorPointer = true })}
}) {
CLAY_TEXT(text, CLAY_TEXT_CONFIG({ .disablePointerEvents = true, .fontSize = 28, .fontId = FONT_ID_BODY_36, .textColor = COLOR_LIGHT }));
CLAY_TEXT(text, CLAY_TEXT_CONFIG({ .fontSize = 28, .fontId = FONT_ID_BODY_36, .textColor = COLOR_LIGHT }));
}
}
void RendererButtonInactive(Clay_String text, size_t rendererIndex) {
CLAY({
.layout = { .sizing = {CLAY_SIZING_FIXED(300)}, .padding = CLAY_PADDING_ALL(16) },
.border = CLAY_BORDER_OUTSIDE({ 2, COLOR_RED }),
.rectangle = { .color = Clay_Hovered() ? COLOR_LIGHT_HOVER : COLOR_LIGHT, .cursorPointer = true },
.shared = { .cornerRadius = CLAY_CORNER_RADIUS(10) }
.border = { .width = {2, 2, 2, 2}, .color = COLOR_RED },
.backgroundColor = Clay_Hovered() ? COLOR_LIGHT_HOVER : COLOR_LIGHT,
.cornerRadius = CLAY_CORNER_RADIUS(10),
.custom = { .customData = FrameAllocateCustomData((CustomHTMLData) { .disablePointerEvents = true, .cursorPointer = true })}
}) {
Clay_OnHover(HandleRendererButtonInteraction, rendererIndex);
CLAY_TEXT(text, CLAY_TEXT_CONFIG({ .disablePointerEvents = true, .fontSize = 28, .fontId = FONT_ID_BODY_36, .textColor = COLOR_RED }));
CLAY_TEXT(text, CLAY_TEXT_CONFIG({ .fontSize = 28, .fontId = FONT_ID_BODY_36, .textColor = COLOR_RED }));
}
}
void RendererPageDesktop() {
CLAY({ .id = CLAY_ID("RendererPageDesktop"), .layout = { .sizing = { CLAY_SIZING_GROW(0), CLAY_SIZING_FIT(.min = windowHeight - 50) }, .childAlignment = {0, CLAY_ALIGN_Y_CENTER}, .padding = { 50, 50 } } }) {
CLAY({ .id = CLAY_ID("RendererPage"), .layout = { .sizing = { CLAY_SIZING_GROW(0), CLAY_SIZING_GROW(0) }, .childAlignment = { 0, CLAY_ALIGN_Y_CENTER }, .padding = CLAY_PADDING_ALL(32), .childGap = 32 }, .border = { .left = { 2, COLOR_RED }, .right = { 2, COLOR_RED } } }) {
CLAY({ .id = CLAY_ID("RendererPage"), .layout = { .sizing = { CLAY_SIZING_GROW(0), CLAY_SIZING_GROW(0) }, .childAlignment = { 0, CLAY_ALIGN_Y_CENTER }, .padding = CLAY_PADDING_ALL(32), .childGap = 32 }, .border = { .width = { .left = 2, .right = 2 }, .color = COLOR_RED } }) {
CLAY({ .id = CLAY_ID("RendererLeftText"), .layout = { .sizing = { CLAY_SIZING_PERCENT(0.5) }, .layoutDirection = CLAY_TOP_TO_BOTTOM, .childGap = 8 } }) {
CLAY_TEXT(CLAY_STRING("Renderer & Platform Agnostic"), CLAY_TEXT_CONFIG({ .fontSize = 52, .fontId = FONT_ID_TITLE_56, .textColor = COLOR_RED }));
CLAY({ .id = CLAY_ID("RendererSpacerLeft"), .layout = { .sizing = { CLAY_SIZING_GROW(.max = 16) }} }) {}
@ -264,7 +282,7 @@ void RendererPageDesktop() {
}
void RendererPageMobile() {
CLAY({ .id = CLAY_ID("RendererMobile"), .layout = { .layoutDirection = CLAY_TOP_TO_BOTTOM, .sizing = { CLAY_SIZING_GROW(0), CLAY_SIZING_FIT(.min = windowHeight - 50) }, .childAlignment = {.x = CLAY_ALIGN_X_CENTER, .y = CLAY_ALIGN_Y_CENTER}, .padding = { 16, 16, 32, 32}, .childGap = 32 }, .rectangle = { .color = COLOR_LIGHT } }) {
CLAY({ .id = CLAY_ID("RendererMobile"), .layout = { .layoutDirection = CLAY_TOP_TO_BOTTOM, .sizing = { CLAY_SIZING_GROW(0), CLAY_SIZING_FIT(.min = windowHeight - 50) }, .childAlignment = {.x = CLAY_ALIGN_X_CENTER, .y = CLAY_ALIGN_Y_CENTER}, .padding = { 16, 16, 32, 32}, .childGap = 32 }, .backgroundColor = COLOR_LIGHT }) {
CLAY({ .id = CLAY_ID("RendererLeftText"), .layout = { .sizing = { CLAY_SIZING_GROW(0) }, .layoutDirection = CLAY_TOP_TO_BOTTOM, .childGap = 8 } }) {
CLAY_TEXT(CLAY_STRING("Renderer & Platform Agnostic"), CLAY_TEXT_CONFIG({ .fontSize = 48, .fontId = FONT_ID_TITLE_56, .textColor = COLOR_RED }));
CLAY({ .id = CLAY_ID("RendererSpacerLeft"), .layout = { .sizing = { CLAY_SIZING_GROW(.max = 16) }} }) {}
@ -287,7 +305,7 @@ void RendererPageMobile() {
}
void DebuggerPageDesktop() {
CLAY({ .id = CLAY_ID("DebuggerDesktop"), .layout = { .sizing = { CLAY_SIZING_GROW(0), CLAY_SIZING_FIT(.min = windowHeight - 50) }, .childAlignment = {0, CLAY_ALIGN_Y_CENTER}, .padding = { 82, 82, 32, 32 }, .childGap = 64 }, .rectangle = { .color = COLOR_RED } }) {
CLAY({ .id = CLAY_ID("DebuggerDesktop"), .layout = { .sizing = { CLAY_SIZING_GROW(0), CLAY_SIZING_FIT(.min = windowHeight - 50) }, .childAlignment = {0, CLAY_ALIGN_Y_CENTER}, .padding = { 82, 82, 32, 32 }, .childGap = 64 }, .backgroundColor = COLOR_RED }) {
CLAY({ .id = CLAY_ID("DebuggerLeftText"), .layout = { .sizing = { CLAY_SIZING_PERCENT(0.5) }, .layoutDirection = CLAY_TOP_TO_BOTTOM, .childGap = 8 } }) {
CLAY_TEXT(CLAY_STRING("Integrated Debug Tools"), CLAY_TEXT_CONFIG({ .fontSize = 52, .fontId = FONT_ID_TITLE_56, .textColor = COLOR_LIGHT }));
CLAY({ .id = CLAY_ID("DebuggerSpacer"), .layout = { .sizing = { CLAY_SIZING_GROW(.max = 16) }} }) {}
@ -297,7 +315,7 @@ void DebuggerPageDesktop() {
CLAY_TEXT(CLAY_STRING("Press the \"d\" key to try it out now!"), CLAY_TEXT_CONFIG({ .fontSize = 32, .fontId = FONT_ID_TITLE_36, .textColor = COLOR_ORANGE }));
}
CLAY({ .id = CLAY_ID("DebuggerRightImageOuter"), .layout = { .sizing = { CLAY_SIZING_PERCENT(0.50) }, .childAlignment = {CLAY_ALIGN_X_CENTER} } }) {
CLAY({ .id = CLAY_ID("DebuggerPageRightImageInner"), .layout = { .sizing = { CLAY_SIZING_GROW(.max = 558) } }, .image = { .sourceDimensions = {1620, 1474}, .sourceURL = CLAY_STRING("/clay/images/debugger.png") } }) {}
CLAY({ .id = CLAY_ID("DebuggerPageRightImageInner"), .layout = { .sizing = { CLAY_SIZING_GROW(.max = 558) } }, .image = { .sourceDimensions = {1620, 1474}, .imageData = "/clay/images/debugger.png" } }) {}
}
}
}
@ -314,45 +332,47 @@ float animationLerpValue = -1.0f;
Clay_RenderCommandArray CreateLayout(bool mobileScreen, float lerpValue) {
Clay_BeginLayout();
CLAY({ .id = CLAY_ID("OuterContainer"), .layout = { .layoutDirection = CLAY_TOP_TO_BOTTOM, .sizing = { CLAY_SIZING_GROW(0), CLAY_SIZING_GROW(0) } }, .rectangle = { .color = COLOR_LIGHT } }) {
CLAY({ .id = CLAY_ID("OuterContainer"), .layout = { .layoutDirection = CLAY_TOP_TO_BOTTOM, .sizing = { CLAY_SIZING_GROW(0), CLAY_SIZING_GROW(0) } }, .backgroundColor = COLOR_LIGHT }) {
CLAY({ .id = CLAY_ID("Header"), .layout = { .sizing = { CLAY_SIZING_GROW(0), CLAY_SIZING_FIXED(50) }, .childAlignment = { 0, CLAY_ALIGN_Y_CENTER }, .childGap = 16, .padding = { 32, 32 } } }) {
CLAY_TEXT(CLAY_STRING("Clay"), &headerTextConfig);
CLAY({ .id = CLAY_ID("Spacer"), .layout = { .sizing = { .width = CLAY_SIZING_GROW(0) } } }) {}
if (!mobileScreen) {
CLAY({ .id = CLAY_ID("LinkExamplesOuter"), .layout = { .padding = {8, 8} }, .rectangle = { .link = CLAY_STRING("https://github.com/nicbarker/clay/tree/main/examples"), .color = {0,0,0,0} } }) {
CLAY_TEXT(CLAY_STRING("Examples"), CLAY_TEXT_CONFIG({ .disablePointerEvents = true, .fontId = FONT_ID_BODY_24, .fontSize = 24, .textColor = {61, 26, 5, 255} }));
CLAY({ .id = CLAY_ID("LinkExamplesOuter"), .layout = { .padding = {8, 8} }, .custom = { .customData = FrameAllocateCustomData((CustomHTMLData) { .link = CLAY_STRING("https://github.com/nicbarker/clay/tree/main/examples") }) } }) {
CLAY_TEXT(CLAY_STRING("Examples"), CLAY_TEXT_CONFIG({ .fontId = FONT_ID_BODY_24, .fontSize = 24, .textColor = {61, 26, 5, 255} }));
}
CLAY({ .id = CLAY_ID("LinkDocsOuter"), .layout = { .padding = {8, 8} }, .rectangle = { .link = CLAY_STRING("https://github.com/nicbarker/clay/blob/main/README.md"), .color = {0,0,0,0} } }) {
CLAY_TEXT(CLAY_STRING("Docs"), CLAY_TEXT_CONFIG({ .disablePointerEvents = true, .fontId = FONT_ID_BODY_24, .fontSize = 24, .textColor = {61, 26, 5, 255} }));
CLAY({ .id = CLAY_ID("LinkDocsOuter"), .layout = { .padding = {8, 8} }, .custom = { .customData = FrameAllocateCustomData((CustomHTMLData) { .link = CLAY_STRING("https://github.com/nicbarker/clay/blob/main/README.md") }) } }) {
CLAY_TEXT(CLAY_STRING("Docs"), CLAY_TEXT_CONFIG({ .fontId = FONT_ID_BODY_24, .fontSize = 24, .textColor = {61, 26, 5, 255} }));
}
}
CLAY({
.layout = { .padding = {16, 16, 6, 6} },
.rectangle = {.link = CLAY_STRING("https://discord.gg/b4FTWkxdvT"), .color = Clay_Hovered() ? COLOR_LIGHT_HOVER : COLOR_LIGHT},
.border = CLAY_BORDER_OUTSIDE({ 2, COLOR_RED }),
.shared = { .cornerRadius = CLAY_CORNER_RADIUS(10) }
.backgroundColor = Clay_Hovered() ? COLOR_LIGHT_HOVER : COLOR_LIGHT,
.border = { .width = {2, 2, 2, 2}, .color = COLOR_RED },
.cornerRadius = CLAY_CORNER_RADIUS(10),
.custom = { .customData = FrameAllocateCustomData((CustomHTMLData) { .link = CLAY_STRING("https://github.com/nicbarker/clay/tree/main/examples") }) },
}) {
CLAY_TEXT(CLAY_STRING("Discord"), CLAY_TEXT_CONFIG({ .disablePointerEvents = true, .fontId = FONT_ID_BODY_24, .fontSize = 24, .textColor = {61, 26, 5, 255} }));
CLAY_TEXT(CLAY_STRING("Discord"), CLAY_TEXT_CONFIG({ .fontId = FONT_ID_BODY_24, .fontSize = 24, .textColor = {61, 26, 5, 255} }));
}
CLAY({
.layout = { .padding = {16, 16, 6, 6} },
.rectangle = { .link = CLAY_STRING("https://github.com/nicbarker/clay"), .color = Clay_Hovered() ? COLOR_LIGHT_HOVER : COLOR_LIGHT },
.border = CLAY_BORDER_OUTSIDE({ 2, COLOR_RED }),
.shared = { .cornerRadius = CLAY_CORNER_RADIUS(10) }
.backgroundColor = Clay_Hovered() ? COLOR_LIGHT_HOVER : COLOR_LIGHT,
.border = { .width = {2, 2, 2, 2}, .color = COLOR_RED },
.cornerRadius = CLAY_CORNER_RADIUS(10),
.custom = { .customData = FrameAllocateCustomData((CustomHTMLData) { .link = CLAY_STRING("https://github.com/nicbarker/clay") }) },
}) {
CLAY_TEXT(CLAY_STRING("Github"), CLAY_TEXT_CONFIG({ .disablePointerEvents = true, .fontId = FONT_ID_BODY_24, .fontSize = 24, .textColor = {61, 26, 5, 255} }));
CLAY_TEXT(CLAY_STRING("Github"), CLAY_TEXT_CONFIG({ .fontId = FONT_ID_BODY_24, .fontSize = 24, .textColor = {61, 26, 5, 255} }));
}
}
Clay_LayoutConfig topBorderConfig = (Clay_LayoutConfig) { .sizing = { CLAY_SIZING_GROW(0), CLAY_SIZING_FIXED(4) }};
CLAY({ .id = CLAY_ID("TopBorder1"), .layout = topBorderConfig, .rectangle = { .color = COLOR_TOP_BORDER_5 } }) {}
CLAY({ .id = CLAY_ID("TopBorder2"), .layout = topBorderConfig, .rectangle = { .color = COLOR_TOP_BORDER_4 } }) {}
CLAY({ .id = CLAY_ID("TopBorder3"), .layout = topBorderConfig, .rectangle = { .color = COLOR_TOP_BORDER_3 } }) {}
CLAY({ .id = CLAY_ID("TopBorder4"), .layout = topBorderConfig, .rectangle = { .color = COLOR_TOP_BORDER_2 } }) {}
CLAY({ .id = CLAY_ID("TopBorder5"), .layout = topBorderConfig, .rectangle = { .color = COLOR_TOP_BORDER_1 } }) {}
CLAY({ .id = CLAY_ID("TopBorder1"), .layout = topBorderConfig, .backgroundColor = COLOR_TOP_BORDER_5 }) {}
CLAY({ .id = CLAY_ID("TopBorder2"), .layout = topBorderConfig, .backgroundColor = COLOR_TOP_BORDER_4 }) {}
CLAY({ .id = CLAY_ID("TopBorder3"), .layout = topBorderConfig, .backgroundColor = COLOR_TOP_BORDER_3 }) {}
CLAY({ .id = CLAY_ID("TopBorder4"), .layout = topBorderConfig, .backgroundColor = COLOR_TOP_BORDER_2 }) {}
CLAY({ .id = CLAY_ID("TopBorder5"), .layout = topBorderConfig, .backgroundColor = COLOR_TOP_BORDER_1 }) {}
CLAY({ .id = CLAY_ID("OuterScrollContainer"),
.layout = { .sizing = { CLAY_SIZING_GROW(0), CLAY_SIZING_GROW(0) }, .layoutDirection = CLAY_TOP_TO_BOTTOM },
.scroll = { .vertical = true },
.border = { .betweenChildren = { 2, COLOR_RED } }
.border = { .width = { .betweenChildren = 2 }, .color = COLOR_RED }
}) {
if (mobileScreen) {
LandingPageMobile();
@ -380,11 +400,12 @@ Clay_RenderCommandArray CreateLayout(bool mobileScreen, float lerpValue) {
scrollbarColor = (Clay_Color){225, 138, 50, 160};
}
float scrollHeight = scrollData.scrollContainerDimensions.height - 12;
CLAY({ .id = CLAY_ID("ScrollBar"),
CLAY({
.id = CLAY_ID("ScrollBar"),
.floating = { .offset = { .x = -6, .y = -(scrollData.scrollPosition->y / scrollData.contentDimensions.height) * scrollHeight + 6}, .zIndex = 1, .parentId = Clay_GetElementId(CLAY_STRING("OuterScrollContainer")).id, .attachment = {.element = CLAY_ATTACH_POINT_RIGHT_TOP, .parent = CLAY_ATTACH_POINT_RIGHT_TOP }},
.layout = { .sizing = {CLAY_SIZING_FIXED(10), CLAY_SIZING_FIXED((scrollHeight / scrollData.contentDimensions.height) * scrollHeight)} },
.rectangle = { .color = scrollbarColor },
.shared = { .cornerRadius = CLAY_CORNER_RADIUS(5) }
.backgroundColor = scrollbarColor,
.cornerRadius = CLAY_CORNER_RADIUS(5)
}) {}
}
return Clay_EndLayout();

View File

@ -13,7 +13,7 @@ int main(void) {
Clay_Arena clayMemory = Clay_CreateArenaWithCapacityAndMemory(totalMemorySize, (char *)malloc(totalMemorySize));
Clay_Initialize(clayMemory, Clay_Dimensions {1024,768}, Clay_ErrorHandler { HandleClayErrors });
Clay_BeginLayout();
CLAY({ .layout = layoutElement, .rectangle = { .color = {255,255,255,0} } }) {
CLAY({ .layout = layoutElement, .backgroundColor = {255,255,255,0} }) {
CLAY_TEXT(CLAY_STRING(""), CLAY_TEXT_CONFIG({ .fontId = 0 }));
}
Clay_EndLayout();

View File

@ -4,8 +4,8 @@
const uint32_t FONT_ID_BODY_24 = 0;
const uint32_t FONT_ID_BODY_16 = 1;
#define COLOR_ORANGE {225, 138, 50, 255}
#define COLOR_BLUE {111, 173, 162, 255}
#define COLOR_ORANGE (Clay_Color) {225, 138, 50, 255}
#define COLOR_BLUE (Clay_Color) {111, 173, 162, 255}
Texture2D profilePicture;
#define RAYLIB_VECTOR2_TO_CLAY_VECTOR2(vector) (Clay_Vector2) { .x = vector.x, .y = vector.y }
@ -19,62 +19,60 @@ void HandleHeaderButtonInteraction(Clay_ElementId elementId, Clay_PointerData po
}
}
Clay_ElementDeclaration headerButtonStyle = {
.layout = {.padding = {16, 16, 8, 8}},
.rectangle = { .color = COLOR_BLUE }
};
Clay_ElementDeclaration HeaderButtonStyle(bool hovered) {
return (Clay_ElementDeclaration) {
.layout = {.padding = {16, 16, 8, 8}},
.backgroundColor = hovered ? COLOR_ORANGE : COLOR_BLUE,
};
}
// Examples of re-usable "Components"
void RenderHeaderButton(Clay_String text) {
CLAY(headerButtonStyle) {
if (Clay_Hovered()) {
Clay_CurrentConfigRectangle()->color = (Clay_Color) COLOR_ORANGE;
}
CLAY(HeaderButtonStyle(Clay_Hovered())) {
CLAY_TEXT(text, CLAY_TEXT_CONFIG(headerTextConfig));
}
}
Clay_LayoutConfig dropdownTextItemLayout = { .padding = {8, 8, 4, 4} };
Clay_RectangleElementConfig dropdownRectangleConfig = { .color = {180, 180, 180, 255} };
Clay_TextElementConfig dropdownTextElementConfig = { .fontSize = 24, .textColor = {255,255,255,255} };
void RenderDropdownTextItem(int index) {
CLAY({ .id = CLAY_IDI("ScrollContainerItem", index), .layout = dropdownTextItemLayout, .rectangle = dropdownRectangleConfig }) {
CLAY({ .id = CLAY_IDI("ScrollContainerItem", index), .layout = dropdownTextItemLayout, .backgroundColor = {180, 180, 180, 255} }) {
CLAY_TEXT(CLAY_STRING("I'm a text field in a scroll container."), &dropdownTextElementConfig);
}
}
Clay_RenderCommandArray CreateLayout(void) {
Clay_BeginLayout();
CLAY({ .id = CLAY_ID("OuterContainer"), .layout = { .sizing = { .width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_GROW(0) }, .padding = { 16, 16, 16, 16 }, .childGap = 16 }, .rectangle = { .color = {200, 200, 200, 255} }}) {
CLAY({ .id = CLAY_ID("SideBar"), .layout = { .layoutDirection = CLAY_TOP_TO_BOTTOM, .sizing = { .width = CLAY_SIZING_FIXED(300), .height = CLAY_SIZING_GROW(0) }, .padding = {16, 16, 16, 16 }, .childGap = 16 }, .rectangle = { .color = {150, 150, 255, 255} }}) {
CLAY({ .id = CLAY_ID("ProfilePictureOuter"), .layout = { .sizing = { .width = CLAY_SIZING_GROW(0) }, .padding = { 8, 8, 8, 8 }, .childGap = 8, .childAlignment = { .y = CLAY_ALIGN_Y_CENTER } }, .rectangle = { .color = {130, 130, 255, 255} }}) {
CLAY({ .id = CLAY_ID("OuterContainer"), .layout = { .sizing = { .width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_GROW(0) }, .padding = { 16, 16, 16, 16 }, .childGap = 16 }, .backgroundColor = {200, 200, 200, 255} }) {
CLAY({ .id = CLAY_ID("SideBar"), .layout = { .layoutDirection = CLAY_TOP_TO_BOTTOM, .sizing = { .width = CLAY_SIZING_FIXED(300), .height = CLAY_SIZING_GROW(0) }, .padding = {16, 16, 16, 16 }, .childGap = 16 }, .backgroundColor = {150, 150, 255, 255} }) {
CLAY({ .id = CLAY_ID("ProfilePictureOuter"), .layout = { .sizing = { .width = CLAY_SIZING_GROW(0) }, .padding = { 8, 8, 8, 8 }, .childGap = 8, .childAlignment = { .y = CLAY_ALIGN_Y_CENTER } }, .backgroundColor = {130, 130, 255, 255} }) {
CLAY({ .id = CLAY_ID("ProfilePicture"), .layout = { .sizing = { .width = CLAY_SIZING_FIXED(60), .height = CLAY_SIZING_FIXED(60) } }, .image = { .imageData = &profilePicture, .sourceDimensions = {60, 60} }}) {}
CLAY_TEXT(profileText, CLAY_TEXT_CONFIG({ .fontSize = 24, .textColor = {0, 0, 0, 255} }));
}
CLAY({ .id = CLAY_ID("SidebarBlob1"), .layout = { .sizing = { .width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_FIXED(50) }}, .rectangle = { .color = {110, 110, 255, 255} }}) {}
CLAY({ .id = CLAY_ID("SidebarBlob2"), .layout = { .sizing = { .width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_FIXED(50) }}, .rectangle = { .color = {110, 110, 255, 255} }}) {}
CLAY({ .id = CLAY_ID("SidebarBlob3"), .layout = { .sizing = { .width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_FIXED(50) }}, .rectangle = { .color = {110, 110, 255, 255} }}) {}
CLAY({ .id = CLAY_ID("SidebarBlob4"), .layout = { .sizing = { .width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_FIXED(50) }}, .rectangle = { .color = {110, 110, 255, 255} }}) {}
CLAY({ .id = CLAY_ID("SidebarBlob1"), .layout = { .sizing = { .width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_FIXED(50) }}, .backgroundColor = {110, 110, 255, 255} }) {}
CLAY({ .id = CLAY_ID("SidebarBlob2"), .layout = { .sizing = { .width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_FIXED(50) }}, .backgroundColor = {110, 110, 255, 255} }) {}
CLAY({ .id = CLAY_ID("SidebarBlob3"), .layout = { .sizing = { .width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_FIXED(50) }}, .backgroundColor = {110, 110, 255, 255} }) {}
CLAY({ .id = CLAY_ID("SidebarBlob4"), .layout = { .sizing = { .width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_FIXED(50) }}, .backgroundColor = {110, 110, 255, 255} }) {}
}
CLAY({ .id = CLAY_ID("RightPanel"), .layout = { .layoutDirection = CLAY_TOP_TO_BOTTOM, .sizing = { .width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_GROW(0) }, .childGap = 16 }}) {
CLAY({ .id = CLAY_ID("HeaderBar"), .layout = { .sizing = { .width = CLAY_SIZING_GROW(0) }, .childAlignment = { .x = CLAY_ALIGN_X_RIGHT }, .padding = {8, 8, 8, 8 }, .childGap = 8 }, .rectangle = { .color = {180, 180, 180, 255} }}) {
CLAY({ .id = CLAY_ID("HeaderBar"), .layout = { .sizing = { .width = CLAY_SIZING_GROW(0) }, .childAlignment = { .x = CLAY_ALIGN_X_RIGHT }, .padding = {8, 8, 8, 8 }, .childGap = 8 }, .backgroundColor = {180, 180, 180, 255} }) {
RenderHeaderButton(CLAY_STRING("Header Item 1"));
RenderHeaderButton(CLAY_STRING("Header Item 2"));
RenderHeaderButton(CLAY_STRING("Header Item 3"));
}
CLAY({.id = CLAY_ID("MainContent"),
.scroll = { .vertical = true },
.layout = { .layoutDirection = CLAY_TOP_TO_BOTTOM, .padding = {16, 16, 16, 16}, .childGap = 16, .sizing = { CLAY_SIZING_GROW(0) } },
.rectangle = { .color = {200, 200, 255, 255} }
.backgroundColor = {200, 200, 255, 255},
.scroll = { .vertical = true },
})
{
CLAY({ .id = CLAY_ID("FloatingContainer"),
.layout = { .sizing = { .width = CLAY_SIZING_FIXED(300), .height = CLAY_SIZING_FIXED(300) }, .padding = { 16, 16, 16, 16 }},
.backgroundColor = { 140, 80, 200, 200 },
.floating = { .zIndex = 1, .attachment = { CLAY_ATTACH_POINT_CENTER_TOP, CLAY_ATTACH_POINT_CENTER_TOP }, .offset = {0, 0} },
.border = CLAY_BORDER_OUTSIDE({ .color = {80, 80, 80, 255}, .width = 2 }),
.rectangle = { .color = {140,80, 200, 200 }}
.border = { .width = CLAY_BORDER_OUTSIDE(2), .color = {80, 80, 80, 255} },
}) {
CLAY_TEXT(CLAY_STRING("I'm an inline floating container."), CLAY_TEXT_CONFIG({ .fontSize = 24, .textColor = {255,255,255,255} }));
}
@ -82,7 +80,7 @@ Clay_RenderCommandArray CreateLayout(void) {
CLAY_TEXT(CLAY_STRING("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt."),
CLAY_TEXT_CONFIG({ .fontId = FONT_ID_BODY_24, .fontSize = 24, .textColor = {0,0,0,255} }));
CLAY({ .id = CLAY_ID("Photos2"), .layout = { .childGap = 16, .padding = { 16, 16, 16, 16 }}, .rectangle = { .color = {180, 180, 220, 255} }}) {
CLAY({ .id = CLAY_ID("Photos2"), .layout = { .childGap = 16, .padding = { 16, 16, 16, 16 }}, .backgroundColor = {180, 180, 220, 255} }) {
CLAY({ .id = CLAY_ID("Picture4"), .layout = { .sizing = { .width = CLAY_SIZING_FIXED(120), .height = CLAY_SIZING_FIXED(120) }}, .image = { .imageData = &profilePicture, .sourceDimensions = {120, 120} }}) {}
CLAY({ .id = CLAY_ID("Picture5"), .layout = { .sizing = { .width = CLAY_SIZING_FIXED(120), .height = CLAY_SIZING_FIXED(120) }}, .image = { .imageData = &profilePicture, .sourceDimensions = {120, 120} }}) {}
CLAY({ .id = CLAY_ID("Picture6"), .layout = { .sizing = { .width = CLAY_SIZING_FIXED(120), .height = CLAY_SIZING_FIXED(120) }}, .image = { .imageData = &profilePicture, .sourceDimensions = {120, 120} }}) {}
@ -94,9 +92,9 @@ Clay_RenderCommandArray CreateLayout(void) {
CLAY_TEXT(CLAY_STRING("Suspendisse in est ante in nibh. Amet venenatis urna cursus eget nunc scelerisque viverra. Elementum sagittis vitae et leo duis ut diam quam nulla. Enim nulla aliquet porttitor lacus. Pellentesque habitant morbi tristique senectus et. Facilisi nullam vehicula ipsum a arcu cursus vitae.\nSem fringilla ut morbi tincidunt. Euismod quis viverra nibh cras pulvinar mattis nunc sed. Velit sed ullamcorper morbi tincidunt ornare massa. Varius quam quisque id diam vel quam. Nulla pellentesque dignissim enim sit amet venenatis. Enim lobortis scelerisque fermentum dui faucibus in. Pretium viverra suspendisse potenti nullam ac tortor vitae. Lectus vestibulum mattis ullamcorper velit sed. Eget mauris pharetra et ultrices neque ornare aenean euismod elementum. Habitant morbi tristique senectus et. Integer vitae justo eget magna fermentum iaculis eu. Semper quis lectus nulla at volutpat diam. Enim praesent elementum facilisis leo. Massa vitae tortor condimentum lacinia quis vel."),
CLAY_TEXT_CONFIG({ .fontSize = 24, .textColor = {0,0,0,255} }));
CLAY({ .id = CLAY_ID("Photos"), .layout = { .sizing = { .width = CLAY_SIZING_GROW(0) }, .childAlignment = { .x = CLAY_ALIGN_X_CENTER, .y = CLAY_ALIGN_Y_CENTER }, .childGap = 16, .padding = {16, 16, 16, 16} }, .rectangle = { .color = {180, 180, 220, 255} }}) {
CLAY({ .id = CLAY_ID("Photos"), .layout = { .sizing = { .width = CLAY_SIZING_GROW(0) }, .childAlignment = { .x = CLAY_ALIGN_X_CENTER, .y = CLAY_ALIGN_Y_CENTER }, .childGap = 16, .padding = {16, 16, 16, 16} }, .backgroundColor = {180, 180, 220, 255} }) {
CLAY({ .id = CLAY_ID("Picture2"), .layout = { .sizing = { .width = CLAY_SIZING_FIXED(120), .height = CLAY_SIZING_FIXED(120) }}, .image = { .imageData = &profilePicture, .sourceDimensions = {120, 120} }}) {}
CLAY({ .id = CLAY_ID("Picture1"), .layout = { .childAlignment = { .x = CLAY_ALIGN_X_CENTER }, .layoutDirection = CLAY_TOP_TO_BOTTOM, .padding = {8, 8, 8, 8} }, .rectangle = { .color = {170, 170, 220, 255} }}) {
CLAY({ .id = CLAY_ID("Picture1"), .layout = { .childAlignment = { .x = CLAY_ALIGN_X_CENTER }, .layoutDirection = CLAY_TOP_TO_BOTTOM, .padding = {8, 8, 8, 8} }, .backgroundColor = {170, 170, 220, 255} }) {
CLAY({ .id = CLAY_ID("ProfilePicture2"), .layout = { .sizing = { .width = CLAY_SIZING_FIXED(60), .height = CLAY_SIZING_FIXED(60) }}, .image = { .imageData = &profilePicture, .sourceDimensions = {60, 60} }}) {}
CLAY_TEXT(CLAY_STRING("Image caption below"), CLAY_TEXT_CONFIG({ .fontSize = 24, .textColor = {0,0,0,255} }));
}
@ -111,11 +109,11 @@ Clay_RenderCommandArray CreateLayout(void) {
CLAY({ .id = CLAY_ID("Blob4Floating2"), .floating = { .zIndex = 1, .parentId = Clay_GetElementId(CLAY_STRING("SidebarBlob4")).id } }) {
CLAY({ .id = CLAY_ID("ScrollContainer"), .layout = { .sizing = { .height = CLAY_SIZING_FIXED(200) }, .childGap = 2 }, .scroll = { .vertical = true } }) {
CLAY({ .id = CLAY_ID("FloatingContainer2"), .floating = { .zIndex = 1 } }) {
CLAY({ .id = CLAY_ID("FloatingContainerInner"), .layout = { .sizing = { .width = CLAY_SIZING_FIXED(300), .height = CLAY_SIZING_FIXED(300) }, .padding = {16, 16, 16, 16} }, .rectangle = { .color = {140,80, 200, 200} } }) {
CLAY({ .id = CLAY_ID("FloatingContainerInner"), .layout = { .sizing = { .width = CLAY_SIZING_FIXED(300), .height = CLAY_SIZING_FIXED(300) }, .padding = {16, 16, 16, 16} }, .backgroundColor = {140,80, 200, 200} }) {
CLAY_TEXT(CLAY_STRING("I'm an inline floating container."), CLAY_TEXT_CONFIG({ .fontSize = 24, .textColor = {255,255,255,255} }));
}
}
CLAY({ .id = CLAY_ID("ScrollContainerInner"), .layout = { .layoutDirection = CLAY_TOP_TO_BOTTOM }, .rectangle = { .color = {160, 160, 160, 255} } }) {
CLAY({ .id = CLAY_ID("ScrollContainerInner"), .layout = { .layoutDirection = CLAY_TOP_TO_BOTTOM }, .backgroundColor = {160, 160, 160, 255} }) {
for (int i = 0; i < 100; i++) {
RenderDropdownTextItem(i);
}
@ -134,8 +132,8 @@ Clay_RenderCommandArray CreateLayout(void) {
}) {
CLAY({ .id = CLAY_ID("ScrollBarButton"),
.layout = { .sizing = {CLAY_SIZING_FIXED(12), CLAY_SIZING_FIXED((scrollData.scrollContainerDimensions.height / scrollData.contentDimensions.height) * scrollData.scrollContainerDimensions.height) }},
.rectangle = { .color = Clay_PointerOver(Clay__HashString(CLAY_STRING("ScrollBar"), 0, 0)) ? (Clay_Color){100, 100, 140, 150} : (Clay_Color){120, 120, 160, 150} },
.shared = { .cornerRadius = CLAY_CORNER_RADIUS(6) }
.backgroundColor = Clay_PointerOver(Clay__HashString(CLAY_STRING("ScrollBar"), 0, 0)) ? (Clay_Color){100, 100, 140, 150} : (Clay_Color){120, 120, 160, 150} ,
.cornerRadius = CLAY_CORNER_RADIUS(6)
}) {}
}
}

View File

@ -7,13 +7,11 @@ Clay_Color COLOR_WHITE = { 255, 255, 255, 255};
void RenderHeaderButton(Clay_String text) {
CLAY({
.layout = { .padding = { 16, 16, 8, 8 }},
.rectangle = {
.color = { 140, 140, 140, 255 },
},
.shared = { .cornerRadius = CLAY_CORNER_RADIUS(5) }
.backgroundColor = { 140, 140, 140, 255 },
.cornerRadius = CLAY_CORNER_RADIUS(5)
}) {
CLAY_TEXT(text, CLAY_TEXT_CONFIG({
.fontId = FONT_ID_BODY_16,
.font = FONT_ID_BODY_16,
.fontSize = 16,
.textColor = { 255, 255, 255, 255 }
}));
@ -101,13 +99,11 @@ Clay_RenderCommandArray ClayVideoDemo_CreateLayout(ClayVideoDemo_Data *data) {
.height = CLAY_SIZING_GROW(0)
};
Clay_RectangleElementConfig contentBackgroundConfig = {
.color = { 90, 90, 90, 255 },
};
Clay_Color contentBackgroundColor = { 90, 90, 90, 255 };
// Build UI here
CLAY({ .id = CLAY_ID("OuterContainer"),
.rectangle = { .color = { 43, 41, 51, 255 } },
.backgroundColor = {43, 41, 51, 255 },
.layout = {
.layoutDirection = CLAY_TOP_TO_BOTTOM,
.sizing = layoutExpand,
@ -117,7 +113,6 @@ Clay_RenderCommandArray ClayVideoDemo_CreateLayout(ClayVideoDemo_Data *data) {
}) {
// Child elements go inside braces
CLAY({ .id = CLAY_ID("HeaderBar"),
.rectangle = contentBackgroundConfig,
.layout = {
.sizing = {
.height = CLAY_SIZING_FIXED(60),
@ -129,15 +124,14 @@ Clay_RenderCommandArray ClayVideoDemo_CreateLayout(ClayVideoDemo_Data *data) {
.y = CLAY_ALIGN_Y_CENTER
}
},
.shared = { .cornerRadius = CLAY_CORNER_RADIUS(8) }
.backgroundColor = contentBackgroundColor,
.cornerRadius = CLAY_CORNER_RADIUS(8)
}) {
// Header buttons go here
CLAY({ .id = CLAY_ID("FileButton"),
.layout = { .padding = { 16, 16, 8, 8 }},
.rectangle ={
.color = { 140, 140, 140, 255 },
},
.shared = { .cornerRadius = CLAY_CORNER_RADIUS(5) }
.backgroundColor = {140, 140, 140, 255 },
.cornerRadius = CLAY_CORNER_RADIUS(5)
}) {
CLAY_TEXT(CLAY_STRING("File"), CLAY_TEXT_CONFIG({
.fontId = FONT_ID_BODY_16,
@ -168,10 +162,8 @@ Clay_RenderCommandArray ClayVideoDemo_CreateLayout(ClayVideoDemo_Data *data) {
.width = CLAY_SIZING_FIXED(200)
},
},
.rectangle ={
.color = { 40, 40, 40, 255 },
},
.shared = { .cornerRadius = CLAY_CORNER_RADIUS(8) }
.backgroundColor = {40, 40, 40, 255 },
.cornerRadius = CLAY_CORNER_RADIUS(8)
}) {
// Render dropdown items here
RenderDropdownMenuItem(CLAY_STRING("New"));
@ -194,7 +186,7 @@ Clay_RenderCommandArray ClayVideoDemo_CreateLayout(ClayVideoDemo_Data *data) {
}) {
CLAY({
.id = CLAY_ID("Sidebar"),
.rectangle = contentBackgroundConfig,
.backgroundColor = contentBackgroundColor,
.layout = {
.layoutDirection = CLAY_TOP_TO_BOTTOM,
.padding = CLAY_PADDING_ALL(16),
@ -215,10 +207,8 @@ Clay_RenderCommandArray ClayVideoDemo_CreateLayout(ClayVideoDemo_Data *data) {
if (i == data->selectedDocumentIndex) {
CLAY({
.layout = sidebarButtonLayout,
.rectangle = {
.color = { 120, 120, 120, 255 },
},
.shared = { .cornerRadius = CLAY_CORNER_RADIUS(8) }
.backgroundColor = {120, 120, 120, 255 },
.cornerRadius = CLAY_CORNER_RADIUS(8)
}) {
CLAY_TEXT(document.title, CLAY_TEXT_CONFIG({
.fontId = FONT_ID_BODY_16,
@ -230,12 +220,8 @@ Clay_RenderCommandArray ClayVideoDemo_CreateLayout(ClayVideoDemo_Data *data) {
SidebarClickData *clickData = (SidebarClickData *)(data->frameArena.memory + data->frameArena.offset);
*clickData = (SidebarClickData) { .requestedDocumentIndex = i, .selectedDocumentIndex = &data->selectedDocumentIndex };
data->frameArena.offset += sizeof(SidebarClickData);
CLAY({ .layout = sidebarButtonLayout }) {
CLAY({ .layout = sidebarButtonLayout, .backgroundColor = (Clay_Color) { 120, 120, 120, Clay_Hovered() ? 120 : 0 }, .cornerRadius = CLAY_CORNER_RADIUS(8) }) {
Clay_OnHover(HandleSidebarInteraction, (intptr_t)clickData);
if (Clay_Hovered()) {
Clay_CurrentConfigRectangle()->color = (Clay_Color) { 120, 120, 120, 120 };
Clay_CurrentConfigShared()->cornerRadius = CLAY_CORNER_RADIUS(8);
}
CLAY_TEXT(document.title, CLAY_TEXT_CONFIG({
.fontId = FONT_ID_BODY_16,
.fontSize = 20,
@ -247,7 +233,7 @@ Clay_RenderCommandArray ClayVideoDemo_CreateLayout(ClayVideoDemo_Data *data) {
}
CLAY({ .id = CLAY_ID("MainContent"),
.rectangle = contentBackgroundConfig,
.backgroundColor = contentBackgroundColor,
.scroll = { .vertical = true },
.layout = {
.layoutDirection = CLAY_TOP_TO_BOTTOM,

View File

@ -44,8 +44,8 @@ static void Clay_SDL2_Render(SDL_Renderer *renderer, Clay_RenderCommandArray ren
switch (renderCommand->commandType)
{
case CLAY_RENDER_COMMAND_TYPE_RECTANGLE: {
Clay_RectangleElementConfig *config = renderCommand->config.rectangleElementConfig;
Clay_Color color = config->color;
Clay_RectangleRenderData *config = &renderCommand->renderData.rectangle;
Clay_Color color = config->backgroundColor;
SDL_SetRenderDrawColor(renderer, color.r, color.g, color.b, color.a);
SDL_FRect rect = (SDL_FRect) {
.x = boundingBox.x,
@ -57,10 +57,9 @@ static void Clay_SDL2_Render(SDL_Renderer *renderer, Clay_RenderCommandArray ren
break;
}
case CLAY_RENDER_COMMAND_TYPE_TEXT: {
Clay_TextElementConfig *config = renderCommand->config.textElementConfig;
Clay_StringSlice text = renderCommand->textOrSharedConfig.text;
char *cloned = (char *)calloc(text.length + 1, 1);
memcpy(cloned, text.chars, text.length);
Clay_TextRenderData *config = &renderCommand->renderData.text;
char *cloned = (char *)calloc(config->stringContents.length + 1, 1);
memcpy(cloned, config->stringContents.chars, config->stringContents.length);
TTF_Font* font = fonts[config->fontId].font;
SDL_Surface *surface = TTF_RenderUTF8_Blended(font, cloned, (SDL_Color) {
.r = (Uint8)config->textColor.r,
@ -98,9 +97,9 @@ static void Clay_SDL2_Render(SDL_Renderer *renderer, Clay_RenderCommandArray ren
break;
}
case CLAY_RENDER_COMMAND_TYPE_IMAGE: {
SDL_Surface *image = (SDL_Surface *)renderCommand->config.imageElementConfig->imageData;
Clay_ImageRenderData *config = &renderCommand->renderData.image;
SDL_Texture *texture = SDL_CreateTextureFromSurface(renderer, image);
SDL_Texture *texture = SDL_CreateTextureFromSurface(renderer, config->imageData);
SDL_Rect destination = (SDL_Rect){
.x = boundingBox.x,
@ -113,36 +112,35 @@ static void Clay_SDL2_Render(SDL_Renderer *renderer, Clay_RenderCommandArray ren
break;
}
case CLAY_RENDER_COMMAND_TYPE_BORDER: {
Clay_BorderElementConfig *config = renderCommand->config.borderElementConfig;
Clay_CornerRadius cornerRadius = renderCommand->textOrSharedConfig.sharedConfig->cornerRadius;
Clay_BorderRenderData *config = &renderCommand->renderData.border;
if (config->left.width > 0) {
SDL_SetRenderDrawColor(renderer, CLAY_COLOR_TO_SDL_COLOR_ARGS(config->left.color));
SDL_FRect rect = { boundingBox.x, boundingBox.y + cornerRadius.topLeft, config->left.width, boundingBox.height - cornerRadius.topLeft - cornerRadius.bottomLeft };
if (config->width.left > 0) {
SDL_SetRenderDrawColor(renderer, CLAY_COLOR_TO_SDL_COLOR_ARGS(config->color));
SDL_FRect rect = { boundingBox.x, boundingBox.y + config->cornerRadius.topLeft, config->width.left, boundingBox.height - config->cornerRadius.topLeft - config->cornerRadius.bottomLeft };
SDL_RenderFillRectF(renderer, &rect);
}
if (config->right.width > 0) {
SDL_SetRenderDrawColor(renderer, CLAY_COLOR_TO_SDL_COLOR_ARGS(config->right.color));
SDL_FRect rect = { boundingBox.x + boundingBox.width - config->right.width, boundingBox.y + cornerRadius.topRight, config->right.width, boundingBox.height - cornerRadius.topRight - cornerRadius.bottomRight };
if (config->width.right > 0) {
SDL_SetRenderDrawColor(renderer, CLAY_COLOR_TO_SDL_COLOR_ARGS(config->color));
SDL_FRect rect = { boundingBox.x + boundingBox.width - config->width.right, boundingBox.y + config->cornerRadius.topRight, config->width.right, boundingBox.height - config->cornerRadius.topRight - config->cornerRadius.bottomRight };
SDL_RenderFillRectF(renderer, &rect);
}
if (config->right.width > 0) {
SDL_SetRenderDrawColor(renderer, CLAY_COLOR_TO_SDL_COLOR_ARGS(config->right.color));
SDL_FRect rect = { boundingBox.x + boundingBox.width - config->right.width, boundingBox.y + cornerRadius.topRight, config->right.width, boundingBox.height - cornerRadius.topRight - cornerRadius.bottomRight };
if (config->width.right > 0) {
SDL_SetRenderDrawColor(renderer, CLAY_COLOR_TO_SDL_COLOR_ARGS(config->color));
SDL_FRect rect = { boundingBox.x + boundingBox.width - config->width.right, boundingBox.y + config->cornerRadius.topRight, config->width.right, boundingBox.height - config->cornerRadius.topRight - config->cornerRadius.bottomRight };
SDL_RenderFillRectF(renderer, &rect);
}
if (config->top.width > 0) {
SDL_SetRenderDrawColor(renderer, CLAY_COLOR_TO_SDL_COLOR_ARGS(config->right.color));
SDL_FRect rect = { boundingBox.x + cornerRadius.topLeft, boundingBox.y, boundingBox.width - cornerRadius.topLeft - cornerRadius.topRight, config->top.width };
if (config->width.top > 0) {
SDL_SetRenderDrawColor(renderer, CLAY_COLOR_TO_SDL_COLOR_ARGS(config->color));
SDL_FRect rect = { boundingBox.x + config->cornerRadius.topLeft, boundingBox.y, boundingBox.width - config->cornerRadius.topLeft - config->cornerRadius.topRight, config->width.top };
SDL_RenderFillRectF(renderer, &rect);
}
if (config->bottom.width > 0) {
SDL_SetRenderDrawColor(renderer, CLAY_COLOR_TO_SDL_COLOR_ARGS(config->bottom.color));
SDL_FRect rect = { boundingBox.x + cornerRadius.bottomLeft, boundingBox.y + boundingBox.height - config->bottom.width, boundingBox.width - cornerRadius.bottomLeft - cornerRadius.bottomRight, config->bottom.width };
if (config->width.bottom > 0) {
SDL_SetRenderDrawColor(renderer, CLAY_COLOR_TO_SDL_COLOR_ARGS(config->color));
SDL_FRect rect = { boundingBox.x + config->cornerRadius.bottomLeft, boundingBox.y + boundingBox.height - config->width.bottom, boundingBox.width - config->cornerRadius.bottomLeft - config->cornerRadius.bottomRight, config->width.bottom };
SDL_RenderFillRectF(renderer, &rect);
}

View File

@ -146,24 +146,20 @@ static void SDL_RenderClayCommands(SDL_Renderer *renderer, Clay_RenderCommandArr
switch (rcmd->commandType) {
case CLAY_RENDER_COMMAND_TYPE_RECTANGLE: {
const Clay_RectangleElementConfig *config = rcmd->config.rectangleElementConfig;
Clay_CornerRadius cornerRadius = rcmd->textOrSharedConfig.sharedConfig->cornerRadius;
const Clay_Color color = config->color;
SDL_SetRenderDrawColor(renderer, color.r, color.g, color.b, color.a);
if (cornerRadius.topLeft > 0) {
SDL_RenderFillRoundedRect(renderer, rect, cornerRadius.topLeft, color);
Clay_RectangleRenderData *config = &rcmd->renderData.rectangle;
SDL_SetRenderDrawColor(renderer, config->backgroundColor.r, config->backgroundColor.g, config->backgroundColor.b, config->backgroundColor.a);
if (config->cornerRadius.topLeft > 0) {
SDL_RenderFillRoundedRect(renderer, rect, config->cornerRadius.topLeft, config->backgroundColor);
} else {
SDL_RenderFillRect(renderer, &rect);
}
} break;
case CLAY_RENDER_COMMAND_TYPE_TEXT: {
const Clay_TextElementConfig *config = rcmd->config.textElementConfig;
const Clay_StringSlice *text = &rcmd->textOrSharedConfig.text;
Clay_TextRenderData *config = &rcmd->renderData.text;
const SDL_Color color = { config->textColor.r, config->textColor.g, config->textColor.b, config->textColor.a };
TTF_Font *font = gFonts[config->fontId];
SDL_Surface *surface = TTF_RenderText_Blended(font, text->chars, text->length, color);
SDL_Surface *surface = TTF_RenderText_Blended(font, config->stringContents.chars, config->stringContents.length, color);
SDL_Texture *texture = SDL_CreateTextureFromSurface(renderer, surface);
SDL_RenderTexture(renderer, texture, NULL, &rect);
@ -171,69 +167,68 @@ static void SDL_RenderClayCommands(SDL_Renderer *renderer, Clay_RenderCommandArr
SDL_DestroyTexture(texture);
} break;
case CLAY_RENDER_COMMAND_TYPE_BORDER: {
const Clay_BorderElementConfig *config = rcmd->config.borderElementConfig;
Clay_CornerRadius cornerRadius = rcmd->textOrSharedConfig.sharedConfig->cornerRadius;
Clay_BorderRenderData *config = &rcmd->renderData.border;
const float minRadius = SDL_min(rect.w, rect.h) / 2.0f;
const Clay_CornerRadius clampedRadii = {
.topLeft = SDL_min(cornerRadius.topLeft, minRadius),
.topRight = SDL_min(cornerRadius.topRight, minRadius),
.bottomLeft = SDL_min(cornerRadius.bottomLeft, minRadius),
.bottomRight = SDL_min(cornerRadius.bottomRight, minRadius)
.topLeft = SDL_min(config->cornerRadius.topLeft, minRadius),
.topRight = SDL_min(config->cornerRadius.topRight, minRadius),
.bottomLeft = SDL_min(config->cornerRadius.bottomLeft, minRadius),
.bottomRight = SDL_min(config->cornerRadius.bottomRight, minRadius)
};
//edges
SDL_SetRenderDrawColor(renderer, config->left.color.r, config->left.color.g, config->left.color.b, config->left.color.a);
if (config->left.width > 0) {
SDL_SetRenderDrawColor(renderer, config->color.r, config->color.g, config->color.b, config->color.a);
if (config->width.left > 0) {
const float starting_y = rect.y + clampedRadii.topLeft;
const float length = rect.h - clampedRadii.topLeft - clampedRadii.bottomLeft;
SDL_FRect line = { rect.x, starting_y, config->left.width, length };
SDL_FRect line = { rect.x, starting_y, config->width.left, length };
SDL_RenderFillRect(renderer, &line);
}
if (config->right.width > 0) {
const float starting_x = rect.x + rect.w - (float)config->right.width;
if (config->width.right > 0) {
const float starting_x = rect.x + rect.w - (float)config->width.right;
const float starting_y = rect.y + clampedRadii.topRight;
const float length = rect.h - clampedRadii.topRight - clampedRadii.bottomRight;
SDL_FRect line = { starting_x, starting_y, config->right.width, length };
SDL_FRect line = { starting_x, starting_y, config->width.right, length };
SDL_RenderFillRect(renderer, &line);
}
if (config->top.width > 0) {
if (config->width.top > 0) {
const float starting_x = rect.x + clampedRadii.topLeft;
const float length = rect.w - clampedRadii.topLeft - clampedRadii.topRight;
SDL_FRect line = { starting_x, rect.y, length, config->top.width };
SDL_FRect line = { starting_x, rect.y, length, config->width.top };
SDL_RenderFillRect(renderer, &line);
}
if (config->bottom.width > 0) {
if (config->width.bottom > 0) {
const float starting_x = rect.x + clampedRadii.bottomLeft;
const float starting_y = rect.y + rect.h - (float)config->bottom.width;
const float starting_y = rect.y + rect.h - (float)config->width.bottom;
const float length = rect.w - clampedRadii.bottomLeft - clampedRadii.bottomRight;
SDL_FRect line = { starting_x, starting_y, length, config->bottom.width };
SDL_SetRenderDrawColor(renderer, config->bottom.color.r, config->bottom.color.g, config->bottom.color.b, config->bottom.color.a);
SDL_FRect line = { starting_x, starting_y, length, config->width.bottom };
SDL_SetRenderDrawColor(renderer, config->color.r, config->color.g, config->color.b, config->color.a);
SDL_RenderFillRect(renderer, &line);
}
//corners
if (cornerRadius.topLeft > 0) {
if (config->cornerRadius.topLeft > 0) {
const float centerX = rect.x + clampedRadii.topLeft -1;
const float centerY = rect.y + clampedRadii.topLeft;
SDL_RenderArc(renderer, (SDL_FPoint){centerX, centerY}, clampedRadii.topLeft,
180.0f, 270.0f, config->top.width, config->top.color);
180.0f, 270.0f, config->width.top, config->color);
}
if (cornerRadius.topRight > 0) {
if (config->cornerRadius.topRight > 0) {
const float centerX = rect.x + rect.w - clampedRadii.topRight -1;
const float centerY = rect.y + clampedRadii.topRight;
SDL_RenderArc(renderer, (SDL_FPoint){centerX, centerY}, clampedRadii.topRight,
270.0f, 360.0f, config->top.width, config->top.color);
270.0f, 360.0f, config->width.top, config->color);
}
if (cornerRadius.bottomLeft > 0) {
if (config->cornerRadius.bottomLeft > 0) {
const float centerX = rect.x + clampedRadii.bottomLeft -1;
const float centerY = rect.y + rect.h - clampedRadii.bottomLeft -1;
SDL_RenderArc(renderer, (SDL_FPoint){centerX, centerY}, clampedRadii.bottomLeft,
90.0f, 180.0f, config->bottom.width, config->bottom.color);
90.0f, 180.0f, config->width.bottom, config->color);
}
if (cornerRadius.bottomRight > 0) {
if (config->cornerRadius.bottomRight > 0) {
const float centerX = rect.x + rect.w - clampedRadii.bottomRight -1; //TODO: why need to -1 in all calculations???
const float centerY = rect.y + rect.h - clampedRadii.bottomRight -1;
SDL_RenderArc(renderer, (SDL_FPoint){centerX, centerY}, clampedRadii.bottomRight,
0.0f, 90.0f, config->bottom.width, config->bottom.color);
0.0f, 90.0f, config->width.bottom, config->color);
}
} break;

View File

@ -26,14 +26,6 @@
#include <string.h>
#include <math.h>
// TODO: Regarding image support, currently this renderer only
// supports PNG images, this is due to cairo having just PNG as it's
// main file format. We maybe should introduce stb_image to load them
// as bitmaps and feed cairo that way.
#define CLAY_EXTEND_CONFIG_IMAGE Clay_String path; // Filesystem path
// TODO: We should use the given `uint16_t fontId` instead of doing this.
#define CLAY_EXTEND_CONFIG_TEXT Clay_String fontFamily; // Font family
#define CLAY_IMPLEMENTATION
#include "../../clay.h"
@ -50,7 +42,7 @@ void Clay_Cairo_Initialize(cairo_t *cairo);
// Render the command queue to the `cairo_t*` instance you called
// `Clay_Cairo_Initialize` on.
void Clay_Cairo_Render(Clay_RenderCommandArray commands);
void Clay_Cairo_Render(Clay_RenderCommandArray commands, char** fonts);
////////////////////////////////
@ -88,6 +80,7 @@ static inline Clay_Dimensions Clay_Cairo_MeasureText(Clay_StringSlice str, Clay_
// once. Cairo does not factor in whitespaces when computing text
// extents, this edge-case serves as a short-circuit to introduce
// (somewhat) sensible values into Clay.
char** fonts = (char**)userData;
if(str.length == 1 && str.chars[0] == ' ') {
cairo_text_extents_t te;
cairo_text_extents(Clay__Cairo, " ", &te);
@ -104,7 +97,7 @@ static inline Clay_Dimensions Clay_Cairo_MeasureText(Clay_StringSlice str, Clay_
// Ensure string is null-terminated for Cairo
Clay_String toTerminate = (Clay_String){ str.length, str.chars };
char *text = Clay_Cairo__NullTerminate(&toTerminate);
char *font_family = Clay_Cairo__NullTerminate(&config->fontFamily);
char *font_family = fonts[config->fontId];
// Save and reset the Cairo context to avoid unwanted transformations
cairo_save(Clay__Cairo);
@ -120,7 +113,6 @@ static inline Clay_Dimensions Clay_Cairo_MeasureText(Clay_StringSlice str, Clay_
fprintf(stderr, "Failed to get scaled font\n");
cairo_restore(Clay__Cairo);
free(text);
free(font_family);
return (Clay_Dimensions){0, 0};
}
@ -134,7 +126,6 @@ static inline Clay_Dimensions Clay_Cairo_MeasureText(Clay_StringSlice str, Clay_
fprintf(stderr, "Failed to generate glyphs: %s\n", cairo_status_to_string(status));
cairo_restore(Clay__Cairo);
free(text);
free(font_family);
return (Clay_Dimensions){0, 0};
}
@ -150,7 +141,6 @@ static inline Clay_Dimensions Clay_Cairo_MeasureText(Clay_StringSlice str, Clay_
// Free temporary strings
free(text);
free(font_family);
// Return dimensions
return (Clay_Dimensions){
@ -192,36 +182,34 @@ void Clay_Cairo__Blit_Surface(cairo_surface_t *src_surface, cairo_surface_t *des
cairo_destroy(cr);
}
void Clay_Cairo_Render(Clay_RenderCommandArray commands) {
void Clay_Cairo_Render(Clay_RenderCommandArray commands, char** fonts) {
cairo_t *cr = Clay__Cairo;
for(size_t i = 0; i < commands.length; i++) {
Clay_RenderCommand *command = Clay_RenderCommandArray_Get(&commands, i);
Clay_CornerRadius cornerRadius = command->textOrSharedConfig.sharedConfig->cornerRadius;
switch(command->commandType) {
case CLAY_RENDER_COMMAND_TYPE_RECTANGLE: {
Clay_RectangleElementConfig *config = command->config.rectangleElementConfig;
Clay_Color color = config->color;
Clay_RectangleRenderData *config = &command->renderData.rectangle;
Clay_BoundingBox bb = command->boundingBox;
cairo_set_source_rgba(cr, CLAY_TO_CAIRO(color));
cairo_set_source_rgba(cr, CLAY_TO_CAIRO(config->backgroundColor));
cairo_new_sub_path(cr);
cairo_arc(cr, bb.x + cornerRadius.topLeft,
bb.y + cornerRadius.topLeft,
cornerRadius.topLeft,
cairo_arc(cr, bb.x + config->cornerRadius.topLeft,
bb.y + config->cornerRadius.topLeft,
config->cornerRadius.topLeft,
M_PI, 3 * M_PI / 2); // 180° to 270°
cairo_arc(cr, bb.x + bb.width - cornerRadius.topRight,
bb.y + cornerRadius.topRight,
cornerRadius.topRight,
cairo_arc(cr, bb.x + bb.width - config->cornerRadius.topRight,
bb.y + config->cornerRadius.topRight,
config->cornerRadius.topRight,
3 * M_PI / 2, 2 * M_PI); // 270° to 360°
cairo_arc(cr, bb.x + bb.width - cornerRadius.bottomRight,
bb.y + bb.height - cornerRadius.bottomRight,
cornerRadius.bottomRight,
cairo_arc(cr, bb.x + bb.width - config->cornerRadius.bottomRight,
bb.y + bb.height - config->cornerRadius.bottomRight,
config->cornerRadius.bottomRight,
0, M_PI / 2); // 0° to 90°
cairo_arc(cr, bb.x + cornerRadius.bottomLeft,
bb.y + bb.height - cornerRadius.bottomLeft,
cornerRadius.bottomLeft,
cairo_arc(cr, bb.x + config->cornerRadius.bottomLeft,
bb.y + bb.height - config->cornerRadius.bottomLeft,
config->cornerRadius.bottomLeft,
M_PI / 2, M_PI); // 90° to 180°
cairo_close_path(cr);
@ -231,15 +219,16 @@ void Clay_Cairo_Render(Clay_RenderCommandArray commands) {
case CLAY_RENDER_COMMAND_TYPE_TEXT: {
// Cairo expects null terminated strings, we need to clone
// to temporarily introduce one.
Clay_String toTerminate = (Clay_String){ command->textOrSharedConfig.text.length, command->textOrSharedConfig.text.chars };
Clay_TextRenderData *config = &command->renderData.text;
Clay_String toTerminate = (Clay_String){ config->stringContents.length, config->stringContents.chars };
char *text = Clay_Cairo__NullTerminate(&toTerminate);
char *font_family = Clay_Cairo__NullTerminate(&command->config.textElementConfig->fontFamily);
char *font_family = fonts[config->fontId];
Clay_BoundingBox bb = command->boundingBox;
Clay_Color color = command->config.textElementConfig->textColor;
Clay_Color color = config->textColor;
cairo_select_font_face(Clay__Cairo, font_family, CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
cairo_set_font_size(cr, command->config.textElementConfig->fontSize);
cairo_set_font_size(cr, config->fontSize);
cairo_move_to(cr, bb.x, bb.y + bb.height);
@ -248,22 +237,21 @@ void Clay_Cairo_Render(Clay_RenderCommandArray commands) {
cairo_close_path(cr);
free(text);
free(font_family);
break;
}
case CLAY_RENDER_COMMAND_TYPE_BORDER: {
Clay_BorderElementConfig *config = command->config.borderElementConfig;
Clay_BorderRenderData *config = &command->renderData.border;
Clay_BoundingBox bb = command->boundingBox;
double top_left_radius = cornerRadius.topLeft / 2.0;
double top_right_radius = cornerRadius.topRight / 2.0;
double bottom_right_radius = cornerRadius.bottomRight / 2.0;
double bottom_left_radius = cornerRadius.bottomLeft / 2.0;
double top_left_radius = config->cornerRadius.topLeft / 2.0;
double top_right_radius = config->cornerRadius.topRight / 2.0;
double bottom_right_radius = config->cornerRadius.bottomRight / 2.0;
double bottom_left_radius = config->cornerRadius.bottomLeft / 2.0;
// Draw the top border
if (config->top.width > 0) {
cairo_set_line_width(cr, config->top.width);
cairo_set_source_rgba(cr, CLAY_TO_CAIRO(config->top.color));
if (config->width.top > 0) {
cairo_set_line_width(cr, config->width.top);
cairo_set_source_rgba(cr, CLAY_TO_CAIRO(config->color));
cairo_new_sub_path(cr);
@ -280,9 +268,9 @@ void Clay_Cairo_Render(Clay_RenderCommandArray commands) {
}
// Draw the right border
if (config->right.width > 0) {
cairo_set_line_width(cr, config->right.width);
cairo_set_source_rgba(cr, CLAY_TO_CAIRO(config->right.color));
if (config->width.right > 0) {
cairo_set_line_width(cr, config->width.right);
cairo_set_source_rgba(cr, CLAY_TO_CAIRO(config->color));
cairo_new_sub_path(cr);
@ -299,9 +287,9 @@ void Clay_Cairo_Render(Clay_RenderCommandArray commands) {
}
// Draw the bottom border
if (config->bottom.width > 0) {
cairo_set_line_width(cr, config->bottom.width);
cairo_set_source_rgba(cr, CLAY_TO_CAIRO(config->bottom.color));
if (config->width.bottom > 0) {
cairo_set_line_width(cr, config->width.bottom);
cairo_set_source_rgba(cr, CLAY_TO_CAIRO(config->color));
cairo_new_sub_path(cr);
@ -318,9 +306,9 @@ void Clay_Cairo_Render(Clay_RenderCommandArray commands) {
}
// Draw the left border
if (config->left.width > 0) {
cairo_set_line_width(cr, config->left.width);
cairo_set_source_rgba(cr, CLAY_TO_CAIRO(config->left.color));
if (config->width.left > 0) {
cairo_set_line_width(cr, config->width.left);
cairo_set_source_rgba(cr, CLAY_TO_CAIRO(config->color));
cairo_new_sub_path(cr);
@ -338,10 +326,10 @@ void Clay_Cairo_Render(Clay_RenderCommandArray commands) {
break;
}
case CLAY_RENDER_COMMAND_TYPE_IMAGE: {
Clay_ImageElementConfig *config = command->config.imageElementConfig;
Clay_ImageRenderData *config = &command->renderData.image;
Clay_BoundingBox bb = command->boundingBox;
char *path = Clay_Cairo__NullTerminate(&config->path);
char *path = config->imageData;
cairo_surface_t *surf = cairo_image_surface_create_from_png(path),
*origin = cairo_get_target(cr);
@ -372,7 +360,6 @@ void Clay_Cairo_Render(Clay_RenderCommandArray commands) {
// Clean up the source surface
cairo_surface_destroy(surf);
free(path);
break;
}
case CLAY_RENDER_COMMAND_TYPE_CUSTOM: {

View File

@ -138,23 +138,23 @@ void Clay_Raylib_Render(Clay_RenderCommandArray renderCommands)
{
case CLAY_RENDER_COMMAND_TYPE_TEXT: {
// Raylib uses standard C strings so isn't compatible with cheap slices, we need to clone the string to append null terminator
Clay_StringSlice text = renderCommand->textOrSharedConfig.text;
char *cloned = (char *)malloc(text.length + 1);
memcpy(cloned, text.chars, text.length);
cloned[text.length] = '\0';
Font fontToUse = Raylib_fonts[renderCommand->config.textElementConfig->fontId].font;
DrawTextEx(fontToUse, cloned, (Vector2){boundingBox.x, boundingBox.y}, (float)renderCommand->config.textElementConfig->fontSize, (float)renderCommand->config.textElementConfig->letterSpacing, CLAY_COLOR_TO_RAYLIB_COLOR(renderCommand->config.textElementConfig->textColor));
Clay_TextRenderData *textData = &renderCommand->renderData.text;
char *cloned = (char *)malloc(textData->stringContents.length + 1);
memcpy(cloned, textData->stringContents.chars, textData->stringContents.length);
cloned[textData->stringContents.length] = '\0';
Font fontToUse = Raylib_fonts[textData->fontId].font;
DrawTextEx(fontToUse, cloned, (Vector2){boundingBox.x, boundingBox.y}, (float)textData->fontSize, (float)textData->letterSpacing, CLAY_COLOR_TO_RAYLIB_COLOR(textData->textColor));
free(cloned);
break;
}
case CLAY_RENDER_COMMAND_TYPE_IMAGE: {
Texture2D imageTexture = *(Texture2D *)renderCommand->config.imageElementConfig->imageData;
Texture2D imageTexture = *(Texture2D *)renderCommand->renderData.image.imageData;
DrawTextureEx(
imageTexture,
(Vector2){boundingBox.x, boundingBox.y},
0,
boundingBox.width / (float)imageTexture.width,
WHITE);
imageTexture,
(Vector2){boundingBox.x, boundingBox.y},
0,
boundingBox.width / (float)imageTexture.width,
CLAY_COLOR_TO_RAYLIB_COLOR(renderCommand->renderData.image.backgroundColor));
break;
}
case CLAY_RENDER_COMMAND_TYPE_SCISSOR_START: {
@ -166,51 +166,50 @@ void Clay_Raylib_Render(Clay_RenderCommandArray renderCommands)
break;
}
case CLAY_RENDER_COMMAND_TYPE_RECTANGLE: {
Clay_RectangleElementConfig *config = renderCommand->config.rectangleElementConfig;
Clay_CornerRadius cornerRadius = renderCommand->textOrSharedConfig.sharedConfig->cornerRadius;
if (cornerRadius.topLeft > 0) {
float radius = (cornerRadius.topLeft * 2) / (float)((boundingBox.width > boundingBox.height) ? boundingBox.height : boundingBox.width);
DrawRectangleRounded((Rectangle) { boundingBox.x, boundingBox.y, boundingBox.width, boundingBox.height }, radius, 8, CLAY_COLOR_TO_RAYLIB_COLOR(config->color));
Clay_RectangleRenderData *config = &renderCommand->renderData.rectangle;
if (config->cornerRadius.topLeft > 0) {
float radius = (config->cornerRadius.topLeft * 2) / (float)((boundingBox.width > boundingBox.height) ? boundingBox.height : boundingBox.width);
DrawRectangleRounded((Rectangle) { boundingBox.x, boundingBox.y, boundingBox.width, boundingBox.height }, radius, 8, CLAY_COLOR_TO_RAYLIB_COLOR(config->backgroundColor));
} else {
DrawRectangle(boundingBox.x, boundingBox.y, boundingBox.width, boundingBox.height, CLAY_COLOR_TO_RAYLIB_COLOR(config->color));
DrawRectangle(boundingBox.x, boundingBox.y, boundingBox.width, boundingBox.height, CLAY_COLOR_TO_RAYLIB_COLOR(config->backgroundColor));
}
break;
}
case CLAY_RENDER_COMMAND_TYPE_BORDER: {
Clay_BorderElementConfig *config = renderCommand->config.borderElementConfig;
Clay_CornerRadius cornerRadius = renderCommand->textOrSharedConfig.sharedConfig->cornerRadius;
Clay_BorderRenderData *config = &renderCommand->renderData.border;
// Left border
if (config->left.width > 0) {
DrawRectangle((int)roundf(boundingBox.x), (int)roundf(boundingBox.y + cornerRadius.topLeft), (int)config->left.width, (int)roundf(boundingBox.height - cornerRadius.topLeft - cornerRadius.bottomLeft), CLAY_COLOR_TO_RAYLIB_COLOR(config->left.color));
if (config->width.left > 0) {
DrawRectangle((int)roundf(boundingBox.x), (int)roundf(boundingBox.y + config->cornerRadius.topLeft), (int)config->width.left, (int)roundf(boundingBox.height - config->cornerRadius.topLeft - config->cornerRadius.bottomLeft), CLAY_COLOR_TO_RAYLIB_COLOR(config->color));
}
// Right border
if (config->right.width > 0) {
DrawRectangle((int)roundf(boundingBox.x + boundingBox.width - config->right.width), (int)roundf(boundingBox.y + cornerRadius.topRight), (int)config->right.width, (int)roundf(boundingBox.height - cornerRadius.topRight - cornerRadius.bottomRight), CLAY_COLOR_TO_RAYLIB_COLOR(config->right.color));
if (config->width.right > 0) {
DrawRectangle((int)roundf(boundingBox.x + boundingBox.width - config->width.right), (int)roundf(boundingBox.y + config->cornerRadius.topRight), (int)config->width.right, (int)roundf(boundingBox.height - config->cornerRadius.topRight - config->cornerRadius.bottomRight), CLAY_COLOR_TO_RAYLIB_COLOR(config->color));
}
// Top border
if (config->top.width > 0) {
DrawRectangle((int)roundf(boundingBox.x + cornerRadius.topLeft), (int)roundf(boundingBox.y), (int)roundf(boundingBox.width - cornerRadius.topLeft - cornerRadius.topRight), (int)config->top.width, CLAY_COLOR_TO_RAYLIB_COLOR(config->top.color));
if (config->width.top > 0) {
DrawRectangle((int)roundf(boundingBox.x + config->cornerRadius.topLeft), (int)roundf(boundingBox.y), (int)roundf(boundingBox.width - config->cornerRadius.topLeft - config->cornerRadius.topRight), (int)config->width.top, CLAY_COLOR_TO_RAYLIB_COLOR(config->color));
}
// Bottom border
if (config->bottom.width > 0) {
DrawRectangle((int)roundf(boundingBox.x + cornerRadius.bottomLeft), (int)roundf(boundingBox.y + boundingBox.height - config->bottom.width), (int)roundf(boundingBox.width - cornerRadius.bottomLeft - cornerRadius.bottomRight), (int)config->bottom.width, CLAY_COLOR_TO_RAYLIB_COLOR(config->bottom.color));
if (config->width.bottom > 0) {
DrawRectangle((int)roundf(boundingBox.x + config->cornerRadius.bottomLeft), (int)roundf(boundingBox.y + boundingBox.height - config->width.bottom), (int)roundf(boundingBox.width - config->cornerRadius.bottomLeft - config->cornerRadius.bottomRight), (int)config->width.bottom, CLAY_COLOR_TO_RAYLIB_COLOR(config->color));
}
if (cornerRadius.topLeft > 0) {
DrawRing((Vector2) { roundf(boundingBox.x + cornerRadius.topLeft), roundf(boundingBox.y + cornerRadius.topLeft) }, roundf(cornerRadius.topLeft - config->top.width), cornerRadius.topLeft, 180, 270, 10, CLAY_COLOR_TO_RAYLIB_COLOR(config->top.color));
if (config->cornerRadius.topLeft > 0) {
DrawRing((Vector2) { roundf(boundingBox.x + config->cornerRadius.topLeft), roundf(boundingBox.y + config->cornerRadius.topLeft) }, roundf(config->cornerRadius.topLeft - config->width.top), config->cornerRadius.topLeft, 180, 270, 10, CLAY_COLOR_TO_RAYLIB_COLOR(config->color));
}
if (cornerRadius.topRight > 0) {
DrawRing((Vector2) { roundf(boundingBox.x + boundingBox.width - cornerRadius.topRight), roundf(boundingBox.y + cornerRadius.topRight) }, roundf(cornerRadius.topRight - config->top.width), cornerRadius.topRight, 270, 360, 10, CLAY_COLOR_TO_RAYLIB_COLOR(config->top.color));
if (config->cornerRadius.topRight > 0) {
DrawRing((Vector2) { roundf(boundingBox.x + boundingBox.width - config->cornerRadius.topRight), roundf(boundingBox.y + config->cornerRadius.topRight) }, roundf(config->cornerRadius.topRight - config->width.top), config->cornerRadius.topRight, 270, 360, 10, CLAY_COLOR_TO_RAYLIB_COLOR(config->color));
}
if (cornerRadius.bottomLeft > 0) {
DrawRing((Vector2) { roundf(boundingBox.x + cornerRadius.bottomLeft), roundf(boundingBox.y + boundingBox.height - cornerRadius.bottomLeft) }, roundf(cornerRadius.bottomLeft - config->top.width), cornerRadius.bottomLeft, 90, 180, 10, CLAY_COLOR_TO_RAYLIB_COLOR(config->bottom.color));
if (config->cornerRadius.bottomLeft > 0) {
DrawRing((Vector2) { roundf(boundingBox.x + config->cornerRadius.bottomLeft), roundf(boundingBox.y + boundingBox.height - config->cornerRadius.bottomLeft) }, roundf(config->cornerRadius.bottomLeft - config->width.top), config->cornerRadius.bottomLeft, 90, 180, 10, CLAY_COLOR_TO_RAYLIB_COLOR(config->color));
}
if (cornerRadius.bottomRight > 0) {
DrawRing((Vector2) { roundf(boundingBox.x + boundingBox.width - cornerRadius.bottomRight), roundf(boundingBox.y + boundingBox.height - cornerRadius.bottomRight) }, roundf(cornerRadius.bottomRight - config->bottom.width), cornerRadius.bottomRight, 0.1, 90, 10, CLAY_COLOR_TO_RAYLIB_COLOR(config->bottom.color));
if (config->cornerRadius.bottomRight > 0) {
DrawRing((Vector2) { roundf(boundingBox.x + boundingBox.width - config->cornerRadius.bottomRight), roundf(boundingBox.y + boundingBox.height - config->cornerRadius.bottomRight) }, roundf(config->cornerRadius.bottomRight - config->width.bottom), config->cornerRadius.bottomRight, 0.1, 90, 10, CLAY_COLOR_TO_RAYLIB_COLOR(config->color));
}
break;
}
case CLAY_RENDER_COMMAND_TYPE_CUSTOM: {
CustomLayoutElement *customElement = (CustomLayoutElement *)renderCommand->config.customElementConfig->customData;
Clay_CustomRenderData *config = &renderCommand->renderData.custom;
CustomLayoutElement *customElement = (CustomLayoutElement *)config->customData;
if (!customElement) continue;
switch (customElement->type) {
case CUSTOM_LAYOUT_ELEMENT_TYPE_3D_MODEL: {