diff --git a/CMakeLists.txt b/CMakeLists.txt index ecb29d7..29fbfcd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,6 +23,7 @@ if(CLAY_INCLUDE_ALL_EXAMPLES OR CLAY_INCLUDE_DEMOS) if(NOT MSVC) add_subdirectory("examples/clay-official-website") endif() + add_subdirectory("examples/cairo-pdf-rendering") add_subdirectory("examples/introducing-clay-video-demo") endif () diff --git a/bindings/odin/clay-odin/linux/clay.a b/bindings/odin/clay-odin/linux/clay.a index 02437d8..79b1ae3 100644 Binary files a/bindings/odin/clay-odin/linux/clay.a and b/bindings/odin/clay-odin/linux/clay.a differ diff --git a/bindings/odin/clay-odin/macos-arm64/clay.a b/bindings/odin/clay-odin/macos-arm64/clay.a index 6d539ea..08b256d 100644 Binary files a/bindings/odin/clay-odin/macos-arm64/clay.a and b/bindings/odin/clay-odin/macos-arm64/clay.a differ diff --git a/bindings/odin/clay-odin/macos/clay.a b/bindings/odin/clay-odin/macos/clay.a index 20c6124..d7a4750 100644 Binary files a/bindings/odin/clay-odin/macos/clay.a and b/bindings/odin/clay-odin/macos/clay.a differ diff --git a/bindings/odin/clay-odin/wasm/clay.o b/bindings/odin/clay-odin/wasm/clay.o index bf4f8db..fbbf500 100644 Binary files a/bindings/odin/clay-odin/wasm/clay.o and b/bindings/odin/clay-odin/wasm/clay.o differ diff --git a/bindings/odin/clay-odin/windows/clay.lib b/bindings/odin/clay-odin/windows/clay.lib index 45e430e..a6c2484 100644 Binary files a/bindings/odin/clay-odin/windows/clay.lib and b/bindings/odin/clay-odin/windows/clay.lib differ diff --git a/clay.h b/clay.h index cb7f91a..404bffa 100644 --- a/clay.h +++ b/clay.h @@ -13,6 +13,15 @@ #include #include #include +#include +#include + +// SIMD includes on supported platforms +#ifdef __x86_64__ +#include +#elif __aarch64__ +#include +#endif // ----------------------------------------- // HEADER DECLARATIONS --------------------- @@ -44,30 +53,12 @@ #define CLAY__MAX(x, y) (((x) > (y)) ? (x) : (y)) #define CLAY__MIN(x, y) (((x) < (y)) ? (x) : (y)) -#define CLAY_LAYOUT(...) Clay__AttachLayoutConfig(Clay__StoreLayoutConfig(CLAY__CONFIG_WRAPPER(Clay_LayoutConfig, __VA_ARGS__))) - -#define CLAY_RECTANGLE(...) Clay__AttachElementConfig(CLAY__INIT(Clay_ElementConfigUnion) { .rectangleElementConfig = Clay__StoreRectangleElementConfig(CLAY__CONFIG_WRAPPER(Clay_RectangleElementConfig, __VA_ARGS__)) }, CLAY__ELEMENT_CONFIG_TYPE_RECTANGLE) - #define CLAY_TEXT_CONFIG(...) Clay__StoreTextElementConfig(CLAY__CONFIG_WRAPPER(Clay_TextElementConfig, __VA_ARGS__)) -#define CLAY_IMAGE(...) Clay__AttachElementConfig(CLAY__INIT(Clay_ElementConfigUnion) { .imageElementConfig = Clay__StoreImageElementConfig(CLAY__CONFIG_WRAPPER(Clay_ImageElementConfig, __VA_ARGS__)) }, CLAY__ELEMENT_CONFIG_TYPE_IMAGE) - -#define CLAY_FLOATING(...) Clay__AttachElementConfig(CLAY__INIT(Clay_ElementConfigUnion) { .floatingElementConfig = Clay__StoreFloatingElementConfig(CLAY__CONFIG_WRAPPER(Clay_FloatingElementConfig, __VA_ARGS__)) }, CLAY__ELEMENT_CONFIG_TYPE_FLOATING_CONTAINER) - -#define CLAY_CUSTOM_ELEMENT(...) Clay__AttachElementConfig(CLAY__INIT(Clay_ElementConfigUnion) { .customElementConfig = Clay__StoreCustomElementConfig(CLAY__CONFIG_WRAPPER(Clay_CustomElementConfig, __VA_ARGS__)) }, CLAY__ELEMENT_CONFIG_TYPE_CUSTOM) - -#define CLAY_SCROLL(...) Clay__AttachElementConfig(CLAY__INIT(Clay_ElementConfigUnion) { .scrollElementConfig = Clay__StoreScrollElementConfig(CLAY__CONFIG_WRAPPER(Clay_ScrollElementConfig, __VA_ARGS__)) }, CLAY__ELEMENT_CONFIG_TYPE_SCROLL_CONTAINER) - -#define CLAY_BORDER(...) Clay__AttachElementConfig(CLAY__INIT(Clay_ElementConfigUnion) { .borderElementConfig = Clay__StoreBorderElementConfig(CLAY__CONFIG_WRAPPER(Clay_BorderElementConfig, __VA_ARGS__)) }, CLAY__ELEMENT_CONFIG_TYPE_BORDER_CONTAINER) - -#define CLAY_BORDER_OUTSIDE(...) Clay__AttachElementConfig(CLAY__INIT(Clay_ElementConfigUnion) { .borderElementConfig = Clay__StoreBorderElementConfig(CLAY__INIT(Clay_BorderElementConfig) { .left = __VA_ARGS__, .right = __VA_ARGS__, .top = __VA_ARGS__, .bottom = __VA_ARGS__ }) }, CLAY__ELEMENT_CONFIG_TYPE_BORDER_CONTAINER) - -#define CLAY_BORDER_OUTSIDE_RADIUS(width, color, radius) Clay__AttachElementConfig(CLAY__INIT(Clay_ElementConfigUnion) { .borderElementConfig = Clay__StoreBorderElementConfig(CLAY__INIT(Clay_BorderElementConfig) { .left = { width, color }, .right = { width, color }, .top = { width, color }, .bottom = { width, color }, .cornerRadius = CLAY_CORNER_RADIUS(radius) })}, CLAY__ELEMENT_CONFIG_TYPE_BORDER_CONTAINER) +#define CLAY_BORDER_OUTSIDE(...) CLAY__CONFIG_WRAPPER(Clay_BorderElementConfig, { .left = __VA_ARGS__, .right = __VA_ARGS__, .top = __VA_ARGS__, .bottom = __VA_ARGS__ }) #define CLAY_BORDER_ALL(...) Clay__AttachElementConfig(CLAY__INIT(Clay_ElementConfigUnion) { .borderElementConfig = Clay__StoreBorderElementConfig(CLAY__INIT(Clay_BorderElementConfig) { .left = __VA_ARGS__, .right = __VA_ARGS__, .top = __VA_ARGS__, .bottom = __VA_ARGS__, .betweenChildren = __VA_ARGS__ } ) }, CLAY__ELEMENT_CONFIG_TYPE_BORDER_CONTAINER) -#define CLAY_BORDER_ALL_RADIUS(width, color, radius) Clay__AttachElementConfig(CLAY__INIT(Clay_ElementConfigUnion) { .borderElementConfig = Clay__StoreBorderElementConfig(CLAY__INIT(Clay_BorderElementConfig) { .left = { width, color }, .right = { width, color }, .top = { width, color }, .bottom = { width, color }, .betweenChildren = { width, color }, .cornerRadius = CLAY_CORNER_RADIUS(radius)}) }, CLAY__ELEMENT_CONFIG_TYPE_BORDER_CONTAINER) - #define CLAY_CORNER_RADIUS(radius) (CLAY__INIT(Clay_CornerRadius) { radius, radius, radius, radius }) #define CLAY_PADDING_ALL(padding) CLAY__CONFIG_WRAPPER(Clay_Padding, { padding, padding, padding, padding }) @@ -80,13 +71,13 @@ #define CLAY_SIZING_PERCENT(percentOfParent) (CLAY__INIT(Clay_SizingAxis) { .size = { .percent = (percentOfParent) }, .type = CLAY__SIZING_TYPE_PERCENT }) -#define CLAY_ID(label) Clay__AttachId(Clay__HashString(CLAY_STRING(label), 0, 0)) +#define CLAY_ID(label) Clay__HashString(CLAY_STRING(label), 0, 0) -#define CLAY_IDI(label, index) Clay__AttachId(Clay__HashString(CLAY_STRING(label), index, 0)) +#define CLAY_IDI(label, index) Clay__HashString(CLAY_STRING(label), index, 0) #define CLAY_ID_LOCAL(label) CLAY_IDI_LOCAL(label, 0) -#define CLAY_IDI_LOCAL(label, index) Clay__AttachId(Clay__HashString(CLAY_STRING(label), index, Clay__GetParentElementId())) +#define CLAY_IDI_LOCAL(label, index) Clay__HashString(CLAY_STRING(label), index, Clay__GetParentElementId()) #define CLAY__STRING_LENGTH(s) ((sizeof(s) / sizeof((s)[0])) - sizeof((s)[0])) @@ -126,7 +117,7 @@ static uint8_t CLAY__ELEMENT_DEFINITION_LATCH; */ #define CLAY(...) \ for (\ - CLAY__ELEMENT_DEFINITION_LATCH = (Clay__OpenElement(), __VA_ARGS__, Clay__ElementPostConfiguration(), 0); \ + CLAY__ELEMENT_DEFINITION_LATCH = (Clay__OpenElement(), Clay__ConfigureOpenElement(CLAY__CONFIG_WRAPPER(Clay_ElementDeclaration, __VA_ARGS__)), 0); \ CLAY__ELEMENT_DEFINITION_LATCH < 1; \ ++CLAY__ELEMENT_DEFINITION_LATCH, Clay__CloseElement() \ ) @@ -220,12 +211,13 @@ typedef struct { typedef CLAY_PACKED_ENUM { CLAY__ELEMENT_CONFIG_TYPE_NONE = 0, CLAY__ELEMENT_CONFIG_TYPE_RECTANGLE = 1, - CLAY__ELEMENT_CONFIG_TYPE_BORDER_CONTAINER = 2, - CLAY__ELEMENT_CONFIG_TYPE_FLOATING_CONTAINER = 4, - CLAY__ELEMENT_CONFIG_TYPE_SCROLL_CONTAINER = 8, + 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__ElementConfigType; // Element Configs --------------------------- @@ -302,7 +294,6 @@ extern Clay_LayoutConfig CLAY_LAYOUT_DEFAULT; // NOTE: Not declared in the typedef asan ifdef inside macro arguments is UB typedef struct { Clay_Color color; - Clay_CornerRadius cornerRadius; #ifdef CLAY_EXTEND_CONFIG_RECTANGLE CLAY_EXTEND_CONFIG_RECTANGLE #endif @@ -397,6 +388,13 @@ typedef struct { CLAY__WRAPPER_STRUCT(Clay_ScrollElementConfig); +// Scroll +typedef struct { + Clay_CornerRadius cornerRadius; +} Clay_SharedElementConfig; + +CLAY__WRAPPER_STRUCT(Clay_SharedElementConfig); + // Border typedef struct { uint32_t width; @@ -409,7 +407,6 @@ typedef struct { Clay_Border top; Clay_Border bottom; Clay_Border betweenChildren; - Clay_CornerRadius cornerRadius; #ifdef CLAY_EXTEND_CONFIG_BORDER CLAY_EXTEND_CONFIG_BORDER #endif @@ -425,6 +422,7 @@ typedef union { Clay_CustomElementConfig *customElementConfig; Clay_ScrollElementConfig *scrollElementConfig; Clay_BorderElementConfig *borderElementConfig; + Clay_SharedElementConfig *sharedElementConfig; } Clay_ElementConfigUnion; typedef struct { @@ -465,7 +463,10 @@ typedef CLAY_PACKED_ENUM { typedef struct { Clay_BoundingBox boundingBox; Clay_ElementConfigUnion config; - Clay_StringSlice text; // TODO I wish there was a way to avoid having to have this on every render command + 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; int32_t zIndex; uint32_t id; Clay_RenderCommandType commandType; @@ -489,6 +490,20 @@ typedef struct { Clay_PointerDataInteractionState state; } Clay_PointerData; +typedef struct { + Clay_ElementId id; + Clay_LayoutConfig layout; + Clay_RectangleElementConfig rectangle; + 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); + typedef CLAY_PACKED_ENUM { CLAY_ERROR_TYPE_TEXT_MEASUREMENT_FUNCTION_NOT_PROVIDED, CLAY_ERROR_TYPE_ARENA_CAPACITY_EXCEEDED, @@ -529,6 +544,7 @@ bool Clay_Hovered(void); void Clay_OnHover(void (*onHoverFunction)(Clay_ElementId elementId, Clay_PointerData pointerData, intptr_t userData), intptr_t userData); bool Clay_PointerOver(Clay_ElementId elementId); Clay_ScrollContainerData Clay_GetScrollContainerData(Clay_ElementId id); +Clay_TextElementConfig * Clay__StoreTextElementConfig(Clay_TextElementConfig config); void Clay_SetMeasureTextFunction(Clay_Dimensions (*measureTextFunction)(Clay_StringSlice text, Clay_TextElementConfig *config, uintptr_t userData), uintptr_t userData); void Clay_SetQueryScrollOffsetFunction(Clay_Vector2 (*queryScrollOffsetFunction)(uint32_t elementId, uintptr_t userData), uintptr_t userData); Clay_RenderCommand * Clay_RenderCommandArray_Get(Clay_RenderCommandArray* array, int32_t index); @@ -542,20 +558,11 @@ void Clay_SetMaxMeasureTextCacheWordCount(int32_t maxMeasureTextCacheWordCount); void Clay_ResetMeasureTextCache(void); // Internal API functions required by macros -void Clay__OpenElement(void); +void Clay__OpenElement(); +void Clay__ConfigureOpenElement(const Clay_ElementDeclaration config); void Clay__CloseElement(void); Clay_LayoutConfig * Clay__StoreLayoutConfig(Clay_LayoutConfig config); -void Clay__ElementPostConfiguration(void); -void Clay__AttachId(Clay_ElementId id); -void Clay__AttachLayoutConfig(Clay_LayoutConfig *config); -void Clay__AttachElementConfig(Clay_ElementConfigUnion config, Clay__ElementConfigType type); -Clay_RectangleElementConfig * Clay__StoreRectangleElementConfig(Clay_RectangleElementConfig config); -Clay_TextElementConfig * Clay__StoreTextElementConfig(Clay_TextElementConfig config); -Clay_ImageElementConfig * Clay__StoreImageElementConfig(Clay_ImageElementConfig config); -Clay_FloatingElementConfig * Clay__StoreFloatingElementConfig(Clay_FloatingElementConfig config); -Clay_CustomElementConfig * Clay__StoreCustomElementConfig(Clay_CustomElementConfig config); -Clay_ScrollElementConfig * Clay__StoreScrollElementConfig(Clay_ScrollElementConfig config); -Clay_BorderElementConfig * Clay__StoreBorderElementConfig(Clay_BorderElementConfig config); +Clay_ElementId Clay__AttachId(Clay_ElementId id); Clay_ElementId Clay__HashString(Clay_String key, uint32_t offset, uint32_t seed); void Clay__OpenTextElement(Clay_String text, Clay_TextElementConfig *textConfig); uint32_t Clay__GetParentElementId(void); @@ -697,6 +704,7 @@ CLAY__ARRAY_DEFINE(Clay_CustomElementConfig, Clay__CustomElementConfigArray) CLAY__ARRAY_DEFINE(Clay_ScrollElementConfig, Clay__ScrollElementConfigArray) CLAY__ARRAY_DEFINE(Clay_BorderElementConfig, Clay__BorderElementConfigArray) CLAY__ARRAY_DEFINE(Clay_String, Clay__StringArray) +CLAY__ARRAY_DEFINE(Clay_SharedElementConfig, Clay__SharedElementConfigArray) CLAY__ARRAY_DEFINE_FUNCTIONS(Clay_RenderCommand, Clay_RenderCommandArray) typedef struct { @@ -844,7 +852,6 @@ struct Clay_Context { Clay__int32_tArray layoutElementClipElementIds; // Configs Clay__LayoutConfigArray layoutConfigs; - Clay__ElementConfigArray elementConfigBuffer; Clay__ElementConfigArray elementConfigs; Clay__RectangleElementConfigArray rectangleElementConfigs; Clay__TextElementConfigArray textElementConfigs; @@ -853,6 +860,7 @@ struct Clay_Context { Clay__ScrollElementConfigArray scrollElementConfigs; Clay__CustomElementConfigArray customElementConfigs; Clay__BorderElementConfigArray borderElementConfigs; + Clay__SharedElementConfigArray sharedElementConfigs; // Misc Data Structures Clay__StringArray layoutElementIdStrings; Clay__WrappedTextLineArray wrappedTextLines; @@ -916,6 +924,27 @@ bool Clay__ElementHasConfig(Clay_LayoutElement *element, Clay__ElementConfigType 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); } +Clay_CustomElementConfig * Clay__StoreCustomElementConfig(Clay_CustomElementConfig config) { return Clay_GetCurrentContext()->booleanWarnings.maxElementsExceeded ? &Clay_CustomElementConfig_DEFAULT : Clay__CustomElementConfigArray_Add(&Clay_GetCurrentContext()->customElementConfigs, config); } +Clay_ScrollElementConfig * Clay__StoreScrollElementConfig(Clay_ScrollElementConfig config) { return Clay_GetCurrentContext()->booleanWarnings.maxElementsExceeded ? &Clay_ScrollElementConfig_DEFAULT : Clay__ScrollElementConfigArray_Add(&Clay_GetCurrentContext()->scrollElementConfigs, config); } +Clay_BorderElementConfig * Clay__StoreBorderElementConfig(Clay_BorderElementConfig config) { return Clay_GetCurrentContext()->booleanWarnings.maxElementsExceeded ? &Clay_BorderElementConfig_DEFAULT : Clay__BorderElementConfigArray_Add(&Clay_GetCurrentContext()->borderElementConfigs, config); } +Clay_SharedElementConfig * Clay__StoreSharedElementConfig(Clay_SharedElementConfig config) { return Clay_GetCurrentContext()->booleanWarnings.maxElementsExceeded ? &Clay_SharedElementConfig_DEFAULT : Clay__SharedElementConfigArray_Add(&Clay_GetCurrentContext()->sharedElementConfigs, config); } + +Clay_ElementConfig Clay__AttachElementConfig(Clay_ElementConfigUnion config, Clay__ElementConfigType type) { + Clay_Context* context = Clay_GetCurrentContext(); + if (context->booleanWarnings.maxElementsExceeded) { + return CLAY__INIT(Clay_ElementConfig) CLAY__DEFAULT_STRUCT; + } + 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 }); +} + Clay_ElementConfigUnion Clay__FindElementConfigWithType(Clay_LayoutElement *element, Clay__ElementConfigType type) { for (int32_t i = 0; i < element->elementConfigs.length; i++) { Clay_ElementConfig *config = Clay__ElementConfigArraySlice_Get(&element->elementConfigs, i); @@ -926,6 +955,45 @@ 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); + } +} + +Clay_RectangleElementConfig * Clay_CurrentConfigRectangle() { return Clay__CurrentConfigUnion(CLAY__ELEMENT_CONFIG_TYPE_RECTANGLE).config.rectangleElementConfig; } +Clay_TextElementConfig * Clay_CurrentConfigText() { return Clay__CurrentConfigUnion(CLAY__ELEMENT_CONFIG_TYPE_TEXT).config.textElementConfig; } +Clay_ImageElementConfig * Clay_CurrentConfigImage() { return Clay__CurrentConfigUnion(CLAY__ELEMENT_CONFIG_TYPE_IMAGE).config.imageElementConfig; } +Clay_FloatingElementConfig * Clay_CurrentConfigFloating() { return Clay__CurrentConfigUnion(CLAY__ELEMENT_CONFIG_TYPE_FLOATING).config.floatingElementConfig; } +Clay_CustomElementConfig * Clay_CurrentConfigCustom() { return Clay__CurrentConfigUnion(CLAY__ELEMENT_CONFIG_TYPE_CUSTOM).config.customElementConfig; } +Clay_ScrollElementConfig * Clay_CurrentConfigScroll() { return Clay__CurrentConfigUnion(CLAY__ELEMENT_CONFIG_TYPE_SCROLL).config.scrollElementConfig; } +Clay_BorderElementConfig * Clay_CurrentConfigBorder() { return Clay__CurrentConfigUnion(CLAY__ELEMENT_CONFIG_TYPE_BORDER).config.borderElementConfig; } +Clay_SharedElementConfig * Clay_CurrentConfigShared() { 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); @@ -1250,97 +1318,6 @@ void Clay__GenerateIdForAnonymousElement(Clay_LayoutElement *openLayoutElement) Clay__StringArray_Add(&context->layoutElementIdStrings, elementId.stringId); } -void Clay__ElementPostConfiguration(void) { - Clay_Context* context = Clay_GetCurrentContext(); - if (context->booleanWarnings.maxElementsExceeded) { - return; - } - Clay_LayoutElement *openLayoutElement = Clay__GetOpenLayoutElement(); - // ID - if (openLayoutElement->id == 0) { - Clay__GenerateIdForAnonymousElement(openLayoutElement); - } - // Layout Config - if (!openLayoutElement->layoutConfig) { - openLayoutElement->layoutConfig = &CLAY_LAYOUT_DEFAULT; - } - - // Loop through element configs and handle special cases - openLayoutElement->elementConfigs.internalArray = &context->elementConfigs.internalArray[context->elementConfigs.length]; - for (int32_t elementConfigIndex = 0; elementConfigIndex < openLayoutElement->elementConfigs.length; elementConfigIndex++) { - Clay_ElementConfig *config = Clay__ElementConfigArray_Add(&context->elementConfigs, *Clay__ElementConfigArray_Get(&context->elementConfigBuffer, context->elementConfigBuffer.length - openLayoutElement->elementConfigs.length + elementConfigIndex)); - openLayoutElement->configsEnabled |= config->type; - switch (config->type) { - case CLAY__ELEMENT_CONFIG_TYPE_RECTANGLE: - case CLAY__ELEMENT_CONFIG_TYPE_BORDER_CONTAINER: break; - case CLAY__ELEMENT_CONFIG_TYPE_FLOATING_CONTAINER: { - Clay_FloatingElementConfig *floatingConfig = config->config.floatingElementConfig; - // This looks dodgy but because of the auto generated root element the depth of the tree will always be at least 2 here - Clay_LayoutElement *hierarchicalParent = Clay_LayoutElementArray_Get(&context->layoutElements, Clay__int32_tArray_GetValue(&context->openLayoutElementStack, context->openLayoutElementStack.length - 2)); - if (!hierarchicalParent) { - break; - } - uint32_t clipElementId = 0; - if (floatingConfig->parentId == 0) { - // If no parent id was specified, attach to the elements direct hierarchical parent - Clay_FloatingElementConfig newConfig = *floatingConfig; - newConfig.parentId = hierarchicalParent->id; - floatingConfig = Clay__FloatingElementConfigArray_Add(&context->floatingElementConfigs, newConfig); - config->config.floatingElementConfig = floatingConfig; - if (context->openClipElementStack.length > 0) { - clipElementId = Clay__int32_tArray_GetValue(&context->openClipElementStack, (int)context->openClipElementStack.length - 1); - } - } else { - Clay_LayoutElementHashMapItem *parentItem = Clay__GetHashMapItem(floatingConfig->parentId); - if (!parentItem) { - context->errorHandler.errorHandlerFunction(CLAY__INIT(Clay_ErrorData) { - .errorType = CLAY_ERROR_TYPE_FLOATING_CONTAINER_PARENT_NOT_FOUND, - .errorText = CLAY_STRING("A floating element was declared with a parentId, but no element with that ID was found."), - .userData = context->errorHandler.userData }); - } else { - clipElementId = Clay__int32_tArray_GetValue(&context->layoutElementClipElementIds, parentItem->layoutElement - context->layoutElements.internalArray); - } - } - Clay__LayoutElementTreeRootArray_Add(&context->layoutElementTreeRoots, CLAY__INIT(Clay__LayoutElementTreeRoot) { - .layoutElementIndex = Clay__int32_tArray_GetValue(&context->openLayoutElementStack, context->openLayoutElementStack.length - 1), - .parentId = floatingConfig->parentId, - .clipElementId = clipElementId, - .zIndex = floatingConfig->zIndex, - }); - break; - } - case CLAY__ELEMENT_CONFIG_TYPE_SCROLL_CONTAINER: { - Clay__int32_tArray_Add(&context->openClipElementStack, (int)openLayoutElement->id); - // Retrieve or create cached data to track scroll position across frames - Clay__ScrollContainerDataInternal *scrollOffset = CLAY__NULL; - for (int32_t i = 0; i < context->scrollContainerDatas.length; i++) { - Clay__ScrollContainerDataInternal *mapping = Clay__ScrollContainerDataInternalArray_Get(&context->scrollContainerDatas, i); - if (openLayoutElement->id == mapping->elementId) { - scrollOffset = mapping; - scrollOffset->layoutElement = openLayoutElement; - scrollOffset->openThisFrame = true; - } - } - if (!scrollOffset) { - scrollOffset = Clay__ScrollContainerDataInternalArray_Add(&context->scrollContainerDatas, CLAY__INIT(Clay__ScrollContainerDataInternal){.layoutElement = openLayoutElement, .scrollOrigin = {-1,-1}, .elementId = openLayoutElement->id, .openThisFrame = true}); - } - if (context->externalScrollHandlingEnabled) { - scrollOffset->scrollPosition = Clay__QueryScrollOffset(scrollOffset->elementId, context->queryScrollOffsetUserData); - } - break; - } - case CLAY__ELEMENT_CONFIG_TYPE_CUSTOM: break; - case CLAY__ELEMENT_CONFIG_TYPE_IMAGE: { - Clay__int32_tArray_Add(&context->imageElementPointers, context->layoutElements.length - 1); - break; - } - case CLAY__ELEMENT_CONFIG_TYPE_TEXT: - default: break; - } - } - context->elementConfigBuffer.length -= openLayoutElement->elementConfigs.length; -} - void Clay__CloseElement(void) { Clay_Context* context = Clay_GetCurrentContext(); if (context->booleanWarnings.maxElementsExceeded) { @@ -1350,8 +1327,8 @@ void Clay__CloseElement(void) { Clay_LayoutConfig *layoutConfig = openLayoutElement->layoutConfig; bool elementHasScrollHorizontal = false; bool elementHasScrollVertical = false; - if (Clay__ElementHasConfig(openLayoutElement, CLAY__ELEMENT_CONFIG_TYPE_SCROLL_CONTAINER)) { - Clay_ScrollElementConfig *scrollConfig = Clay__FindElementConfigWithType(openLayoutElement, CLAY__ELEMENT_CONFIG_TYPE_SCROLL_CONTAINER).scrollElementConfig; + 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--; @@ -1424,7 +1401,7 @@ void Clay__CloseElement(void) { openLayoutElement->dimensions.height = 0; } - bool elementIsFloating = Clay__ElementHasConfig(openLayoutElement, CLAY__ELEMENT_CONFIG_TYPE_FLOATING_CONTAINER); + bool elementIsFloating = Clay__ElementHasConfig(openLayoutElement, CLAY__ELEMENT_CONFIG_TYPE_FLOATING); // Close the currently open element int32_t closingElementIndex = Clay__int32_tArray_RemoveSwapback(&context->openLayoutElementStack, (int)context->openLayoutElementStack.length - 1); @@ -1436,7 +1413,72 @@ void Clay__CloseElement(void) { } } -void Clay__OpenElement(void) { +bool Clay__MemCmp(const char *s1, const char *s2, int32_t length); +#ifdef __x86_64__ + bool Clay__MemCmp(const char *s1, const char *s2, int32_t length) { + while (length >= 16) { + __m128i v1 = _mm_loadu_si128((const __m128i *)s1); + __m128i v2 = _mm_loadu_si128((const __m128i *)s2); + + if (_mm_movemask_epi8(_mm_cmpeq_epi8(v1, v2)) != 0xFFFF) { // If any byte differs + return false; + } + + s1 += 16; + s2 += 16; + length -= 16; + } + + // Handle remaining bytes + while (length--) { + if (*s1 != *s2) { + return false; + } + s1++; + s2++; + } + + return true; + } +#elif defined(__aarch64__) + bool Clay__MemCmp(const char *s1, const char *s2, int32_t length) { + while (length >= 16) { + uint8x16_t v1 = vld1q_u8((const uint8_t *)s1); + uint8x16_t v2 = vld1q_u8((const uint8_t *)s2); + + // Compare vectors + if (vminvq_u32(vceqq_u8(v1, v2)) != 0xFFFFFFFF) { // If there's a difference + return false; + } + + s1 += 16; + s2 += 16; + length -= 16; + } + + // Handle remaining bytes + while (length--) { + if (*s1 != *s2) { + return false; + } + s1++; + s2++; + } + + return true; + } +#else + bool Clay__MemCmp(const char *s1, const char *s2, int32_t length) { + for (int32_t i = 0; i < length; i++) { + if (s1[i] != s2[i]) { + return false; + } + } + return true; + } +#endif + +void Clay__OpenElement() { Clay_Context* context = Clay_GetCurrentContext(); if (context->layoutElements.length == context->layoutElements.capacity - 1 || context->booleanWarnings.maxElementsExceeded) { context->booleanWarnings.maxElementsExceeded = true; @@ -1461,26 +1503,111 @@ void Clay__OpenTextElement(Clay_String text, Clay_TextElementConfig *textConfig) Clay_LayoutElement *parentElement = Clay__GetOpenLayoutElement(); parentElement->childrenOrTextContent.children.length++; - Clay__OpenElement(); - Clay_LayoutElement * openLayoutElement = Clay__GetOpenLayoutElement(); + Clay_LayoutElement layoutElement = CLAY__DEFAULT_STRUCT; + Clay_LayoutElement *textElement = Clay_LayoutElementArray_Add(&context->layoutElements, layoutElement); + if (context->openClipElementStack.length > 0) { + Clay__int32_tArray_Set(&context->layoutElementClipElementIds, context->layoutElements.length - 1, Clay__int32_tArray_GetValue(&context->openClipElementStack, (int)context->openClipElementStack.length - 1)); + } else { + Clay__int32_tArray_Set(&context->layoutElementClipElementIds, context->layoutElements.length - 1, 0); + } + Clay__int32_tArray_Add(&context->layoutElementChildrenBuffer, context->layoutElements.length - 1); Clay__MeasureTextCacheItem *textMeasured = Clay__MeasureTextCached(&text, textConfig); Clay_ElementId elementId = Clay__HashString(CLAY_STRING("Text"), parentElement->childrenOrTextContent.children.length, parentElement->id); - openLayoutElement->id = elementId.id; - Clay__AddHashMapItem(elementId, openLayoutElement); + textElement->id = elementId.id; + Clay__AddHashMapItem(elementId, textElement); Clay__StringArray_Add(&context->layoutElementIdStrings, elementId.stringId); Clay_Dimensions textDimensions = { .width = textMeasured->unwrappedDimensions.width, .height = textConfig->lineHeight > 0 ? (float)textConfig->lineHeight : textMeasured->unwrappedDimensions.height }; - openLayoutElement->dimensions = textDimensions; - openLayoutElement->minDimensions = CLAY__INIT(Clay_Dimensions) { .width = textMeasured->unwrappedDimensions.height, .height = textDimensions.height }; // TODO not sure this is the best way to decide min width for text - openLayoutElement->childrenOrTextContent.textElementData = Clay__TextElementDataArray_Add(&context->textElementData, CLAY__INIT(Clay__TextElementData) { .text = text, .preferredDimensions = textMeasured->unwrappedDimensions, .elementIndex = context->layoutElements.length - 1 }); - openLayoutElement->elementConfigs = CLAY__INIT(Clay__ElementConfigArraySlice) { - .length = 1, - .internalArray = Clay__ElementConfigArray_Add(&context->elementConfigs, CLAY__INIT(Clay_ElementConfig) { .type = CLAY__ELEMENT_CONFIG_TYPE_TEXT, .config = { .textElementConfig = textConfig }}) + textElement->dimensions = textDimensions; + textElement->minDimensions = CLAY__INIT(Clay_Dimensions) { .width = textMeasured->unwrappedDimensions.height, .height = textDimensions.height }; // TODO not sure this is the best way to decide min width for text + textElement->childrenOrTextContent.textElementData = Clay__TextElementDataArray_Add(&context->textElementData, CLAY__INIT(Clay__TextElementData) { .text = text, .preferredDimensions = textMeasured->unwrappedDimensions, .elementIndex = context->layoutElements.length - 1 }); + textElement->elementConfigs = CLAY__INIT(Clay__ElementConfigArraySlice) { + .length = 1, + .internalArray = Clay__ElementConfigArray_Add(&context->elementConfigs, CLAY__INIT(Clay_ElementConfig) { .type = CLAY__ELEMENT_CONFIG_TYPE_TEXT, .config = { .textElementConfig = textConfig }}) }; - openLayoutElement->configsEnabled |= CLAY__ELEMENT_CONFIG_TYPE_TEXT; - openLayoutElement->layoutConfig = &CLAY_LAYOUT_DEFAULT; - // Close the currently open element - Clay__int32_tArray_RemoveSwapback(&context->openLayoutElementStack, (int)context->openLayoutElementStack.length - 1); + textElement->configsEnabled |= CLAY__ELEMENT_CONFIG_TYPE_TEXT; + textElement->layoutConfig = &CLAY_LAYOUT_DEFAULT; +} + +void Clay__ConfigureOpenElement(const Clay_ElementDeclaration declaration) { + Clay_Context* context = Clay_GetCurrentContext(); + Clay_LayoutElement *openLayoutElement = Clay__GetOpenLayoutElement(); + openLayoutElement->layoutConfig = Clay__StoreLayoutConfig(declaration.layout); + if (declaration.id.id != 0) { + Clay__AttachId(declaration.id); + } else if (openLayoutElement->id == 0) { + Clay__GenerateIdForAnonymousElement(openLayoutElement); + } + + 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); + } + 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); + Clay__int32_tArray_Add(&context->imageElementPointers, context->layoutElements.length - 1); + } + if (!Clay__MemCmp((char *)(&declaration.floating), (char *)(&Clay_FloatingElementConfig_DEFAULT), sizeof(Clay_FloatingElementConfig))) { + Clay_FloatingElementConfig floatingConfig = declaration.floating; + // This looks dodgy but because of the auto generated root element the depth of the tree will always be at least 2 here + Clay_LayoutElement *hierarchicalParent = Clay_LayoutElementArray_Get(&context->layoutElements, Clay__int32_tArray_GetValue(&context->openLayoutElementStack, context->openLayoutElementStack.length - 2)); + if (hierarchicalParent) { + uint32_t clipElementId = 0; + if (floatingConfig.parentId == 0) { + // If no parent id was specified, attach to the elements direct hierarchical parent + floatingConfig.parentId = hierarchicalParent->id; + if (context->openClipElementStack.length > 0) { + clipElementId = Clay__int32_tArray_GetValue(&context->openClipElementStack, (int)context->openClipElementStack.length - 1); + } + } else { + Clay_LayoutElementHashMapItem *parentItem = Clay__GetHashMapItem(floatingConfig.parentId); + if (!parentItem) { + context->errorHandler.errorHandlerFunction(CLAY__INIT(Clay_ErrorData) { + .errorType = CLAY_ERROR_TYPE_FLOATING_CONTAINER_PARENT_NOT_FOUND, + .errorText = CLAY_STRING("A floating element was declared with a parentId, but no element with that ID was found."), + .userData = context->errorHandler.userData }); + } else { + clipElementId = Clay__int32_tArray_GetValue(&context->layoutElementClipElementIds, parentItem->layoutElement - context->layoutElements.internalArray); + } + } + Clay__LayoutElementTreeRootArray_Add(&context->layoutElementTreeRoots, CLAY__INIT(Clay__LayoutElementTreeRoot) { + .layoutElementIndex = Clay__int32_tArray_GetValue(&context->openLayoutElementStack, context->openLayoutElementStack.length - 1), + .parentId = floatingConfig.parentId, + .clipElementId = clipElementId, + .zIndex = floatingConfig.zIndex, + }); + Clay__AttachElementConfig(CLAY__INIT(Clay_ElementConfigUnion) { .floatingElementConfig = Clay__StoreFloatingElementConfig(declaration.floating) }, CLAY__ELEMENT_CONFIG_TYPE_FLOATING); + } + } + 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); + // Retrieve or create cached data to track scroll position across frames + Clay__ScrollContainerDataInternal *scrollOffset = CLAY__NULL; + for (int32_t i = 0; i < context->scrollContainerDatas.length; i++) { + Clay__ScrollContainerDataInternal *mapping = Clay__ScrollContainerDataInternalArray_Get(&context->scrollContainerDatas, i); + if (openLayoutElement->id == mapping->elementId) { + scrollOffset = mapping; + scrollOffset->layoutElement = openLayoutElement; + scrollOffset->openThisFrame = true; + } + } + if (!scrollOffset) { + scrollOffset = Clay__ScrollContainerDataInternalArray_Add(&context->scrollContainerDatas, CLAY__INIT(Clay__ScrollContainerDataInternal){.layoutElement = openLayoutElement, .scrollOrigin = {-1,-1}, .elementId = openLayoutElement->id, .openThisFrame = true}); + } + if (context->externalScrollHandlingEnabled) { + scrollOffset->scrollPosition = Clay__QueryScrollOffset(scrollOffset->elementId, context->queryScrollOffsetUserData); + } + } + if (!Clay__MemCmp((char *)(&declaration.border), (char *)(&Clay_BorderElementConfig_DEFAULT), sizeof(Clay_BorderElementConfig))) { + Clay__AttachElementConfig(CLAY__INIT(Clay_ElementConfigUnion) { .borderElementConfig = Clay__StoreBorderElementConfig(declaration.border) }, CLAY__ELEMENT_CONFIG_TYPE_BORDER); + } } void Clay__InitializeEphemeralMemory(Clay_Context* context) { @@ -1494,7 +1621,6 @@ void Clay__InitializeEphemeralMemory(Clay_Context* context) { context->warnings = Clay__WarningArray_Allocate_Arena(100, arena); context->layoutConfigs = Clay__LayoutConfigArray_Allocate_Arena(maxElementCount, arena); - context->elementConfigBuffer = Clay__ElementConfigArray_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); @@ -1503,6 +1629,7 @@ void Clay__InitializeEphemeralMemory(Clay_Context* context) { context->scrollElementConfigs = Clay__ScrollElementConfigArray_Allocate_Arena(maxElementCount, arena); context->customElementConfigs = Clay__CustomElementConfigArray_Allocate_Arena(maxElementCount, arena); context->borderElementConfigs = Clay__BorderElementConfigArray_Allocate_Arena(maxElementCount, arena); + context->sharedElementConfigs = Clay__SharedElementConfigArray_Allocate_Arena(maxElementCount, arena); context->layoutElementIdStrings = Clay__StringArray_Allocate_Arena(maxElementCount, arena); context->wrappedTextLines = Clay__WrappedTextLineArray_Allocate_Arena(maxElementCount, arena); @@ -1605,10 +1732,10 @@ void Clay__SizeContainersAlongAxis(bool xAxis) { Clay__int32_tArray_Add(&bfsBuffer, (int32_t)root->layoutElementIndex); // Size floating containers to their parents - if (Clay__ElementHasConfig(rootElement, CLAY__ELEMENT_CONFIG_TYPE_FLOATING_CONTAINER)) { - Clay_FloatingElementConfig *floatingElementConfig = Clay__FindElementConfigWithType(rootElement, CLAY__ELEMENT_CONFIG_TYPE_FLOATING_CONTAINER).floatingElementConfig; + if (Clay__ElementHasConfig(rootElement, CLAY__ELEMENT_CONFIG_TYPE_FLOATING)) { + Clay_FloatingElementConfig *floatingElementConfig = Clay__FindElementConfigWithType(rootElement, CLAY__ELEMENT_CONFIG_TYPE_FLOATING).floatingElementConfig; Clay_LayoutElementHashMapItem *parentItem = Clay__GetHashMapItem(floatingElementConfig->parentId); - if (parentItem) { + if (parentItem && parentItem != &Clay_LayoutElementHashMapItem_DEFAULT) { Clay_LayoutElement *parentLayoutElement = parentItem->layoutElement; if (rootElement->layoutConfig->sizing.width.type == CLAY__SIZING_TYPE_GROW) { rootElement->dimensions.width = parentLayoutElement->dimensions.width; @@ -1682,8 +1809,8 @@ void Clay__SizeContainersAlongAxis(bool xAxis) { // The content is too large, compress the children as much as possible if (sizeToDistribute < 0) { // If the parent can scroll in the axis direction in this direction, don't compress children, just leave them alone - if (Clay__ElementHasConfig(parent, CLAY__ELEMENT_CONFIG_TYPE_SCROLL_CONTAINER)) { - Clay_ScrollElementConfig *scrollElementConfig = Clay__FindElementConfigWithType(parent, CLAY__ELEMENT_CONFIG_TYPE_SCROLL_CONTAINER).scrollElementConfig; + if (Clay__ElementHasConfig(parent, CLAY__ELEMENT_CONFIG_TYPE_SCROLL)) { + Clay_ScrollElementConfig *scrollElementConfig = Clay__FindElementConfigWithType(parent, CLAY__ELEMENT_CONFIG_TYPE_SCROLL).scrollElementConfig; if (((xAxis && scrollElementConfig->horizontal) || (!xAxis && scrollElementConfig->vertical))) { continue; } @@ -1724,8 +1851,8 @@ void Clay__SizeContainersAlongAxis(bool xAxis) { // If we're laying out the children of a scroll panel, grow containers expand to the height of the inner content, not the outer container float maxSize = parentSize - parentPadding; - if (Clay__ElementHasConfig(parent, CLAY__ELEMENT_CONFIG_TYPE_SCROLL_CONTAINER)) { - Clay_ScrollElementConfig *scrollElementConfig = Clay__FindElementConfigWithType(parent, CLAY__ELEMENT_CONFIG_TYPE_SCROLL_CONTAINER).scrollElementConfig; + if (Clay__ElementHasConfig(parent, CLAY__ELEMENT_CONFIG_TYPE_SCROLL)) { + Clay_ScrollElementConfig *scrollElementConfig = Clay__FindElementConfigWithType(parent, CLAY__ELEMENT_CONFIG_TYPE_SCROLL).scrollElementConfig; if (((xAxis && scrollElementConfig->horizontal) || (!xAxis && scrollElementConfig->vertical))) { maxSize = CLAY__MAX(maxSize, innerContentSize); } @@ -1939,8 +2066,8 @@ void Clay__CalculateFinalLayout(void) { Clay_Vector2 rootPosition = CLAY__DEFAULT_STRUCT; Clay_LayoutElementHashMapItem *parentHashMapItem = Clay__GetHashMapItem(root->parentId); // Position root floating containers - if (Clay__ElementHasConfig(rootElement, CLAY__ELEMENT_CONFIG_TYPE_FLOATING_CONTAINER) && parentHashMapItem) { - Clay_FloatingElementConfig *config = Clay__FindElementConfigWithType(rootElement, CLAY__ELEMENT_CONFIG_TYPE_FLOATING_CONTAINER).floatingElementConfig; + if (Clay__ElementHasConfig(rootElement, CLAY__ELEMENT_CONFIG_TYPE_FLOATING) && parentHashMapItem) { + Clay_FloatingElementConfig *config = Clay__FindElementConfigWithType(rootElement, CLAY__ELEMENT_CONFIG_TYPE_FLOATING).floatingElementConfig; Clay_Dimensions rootDimensions = rootElement->dimensions; Clay_BoundingBox parentBoundingBox = parentHashMapItem->boundingBox; // Set X position @@ -1998,7 +2125,7 @@ void Clay__CalculateFinalLayout(void) { if (clipHashMapItem) { // Floating elements that are attached to scrolling contents won't be correctly positioned if external scroll handling is enabled, fix here if (context->externalScrollHandlingEnabled) { - Clay_ScrollElementConfig *scrollConfig = Clay__FindElementConfigWithType(clipHashMapItem->layoutElement, CLAY__ELEMENT_CONFIG_TYPE_SCROLL_CONTAINER).scrollElementConfig; + Clay_ScrollElementConfig *scrollConfig = Clay__FindElementConfigWithType(clipHashMapItem->layoutElement, CLAY__ELEMENT_CONFIG_TYPE_SCROLL).scrollElementConfig; for (int32_t i = 0; i < context->scrollContainerDatas.length; i++) { Clay__ScrollContainerDataInternal *mapping = Clay__ScrollContainerDataInternalArray_Get(&context->scrollContainerDatas, i); if (mapping->layoutElement == clipHashMapItem->layoutElement) { @@ -2036,8 +2163,8 @@ void Clay__CalculateFinalLayout(void) { context->treeNodeVisited.internalArray[dfsBuffer.length - 1] = true; Clay_BoundingBox currentElementBoundingBox = { currentElementTreeNode->position.x, currentElementTreeNode->position.y, currentElement->dimensions.width, currentElement->dimensions.height }; - if (Clay__ElementHasConfig(currentElement, CLAY__ELEMENT_CONFIG_TYPE_FLOATING_CONTAINER)) { - Clay_FloatingElementConfig *floatingElementConfig = Clay__FindElementConfigWithType(currentElement, CLAY__ELEMENT_CONFIG_TYPE_FLOATING_CONTAINER).floatingElementConfig; + if (Clay__ElementHasConfig(currentElement, CLAY__ELEMENT_CONFIG_TYPE_FLOATING)) { + Clay_FloatingElementConfig *floatingElementConfig = Clay__FindElementConfigWithType(currentElement, CLAY__ELEMENT_CONFIG_TYPE_FLOATING).floatingElementConfig; Clay_Dimensions expand = floatingElementConfig->expand; currentElementBoundingBox.x -= expand.width; currentElementBoundingBox.width += expand.width * 2; @@ -2047,8 +2174,8 @@ void Clay__CalculateFinalLayout(void) { Clay__ScrollContainerDataInternal *scrollContainerData = CLAY__NULL; // Apply scroll offsets to container - if (Clay__ElementHasConfig(currentElement, CLAY__ELEMENT_CONFIG_TYPE_SCROLL_CONTAINER)) { - Clay_ScrollElementConfig *scrollConfig = Clay__FindElementConfigWithType(currentElement, CLAY__ELEMENT_CONFIG_TYPE_SCROLL_CONTAINER).scrollElementConfig; + if (Clay__ElementHasConfig(currentElement, CLAY__ELEMENT_CONFIG_TYPE_SCROLL)) { + Clay_ScrollElementConfig *scrollConfig = Clay__FindElementConfigWithType(currentElement, CLAY__ELEMENT_CONFIG_TYPE_SCROLL).scrollElementConfig; // This linear scan could theoretically be slow under very strange conditions, but I can't imagine a real UI with more than a few 10's of scroll containers for (int32_t i = 0; i < context->scrollContainerDatas.length; i++) { @@ -2086,7 +2213,7 @@ void Clay__CalculateFinalLayout(void) { int32_t next = sortedConfigIndexes[i + 1]; Clay__ElementConfigType currentType = Clay__ElementConfigArraySlice_Get(¤tElement->elementConfigs, current)->type; Clay__ElementConfigType nextType = Clay__ElementConfigArraySlice_Get(¤tElement->elementConfigs, next)->type; - if (nextType == CLAY__ELEMENT_CONFIG_TYPE_SCROLL_CONTAINER || currentType == CLAY__ELEMENT_CONFIG_TYPE_BORDER_CONTAINER) { + if (nextType == CLAY__ELEMENT_CONFIG_TYPE_SCROLL || currentType == CLAY__ELEMENT_CONFIG_TYPE_BORDER) { sortedConfigIndexes[i] = next; sortedConfigIndexes[i + 1] = current; } @@ -2100,6 +2227,7 @@ void Clay__CalculateFinalLayout(void) { 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, }; @@ -2111,16 +2239,17 @@ void Clay__CalculateFinalLayout(void) { renderCommand.commandType = CLAY_RENDER_COMMAND_TYPE_RECTANGLE; break; } - case CLAY__ELEMENT_CONFIG_TYPE_BORDER_CONTAINER: { + case CLAY__ELEMENT_CONFIG_TYPE_SHARED: + case CLAY__ELEMENT_CONFIG_TYPE_BORDER: { shouldRender = false; break; } - case CLAY__ELEMENT_CONFIG_TYPE_FLOATING_CONTAINER: { + case CLAY__ELEMENT_CONFIG_TYPE_FLOATING: { renderCommand.commandType = CLAY_RENDER_COMMAND_TYPE_NONE; shouldRender = false; break; } - case CLAY__ELEMENT_CONFIG_TYPE_SCROLL_CONTAINER: { + case CLAY__ELEMENT_CONFIG_TYPE_SCROLL: { renderCommand.commandType = CLAY_RENDER_COMMAND_TYPE_SCISSOR_START; shouldRender = true; break; @@ -2149,7 +2278,7 @@ void Clay__CalculateFinalLayout(void) { Clay__AddRenderCommand(CLAY__INIT(Clay_RenderCommand) { .boundingBox = { currentElementBoundingBox.x, currentElementBoundingBox.y + yPosition, wrappedLine.dimensions.width, wrappedLine.dimensions.height }, // TODO width .config = configUnion, - .text = CLAY__INIT(Clay_StringSlice) { .length = wrappedLine.line.length, .chars = wrappedLine.line.chars, .baseChars = currentElement->childrenOrTextContent.textElementData->text.chars }, + .textOrSharedConfig = { .text = CLAY__INIT(Clay_StringSlice) { .length = wrappedLine.line.length, .chars = wrappedLine.line.chars, .baseChars = currentElement->childrenOrTextContent.textElementData->text.chars } }, .zIndex = root->zIndex, .id = Clay__HashNumber(lineIndex, currentElement->id).id, .commandType = CLAY_RENDER_COMMAND_TYPE_TEXT, @@ -2219,9 +2348,9 @@ void Clay__CalculateFinalLayout(void) { else { // DFS is returning upwards backwards bool closeScrollElement = false; - if (Clay__ElementHasConfig(currentElement, CLAY__ELEMENT_CONFIG_TYPE_SCROLL_CONTAINER)) { + if (Clay__ElementHasConfig(currentElement, CLAY__ELEMENT_CONFIG_TYPE_SCROLL)) { closeScrollElement = true; - Clay_ScrollElementConfig *scrollConfig = Clay__FindElementConfigWithType(currentElement, CLAY__ELEMENT_CONFIG_TYPE_SCROLL_CONTAINER).scrollElementConfig; + Clay_ScrollElementConfig *scrollConfig = Clay__FindElementConfigWithType(currentElement, CLAY__ELEMENT_CONFIG_TYPE_SCROLL).scrollElementConfig; for (int32_t i = 0; i < context->scrollContainerDatas.length; i++) { Clay__ScrollContainerDataInternal *mapping = Clay__ScrollContainerDataInternalArray_Get(&context->scrollContainerDatas, i); if (mapping->layoutElement == currentElement) { @@ -2235,16 +2364,18 @@ void Clay__CalculateFinalLayout(void) { } } - if (Clay__ElementHasConfig(currentElement, CLAY__ELEMENT_CONFIG_TYPE_BORDER_CONTAINER)) { + if (Clay__ElementHasConfig(currentElement, CLAY__ELEMENT_CONFIG_TYPE_BORDER)) { Clay_LayoutElementHashMapItem *currentElementData = Clay__GetHashMapItem(currentElement->id); Clay_BoundingBox currentElementBoundingBox = currentElementData->boundingBox; // 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 if (!Clay__ElementIsOffscreen(¤tElementBoundingBox)) { - Clay_BorderElementConfig *borderConfig = Clay__FindElementConfigWithType(currentElement, CLAY__ELEMENT_CONFIG_TYPE_BORDER_CONTAINER).borderElementConfig; + Clay_SharedElementConfig *sharedConfig = Clay__ElementHasConfig(currentElement, CLAY__ELEMENT_CONFIG_TYPE_SHARED) ? Clay__FindElementConfigWithType(currentElement, CLAY__ELEMENT_CONFIG_TYPE_SHARED).sharedElementConfig : &Clay_SharedElementConfig_DEFAULT; + Clay_BorderElementConfig *borderConfig = Clay__FindElementConfigWithType(currentElement, CLAY__ELEMENT_CONFIG_TYPE_BORDER).borderElementConfig; Clay_RenderCommand renderCommand = { .boundingBox = currentElementBoundingBox, .config = { .borderElementConfig = borderConfig }, + .textOrSharedConfig = { .sharedConfig = sharedConfig }, .id = Clay__RehashWithNumber(currentElement->id, 4), .commandType = CLAY_RENDER_COMMAND_TYPE_BORDER, }; @@ -2260,6 +2391,7 @@ void Clay__CalculateFinalLayout(void) { 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 }, .id = Clay__RehashWithNumber(currentElement->id, 5 + i), .commandType = CLAY_RENDER_COMMAND_TYPE_RECTANGLE, }); @@ -2273,6 +2405,7 @@ void Clay__CalculateFinalLayout(void) { 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 }, .id = Clay__RehashWithNumber(currentElement->id, 5 + i), .commandType = CLAY_RENDER_COMMAND_TYPE_RECTANGLE, }); @@ -2349,42 +2482,18 @@ void Clay__CalculateFinalLayout(void) { } } -void Clay__AttachId(Clay_ElementId elementId) { +Clay_ElementId Clay__AttachId(Clay_ElementId elementId) { Clay_Context* context = Clay_GetCurrentContext(); if (context->booleanWarnings.maxElementsExceeded) { - return; + return Clay_ElementId_DEFAULT; } Clay_LayoutElement *openLayoutElement = Clay__GetOpenLayoutElement(); openLayoutElement->id = elementId.id; Clay__AddHashMapItem(elementId, openLayoutElement); Clay__StringArray_Add(&context->layoutElementIdStrings, elementId.stringId); + return elementId; } -void Clay__AttachLayoutConfig(Clay_LayoutConfig *config) { - Clay_Context* context = Clay_GetCurrentContext(); - if (context->booleanWarnings.maxElementsExceeded) { - return; - } - Clay__GetOpenLayoutElement()->layoutConfig = config; -} -void Clay__AttachElementConfig(Clay_ElementConfigUnion config, Clay__ElementConfigType type) { - Clay_Context* context = Clay_GetCurrentContext(); - if (context->booleanWarnings.maxElementsExceeded) { - return; - } - Clay_LayoutElement *openLayoutElement = Clay__GetOpenLayoutElement(); - openLayoutElement->elementConfigs.length++; - Clay__ElementConfigArray_Add(&context->elementConfigBuffer, CLAY__INIT(Clay_ElementConfig) { .type = type, .config = config }); -} -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); } -Clay_CustomElementConfig * Clay__StoreCustomElementConfig(Clay_CustomElementConfig config) { return Clay_GetCurrentContext()->booleanWarnings.maxElementsExceeded ? &Clay_CustomElementConfig_DEFAULT : Clay__CustomElementConfigArray_Add(&Clay_GetCurrentContext()->customElementConfigs, config); } -Clay_ScrollElementConfig * Clay__StoreScrollElementConfig(Clay_ScrollElementConfig config) { return Clay_GetCurrentContext()->booleanWarnings.maxElementsExceeded ? &Clay_ScrollElementConfig_DEFAULT : Clay__ScrollElementConfigArray_Add(&Clay_GetCurrentContext()->scrollElementConfigs, config); } -Clay_BorderElementConfig * Clay__StoreBorderElementConfig(Clay_BorderElementConfig config) { return Clay_GetCurrentContext()->booleanWarnings.maxElementsExceeded ? &Clay_BorderElementConfig_DEFAULT : Clay__BorderElementConfigArray_Add(&Clay_GetCurrentContext()->borderElementConfigs, config); } - #pragma region DebugTools Clay_Color CLAY__DEBUGVIEW_COLOR_1 = {58, 56, 52, 255}; Clay_Color CLAY__DEBUGVIEW_COLOR_2 = {62, 60, 58, 255}; @@ -2407,9 +2516,9 @@ Clay__DebugElementConfigTypeLabelConfig Clay__DebugGetElementConfigTypeLabel(Cla case CLAY__ELEMENT_CONFIG_TYPE_RECTANGLE: return CLAY__INIT(Clay__DebugElementConfigTypeLabelConfig) { CLAY_STRING("Rectangle"), {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_CONTAINER: return CLAY__INIT(Clay__DebugElementConfigTypeLabelConfig) { CLAY_STRING("Floating"), {250,105,0,255} }; - case CLAY__ELEMENT_CONFIG_TYPE_SCROLL_CONTAINER: return CLAY__INIT(Clay__DebugElementConfigTypeLabelConfig) { CLAY_STRING("Scroll"), {242,196,90,255} }; - case CLAY__ELEMENT_CONFIG_TYPE_BORDER_CONTAINER: return CLAY__INIT(Clay__DebugElementConfigTypeLabelConfig) { CLAY_STRING("Border"), {108,91,123, 255} }; + case CLAY__ELEMENT_CONFIG_TYPE_FLOATING: return CLAY__INIT(Clay__DebugElementConfigTypeLabelConfig) { CLAY_STRING("Floating"), {250,105,0,255} }; + case CLAY__ELEMENT_CONFIG_TYPE_SCROLL: return CLAY__INIT(Clay__DebugElementConfigTypeLabelConfig) {CLAY_STRING("Scroll"), {242, 196, 90, 255} }; + case CLAY__ELEMENT_CONFIG_TYPE_BORDER: return CLAY__INIT(Clay__DebugElementConfigTypeLabelConfig) {CLAY_STRING("Border"), {108, 91, 123, 255} }; case CLAY__ELEMENT_CONFIG_TYPE_CUSTOM: return CLAY__INIT(Clay__DebugElementConfigTypeLabelConfig) { CLAY_STRING("Custom"), {11,72,107,255} }; default: break; } @@ -2436,8 +2545,8 @@ Clay__RenderDebugLayoutData Clay__RenderDebugLayoutElementsList(int32_t initialR Clay__int32_tArray_Add(&dfsBuffer, (int32_t)root->layoutElementIndex); context->treeNodeVisited.internalArray[0] = false; if (rootIndex > 0) { - CLAY(CLAY_IDI("Clay__DebugView_EmptyRowOuter", rootIndex), CLAY_LAYOUT({ .sizing = {.width = CLAY_SIZING_GROW(0)}, .padding = {CLAY__DEBUGVIEW_INDENT_WIDTH / 2, 0} })) { - CLAY(CLAY_IDI("Clay__DebugView_EmptyRow", rootIndex), CLAY_LAYOUT({ .sizing = { .width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_FIXED((float)CLAY__DEBUGVIEW_ROW_HEIGHT) }}), CLAY_BORDER({ .top = { .width = 1, .color = CLAY__DEBUGVIEW_COLOR_3 } })) {} + 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 } } }) {} } layoutData.rowCount++; } @@ -2467,29 +2576,30 @@ Clay__RenderDebugLayoutData Clay__RenderDebugLayoutElementsList(int32_t initialR if (context->debugSelectedElementId == currentElement->id) { layoutData.selectedElementRowIndex = layoutData.rowCount; } - CLAY(CLAY_IDI("Clay__DebugView_ElementOuter", currentElement->id), Clay__AttachLayoutConfig(&Clay__DebugView_ScrollViewItemLayoutConfig)) { + CLAY({ .id = CLAY_IDI("Clay__DebugView_ElementOuter", currentElement->id), .layout = Clay__DebugView_ScrollViewItemLayoutConfig }) { // Collapse icon / button if (!(Clay__ElementHasConfig(currentElement, CLAY__ELEMENT_CONFIG_TYPE_TEXT) || currentElement->childrenOrTextContent.children.length == 0)) { - CLAY(CLAY_IDI("Clay__DebugView_CollapseElement", currentElement->id), - CLAY_LAYOUT({ .sizing = {CLAY_SIZING_FIXED(16), CLAY_SIZING_FIXED(16)}, .childAlignment = { CLAY_ALIGN_X_CENTER, CLAY_ALIGN_Y_CENTER} }), - CLAY_BORDER_OUTSIDE_RADIUS(1, CLAY__DEBUGVIEW_COLOR_3, 4) - ) { + 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 }) + }) { 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(CLAY_LAYOUT({ .sizing = {CLAY_SIZING_FIXED(16), CLAY_SIZING_FIXED(16)}, .childAlignment = { CLAY_ALIGN_X_CENTER, CLAY_ALIGN_Y_CENTER } })) { - CLAY(CLAY_LAYOUT({ .sizing = {CLAY_SIZING_FIXED(8), CLAY_SIZING_FIXED(8)} }), CLAY_RECTANGLE({ .color = CLAY__DEBUGVIEW_COLOR_3, .cornerRadius = CLAY_CORNER_RADIUS(2) })) {} + 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) } }) {} } } // Collisions and offscreen info if (currentElementData) { if (currentElementData->debugData->collision) { - CLAY(CLAY_LAYOUT({ .padding = { 8, 8, 2, 2 } }), CLAY_BORDER_OUTSIDE_RADIUS(1, (CLAY__INIT(Clay_Color){177, 147, 8, 255}), 4)) { + CLAY({ .layout = { .padding = { 8, 8, 2, 2 } }, .border = CLAY_BORDER_OUTSIDE({ 1, (CLAY__INIT(Clay_Color){177, 147, 8, 255}) }) }) { CLAY_TEXT(CLAY_STRING("Duplicate ID"), CLAY_TEXT_CONFIG({ .textColor = CLAY__DEBUGVIEW_COLOR_3, .fontSize = 16 })); } } if (offscreen) { - CLAY(CLAY_LAYOUT({ .padding = { 8, 8, 2, 2 } }), CLAY_BORDER_OUTSIDE_RADIUS(1, CLAY__DEBUGVIEW_COLOR_3, 4)) { + CLAY({ .layout = { .padding = { 8, 8, 2, 2 } }, .border = CLAY_BORDER_OUTSIDE({ 1, CLAY__DEBUGVIEW_COLOR_3 }) }) { CLAY_TEXT(CLAY_STRING("Offscreen"), CLAY_TEXT_CONFIG({ .textColor = CLAY__DEBUGVIEW_COLOR_3, .fontSize = 16 })); } } @@ -2503,7 +2613,7 @@ Clay__RenderDebugLayoutData Clay__RenderDebugLayoutElementsList(int32_t initialR Clay__DebugElementConfigTypeLabelConfig config = Clay__DebugGetElementConfigTypeLabel(elementConfig->type); Clay_Color backgroundColor = config.color; backgroundColor.a = 90; - CLAY(CLAY_LAYOUT({ .padding = { 8, 8, 2, 2 } }), CLAY_RECTANGLE({ .color = backgroundColor, .cornerRadius = CLAY_CORNER_RADIUS(4) }), CLAY_BORDER_OUTSIDE_RADIUS(1, config.color, 4)) { + CLAY({ .layout = { .padding = { 8, 8, 2, 2 } }, .rectangle = { .color = backgroundColor }, .border = CLAY_BORDER_OUTSIDE({ 1, config.color }), .shared = { .cornerRadius = CLAY_CORNER_RADIUS(4) } }) { CLAY_TEXT(config.label, CLAY_TEXT_CONFIG({ .textColor = offscreen ? CLAY__DEBUGVIEW_COLOR_3 : CLAY__DEBUGVIEW_COLOR_4, .fontSize = 16 })); } } @@ -2514,8 +2624,8 @@ Clay__RenderDebugLayoutData Clay__RenderDebugLayoutElementsList(int32_t initialR layoutData.rowCount++; Clay__TextElementData *textElementData = currentElement->childrenOrTextContent.textElementData; Clay_TextElementConfig *rawTextConfig = offscreen ? CLAY_TEXT_CONFIG({ .textColor = CLAY__DEBUGVIEW_COLOR_3, .fontSize = 16 }) : &Clay__DebugView_TextNameConfig; - CLAY(CLAY_LAYOUT({ .sizing = { .height = CLAY_SIZING_FIXED(CLAY__DEBUGVIEW_ROW_HEIGHT)}, .childAlignment = { .y = CLAY_ALIGN_Y_CENTER } }), CLAY_RECTANGLE(CLAY__DEFAULT_STRUCT)) { - CLAY(CLAY_LAYOUT({ .sizing = {CLAY_SIZING_FIXED(CLAY__DEBUGVIEW_INDENT_WIDTH + 16), CLAY__DEFAULT_STRUCT} })) {} + CLAY({ .layout = { .sizing = { .height = CLAY_SIZING_FIXED(CLAY__DEBUGVIEW_ROW_HEIGHT)}, .childAlignment = { .y = CLAY_ALIGN_Y_CENTER } }, .rectangle = CLAY__DEFAULT_STRUCT }) { + CLAY({ .layout = { .sizing = {CLAY_SIZING_FIXED(CLAY__DEBUGVIEW_INDENT_WIDTH + 16), CLAY__DEFAULT_STRUCT} } }) {} CLAY_TEXT(CLAY_STRING("\""), rawTextConfig); CLAY_TEXT(textElementData->text.length > 40 ? (CLAY__INIT(Clay_String) { .length = 40, .chars = textElementData->text.chars }) : textElementData->text, rawTextConfig); if (textElementData->text.length > 40) { @@ -2525,15 +2635,11 @@ Clay__RenderDebugLayoutData Clay__RenderDebugLayoutElementsList(int32_t initialR } } else if (currentElement->childrenOrTextContent.children.length > 0) { Clay__OpenElement(); - CLAY_LAYOUT({ .padding = { 8 } }); - Clay__ElementPostConfiguration(); + Clay__ConfigureOpenElement(CLAY__INIT(Clay_ElementDeclaration) { .layout = { .padding = { 8 } } }); Clay__OpenElement(); - CLAY_BORDER({ .left = { .width = 1, .color = CLAY__DEBUGVIEW_COLOR_3 }}); - Clay__ElementPostConfiguration(); - CLAY(CLAY_LAYOUT({ .sizing = {CLAY_SIZING_FIXED( CLAY__DEBUGVIEW_INDENT_WIDTH), CLAY__DEFAULT_STRUCT}, .childAlignment = { .x = CLAY_ALIGN_X_RIGHT } })) {} + Clay__ConfigureOpenElement(CLAY__INIT(Clay_ElementDeclaration) { .layout = { .padding = { .left = CLAY__DEBUGVIEW_INDENT_WIDTH }}, .border = { .left = { .width = 1, .color = CLAY__DEBUGVIEW_COLOR_3 }}}); Clay__OpenElement(); - CLAY_LAYOUT({ .layoutDirection = CLAY_TOP_TO_BOTTOM }); - Clay__ElementPostConfiguration(); + Clay__ConfigureOpenElement(CLAY__INIT(Clay_ElementDeclaration) { .layout = { .layoutDirection = CLAY_TOP_TO_BOTTOM } }); } layoutData.rowCount++; @@ -2559,8 +2665,8 @@ Clay__RenderDebugLayoutData Clay__RenderDebugLayoutElementsList(int32_t initialR } if (highlightedElementId) { - CLAY(CLAY_ID("Clay__DebugView_ElementHighlight"), CLAY_LAYOUT({ .sizing = {CLAY_SIZING_GROW(0), CLAY_SIZING_GROW(0)} }), CLAY_FLOATING({ .zIndex = 65535, .parentId = highlightedElementId })) { - CLAY(CLAY_ID("Clay__DebugView_ElementHighlightRectangle"), CLAY_LAYOUT({ .sizing = {CLAY_SIZING_GROW(0), CLAY_SIZING_GROW(0)} }), CLAY_RECTANGLE({.color = Clay__debugViewHighlightColor })) {} + CLAY({ .id = CLAY_ID("Clay__DebugView_ElementHighlight"), .layout = { .sizing = {CLAY_SIZING_GROW(0), CLAY_SIZING_GROW(0)} }, .floating = { .zIndex = 65535, .parentId = highlightedElementId } }) { + CLAY({ .id = CLAY_ID("Clay__DebugView_ElementHighlightRectangle"), .layout = { .sizing = {CLAY_SIZING_GROW(0), CLAY_SIZING_GROW(0)} }, .rectangle = {.color = Clay__debugViewHighlightColor } }) {} } } return layoutData; @@ -2595,17 +2701,17 @@ void Clay__RenderDebugViewElementConfigHeader(Clay_String elementId, Clay__Eleme Clay__DebugElementConfigTypeLabelConfig config = Clay__DebugGetElementConfigTypeLabel(type); Clay_Color backgroundColor = config.color; backgroundColor.a = 90; - CLAY(CLAY_LAYOUT({ .sizing = { CLAY_SIZING_GROW(0)}, .padding = CLAY_PADDING_ALL(CLAY__DEBUGVIEW_OUTER_PADDING), .childAlignment = { .y = CLAY_ALIGN_Y_CENTER } })) { - CLAY(CLAY_LAYOUT({ .padding = { 8, 8, 2, 2 } }), CLAY_RECTANGLE({ .color = backgroundColor, .cornerRadius = CLAY_CORNER_RADIUS(4) }), CLAY_BORDER_OUTSIDE_RADIUS(1, config.color, 4)) { + 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_TEXT(config.label, CLAY_TEXT_CONFIG({ .textColor = CLAY__DEBUGVIEW_COLOR_4, .fontSize = 16 })); } - CLAY(CLAY_LAYOUT({ .sizing = { .width = CLAY_SIZING_GROW(0) } })) {} + CLAY({ .layout = { .sizing = { .width = CLAY_SIZING_GROW(0) } } }) {} CLAY_TEXT(elementId, CLAY_TEXT_CONFIG({ .textColor = CLAY__DEBUGVIEW_COLOR_3, .fontSize = 16, .wrapMode = CLAY_TEXT_WRAP_NONE })); } } void Clay__RenderDebugViewColor(Clay_Color color, Clay_TextElementConfig *textConfig) { - CLAY(CLAY_LAYOUT({ .childAlignment = {.y = CLAY_ALIGN_Y_CENTER} })) { + CLAY({ .layout = { .childAlignment = {.y = CLAY_ALIGN_Y_CENTER} } }) { CLAY_TEXT(CLAY_STRING("{ r: "), textConfig); CLAY_TEXT(Clay__IntToString(color.r), textConfig); CLAY_TEXT(CLAY_STRING(", g: "), textConfig); @@ -2615,15 +2721,15 @@ void Clay__RenderDebugViewColor(Clay_Color color, Clay_TextElementConfig *textCo CLAY_TEXT(CLAY_STRING(", a: "), textConfig); CLAY_TEXT(Clay__IntToString(color.a), textConfig); CLAY_TEXT(CLAY_STRING(" }"), textConfig); - CLAY(CLAY_LAYOUT({ .sizing = { CLAY_SIZING_FIXED(10), CLAY__DEFAULT_STRUCT } })) {} - CLAY(CLAY_LAYOUT({ .sizing = { CLAY_SIZING_FIXED(CLAY__DEBUGVIEW_ROW_HEIGHT - 8), CLAY_SIZING_FIXED(CLAY__DEBUGVIEW_ROW_HEIGHT - 8)} }), CLAY_BORDER_OUTSIDE_RADIUS(1, CLAY__DEBUGVIEW_COLOR_4, 4)) { - CLAY(CLAY_LAYOUT({ .sizing = { CLAY_SIZING_FIXED(CLAY__DEBUGVIEW_ROW_HEIGHT - 8), CLAY_SIZING_FIXED(CLAY__DEBUGVIEW_ROW_HEIGHT - 8)} }), CLAY_RECTANGLE({ .color = color, .cornerRadius = CLAY_CORNER_RADIUS(4) })) {} + CLAY({ .layout = { .sizing = { CLAY_SIZING_FIXED(10), CLAY__DEFAULT_STRUCT } } }) {} + CLAY({ .layout = { .sizing = { CLAY_SIZING_FIXED(CLAY__DEBUGVIEW_ROW_HEIGHT - 8), CLAY_SIZING_FIXED(CLAY__DEBUGVIEW_ROW_HEIGHT - 8)} }, .border = CLAY_BORDER_OUTSIDE({ 1, CLAY__DEBUGVIEW_COLOR_4 }) }) { + CLAY({ .layout = { .sizing = { CLAY_SIZING_FIXED(CLAY__DEBUGVIEW_ROW_HEIGHT - 8), CLAY_SIZING_FIXED(CLAY__DEBUGVIEW_ROW_HEIGHT - 8)} }, .rectangle = { .color = color }, .shared = { .cornerRadius = CLAY_CORNER_RADIUS(4) } }) {} } } } void Clay__RenderDebugViewCornerRadius(Clay_CornerRadius cornerRadius, Clay_TextElementConfig *textConfig) { - CLAY(CLAY_LAYOUT({ .childAlignment = {.y = CLAY_ALIGN_Y_CENTER} })) { + CLAY({ .layout = { .childAlignment = {.y = CLAY_ALIGN_Y_CENTER} } }) { CLAY_TEXT(CLAY_STRING("{ topLeft: "), textConfig); CLAY_TEXT(Clay__IntToString(cornerRadius.topLeft), textConfig); CLAY_TEXT(CLAY_STRING(", topRight: "), textConfig); @@ -2638,7 +2744,7 @@ void Clay__RenderDebugViewCornerRadius(Clay_CornerRadius cornerRadius, Clay_Text void Clay__RenderDebugViewBorder(int32_t index, Clay_Border border, Clay_TextElementConfig *textConfig) { (void) index; - CLAY(CLAY_LAYOUT({ .childAlignment = {.y = CLAY_ALIGN_Y_CENTER} })) { + 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); @@ -2693,35 +2799,36 @@ void Clay__RenderDebugView(void) { highlightedRow = -1; } Clay__RenderDebugLayoutData layoutData = CLAY__DEFAULT_STRUCT; - CLAY(CLAY_ID("Clay__DebugView"), - CLAY_FLOATING({ .zIndex = 65000, .parentId = Clay__HashString(CLAY_STRING("Clay__RootContainer"), 0, 0).id, .attachment = { .element = CLAY_ATTACH_POINT_LEFT_CENTER, .parent = CLAY_ATTACH_POINT_RIGHT_CENTER }}), - CLAY_LAYOUT({ .sizing = { CLAY_SIZING_FIXED((float)Clay__debugViewWidth) , CLAY_SIZING_FIXED(context->layoutDimensions.height) }, .layoutDirection = CLAY_TOP_TO_BOTTOM }), - CLAY_BORDER({ .bottom = { .width = 1, .color = CLAY__DEBUGVIEW_COLOR_3 }}) - ) { - CLAY(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} }), CLAY_RECTANGLE({ .color = CLAY__DEBUGVIEW_COLOR_2 })) { + 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 = { .zIndex = 65000, .parentId = Clay__HashString(CLAY_STRING("Clay__RootContainer"), 0, 0).id, .attachment = { .element = CLAY_ATTACH_POINT_LEFT_CENTER, .parent = CLAY_ATTACH_POINT_RIGHT_CENTER }}, + .border = { .bottom = { .width = 1, .color = CLAY__DEBUGVIEW_COLOR_3 }} + }) { + 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_TEXT(CLAY_STRING("Clay Debug Tools"), infoTextConfig); - CLAY(CLAY_LAYOUT({ .sizing = { CLAY_SIZING_GROW(0) } })) {} + CLAY({ .layout = { .sizing = { CLAY_SIZING_GROW(0) } } }) {} // Close button - CLAY(CLAY_BORDER_OUTSIDE_RADIUS(1, (CLAY__INIT(Clay_Color){217,91,67,255}), 4), - 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} }), - CLAY_RECTANGLE({ .color = {217,91,67,80} }), - Clay_OnHover(HandleDebugViewCloseButtonInteraction, 0) - ) { + 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}) }), + }) { + Clay_OnHover(HandleDebugViewCloseButtonInteraction, 0); CLAY_TEXT(CLAY_STRING("x"), CLAY_TEXT_CONFIG({ .textColor = CLAY__DEBUGVIEW_COLOR_4, .fontSize = 16 })); } } - CLAY(CLAY_LAYOUT({ .sizing = {CLAY_SIZING_GROW(0), CLAY_SIZING_FIXED(1)} }), CLAY_RECTANGLE({ .color = CLAY__DEBUGVIEW_COLOR_3 })) {} - CLAY(Clay__AttachId(scrollId), CLAY_LAYOUT({ .sizing = {CLAY_SIZING_GROW(0), CLAY_SIZING_GROW(0)} }), CLAY_SCROLL({ .horizontal = true, .vertical = true })) { - CLAY(CLAY_LAYOUT({ .sizing = {CLAY_SIZING_GROW(0), CLAY_SIZING_GROW(0)}, .layoutDirection = CLAY_TOP_TO_BOTTOM }), CLAY_RECTANGLE({ .color = ((initialElementsLength + initialRootsLength) & 1) == 0 ? CLAY__DEBUGVIEW_COLOR_2 : CLAY__DEBUGVIEW_COLOR_1 })) { + CLAY({ .layout = { .sizing = {CLAY_SIZING_GROW(0), CLAY_SIZING_FIXED(1)} }, .rectangle = { .color = 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_ElementId panelContentsId = Clay__HashString(CLAY_STRING("Clay__DebugViewPaneOuter"), 0, 0); // Element list - CLAY(Clay__AttachId(panelContentsId), CLAY_LAYOUT({ .sizing = {CLAY_SIZING_GROW(0), CLAY_SIZING_GROW(0)} }), CLAY_FLOATING({ .zIndex = 65001, .pointerCaptureMode = CLAY_POINTER_CAPTURE_MODE_PASSTHROUGH })) { - CLAY(CLAY_LAYOUT({ .sizing = {CLAY_SIZING_GROW(0), CLAY_SIZING_GROW(0)}, .padding = { CLAY__DEBUGVIEW_OUTER_PADDING, CLAY__DEBUGVIEW_OUTER_PADDING }, .layoutDirection = CLAY_TOP_TO_BOTTOM })) { + CLAY({ .id = panelContentsId, .layout = { .sizing = {CLAY_SIZING_GROW(0), CLAY_SIZING_GROW(0)} }, .floating = { .zIndex = 65001, .pointerCaptureMode = CLAY_POINTER_CAPTURE_MODE_PASSTHROUGH } }) { + CLAY({ .layout = { .sizing = {CLAY_SIZING_GROW(0), CLAY_SIZING_GROW(0)}, .padding = { CLAY__DEBUGVIEW_OUTER_PADDING, CLAY__DEBUGVIEW_OUTER_PADDING }, .layoutDirection = CLAY_TOP_TO_BOTTOM } }) { layoutData = Clay__RenderDebugLayoutElementsList((int32_t)initialRootsLength, highlightedRow); } } float contentWidth = Clay__GetHashMapItem(panelContentsId.id)->layoutElement->dimensions.width; - CLAY(CLAY_LAYOUT({ .sizing = {CLAY_SIZING_FIXED(contentWidth), CLAY__DEFAULT_STRUCT}, .layoutDirection = CLAY_TOP_TO_BOTTOM })) {} + CLAY({ .layout = { .sizing = {CLAY_SIZING_FIXED(contentWidth) }, .layoutDirection = CLAY_TOP_TO_BOTTOM } }) {} for (int32_t i = 0; i < layoutData.rowCount; i++) { Clay_Color rowColor = (i & 1) == 0 ? CLAY__DEBUGVIEW_COLOR_2 : CLAY__DEBUGVIEW_COLOR_1; if (i == layoutData.selectedElementRowIndex) { @@ -2732,22 +2839,22 @@ void Clay__RenderDebugView(void) { rowColor.g *= 1.25f; rowColor.b *= 1.25f; } - CLAY(CLAY_LAYOUT({ .sizing = {CLAY_SIZING_GROW(0), CLAY_SIZING_FIXED(CLAY__DEBUGVIEW_ROW_HEIGHT)}, .layoutDirection = CLAY_TOP_TO_BOTTOM }), CLAY_RECTANGLE({ .color = rowColor })) {} + CLAY({ .layout = { .sizing = {CLAY_SIZING_GROW(0), CLAY_SIZING_FIXED(CLAY__DEBUGVIEW_ROW_HEIGHT)}, .layoutDirection = CLAY_TOP_TO_BOTTOM }, .rectangle = { .color = rowColor } }) {} } } } - CLAY(CLAY_LAYOUT({ .sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_FIXED(1)} }), CLAY_RECTANGLE({ .color = CLAY__DEBUGVIEW_COLOR_3 })) {} + CLAY({ .layout = { .sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_FIXED(1)} }, .rectangle = { .color = CLAY__DEBUGVIEW_COLOR_3 } }) {} if (context->debugSelectedElementId != 0) { Clay_LayoutElementHashMapItem *selectedItem = Clay__GetHashMapItem(context->debugSelectedElementId); - CLAY( - CLAY_SCROLL({ .vertical = true }), - CLAY_LAYOUT({ .sizing = {CLAY_SIZING_GROW(0), CLAY_SIZING_FIXED(300)}, .layoutDirection = CLAY_TOP_TO_BOTTOM }), - CLAY_RECTANGLE({ .color = CLAY__DEBUGVIEW_COLOR_2 }), - CLAY_BORDER({ .betweenChildren = { .width = 1, .color = CLAY__DEBUGVIEW_COLOR_3 }}) - ) { - CLAY(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({ + .layout = { .sizing = {CLAY_SIZING_GROW(0), CLAY_SIZING_FIXED(300)}, .layoutDirection = CLAY_TOP_TO_BOTTOM }, + .rectangle = { .color = CLAY__DEBUGVIEW_COLOR_2 }, + .scroll = { .vertical = true }, + .border = { .betweenChildren = { .width = 1, .color = CLAY__DEBUGVIEW_COLOR_3 }} + }) { + 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); - CLAY(CLAY_LAYOUT({ .sizing = { CLAY_SIZING_GROW(0) } })) {} + CLAY({ .layout = { .sizing = { CLAY_SIZING_GROW(0) } } }) {} if (selectedItem->elementId.stringId.length != 0) { CLAY_TEXT(selectedItem->elementId.stringId, infoTitleConfig); if (selectedItem->elementId.offset != 0) { @@ -2759,10 +2866,10 @@ void Clay__RenderDebugView(void) { } Clay_Padding attributeConfigPadding = {CLAY__DEBUGVIEW_OUTER_PADDING, CLAY__DEBUGVIEW_OUTER_PADDING, 8, 8}; // Clay_LayoutConfig debug info - CLAY(CLAY_LAYOUT({ .padding = attributeConfigPadding, .childGap = 8, .layoutDirection = CLAY_TOP_TO_BOTTOM })) { + CLAY({ .layout = { .padding = attributeConfigPadding, .childGap = 8, .layoutDirection = CLAY_TOP_TO_BOTTOM } }) { // .boundingBox CLAY_TEXT(CLAY_STRING("Bounding Box"), infoTitleConfig); - CLAY(CLAY_LAYOUT(CLAY__DEFAULT_STRUCT)) { + CLAY({}) { CLAY_TEXT(CLAY_STRING("{ x: "), infoTextConfig); CLAY_TEXT(Clay__IntToString(selectedItem->boundingBox.x), infoTextConfig); CLAY_TEXT(CLAY_STRING(", y: "), infoTextConfig); @@ -2779,17 +2886,17 @@ void Clay__RenderDebugView(void) { CLAY_TEXT(layoutConfig->layoutDirection == CLAY_TOP_TO_BOTTOM ? CLAY_STRING("TOP_TO_BOTTOM") : CLAY_STRING("LEFT_TO_RIGHT"), infoTextConfig); // .sizing CLAY_TEXT(CLAY_STRING("Sizing"), infoTitleConfig); - CLAY(CLAY_LAYOUT(CLAY__DEFAULT_STRUCT)) { + CLAY({}) { CLAY_TEXT(CLAY_STRING("width: "), infoTextConfig); Clay__RenderDebugLayoutSizing(layoutConfig->sizing.width, infoTextConfig); } - CLAY(CLAY_LAYOUT(CLAY__DEFAULT_STRUCT)) { + CLAY({}) { CLAY_TEXT(CLAY_STRING("height: "), infoTextConfig); Clay__RenderDebugLayoutSizing(layoutConfig->sizing.height, infoTextConfig); } // .padding CLAY_TEXT(CLAY_STRING("Padding"), infoTitleConfig); - CLAY(CLAY_ID("Clay__DebugViewElementInfoPadding")) { + CLAY({ .id = CLAY_ID("Clay__DebugViewElementInfoPadding") }) { CLAY_TEXT(CLAY_STRING("{ left: "), infoTextConfig); CLAY_TEXT(Clay__IntToString(layoutConfig->padding.left), infoTextConfig); CLAY_TEXT(CLAY_STRING(", right: "), infoTextConfig); @@ -2805,7 +2912,7 @@ void Clay__RenderDebugView(void) { CLAY_TEXT(Clay__IntToString(layoutConfig->childGap), infoTextConfig); // .childAlignment CLAY_TEXT(CLAY_STRING("Child Alignment"), infoTitleConfig); - CLAY(CLAY_LAYOUT(CLAY__DEFAULT_STRUCT)) { + CLAY({ .layout = CLAY__DEFAULT_STRUCT }) { CLAY_TEXT(CLAY_STRING("{ x: "), infoTextConfig); Clay_String alignX = CLAY_STRING("LEFT"); if (layoutConfig->childAlignment.x == CLAY_ALIGN_X_CENTER) { @@ -2829,21 +2936,28 @@ void Clay__RenderDebugView(void) { Clay_ElementConfig *elementConfig = Clay__ElementConfigArraySlice_Get(&selectedItem->layoutElement->elementConfigs, elementConfigIndex); Clay__RenderDebugViewElementConfigHeader(selectedItem->elementId.stringId, elementConfig->type); switch (elementConfig->type) { + case CLAY__ELEMENT_CONFIG_TYPE_SHARED: { + Clay_SharedElementConfig *sharedConfig = elementConfig->config.sharedElementConfig; + CLAY({ .layout = { .padding = attributeConfigPadding, .childGap = 8, .layoutDirection = CLAY_TOP_TO_BOTTOM }}) { + // .cornerRadius + CLAY_TEXT(CLAY_STRING("Color"), infoTitleConfig); + Clay__RenderDebugViewCornerRadius(sharedConfig->cornerRadius, infoTextConfig); + } + break; + break; + } case CLAY__ELEMENT_CONFIG_TYPE_RECTANGLE: { Clay_RectangleElementConfig *rectangleConfig = elementConfig->config.rectangleElementConfig; - CLAY(CLAY_LAYOUT({ .padding = attributeConfigPadding, .childGap = 8, .layoutDirection = CLAY_TOP_TO_BOTTOM })) { + CLAY({ .layout = { .padding = attributeConfigPadding, .childGap = 8, .layoutDirection = CLAY_TOP_TO_BOTTOM }}) { // .color CLAY_TEXT(CLAY_STRING("Color"), infoTitleConfig); Clay__RenderDebugViewColor(rectangleConfig->color, infoTextConfig); - // .cornerRadius - CLAY_TEXT(CLAY_STRING("Corner Radius"), infoTitleConfig); - Clay__RenderDebugViewCornerRadius(rectangleConfig->cornerRadius, infoTextConfig); } break; } case CLAY__ELEMENT_CONFIG_TYPE_TEXT: { Clay_TextElementConfig *textConfig = elementConfig->config.textElementConfig; - CLAY(CLAY_LAYOUT({ .padding = attributeConfigPadding, .childGap = 8, .layoutDirection = CLAY_TOP_TO_BOTTOM })) { + CLAY({ .layout = { .padding = attributeConfigPadding, .childGap = 8, .layoutDirection = CLAY_TOP_TO_BOTTOM } }) { // .fontSize CLAY_TEXT(CLAY_STRING("Font Size"), infoTitleConfig); CLAY_TEXT(Clay__IntToString(textConfig->fontSize), infoTextConfig); @@ -2873,10 +2987,10 @@ void Clay__RenderDebugView(void) { } case CLAY__ELEMENT_CONFIG_TYPE_IMAGE: { Clay_ImageElementConfig *imageConfig = elementConfig->config.imageElementConfig; - CLAY(CLAY_ID("Clay__DebugViewElementInfoImageBody"), CLAY_LAYOUT({ .padding = attributeConfigPadding, .childGap = 8, .layoutDirection = CLAY_TOP_TO_BOTTOM })) { + CLAY({ .id = CLAY_ID("Clay__DebugViewElementInfoImageBody"), .layout = { .padding = attributeConfigPadding, .childGap = 8, .layoutDirection = CLAY_TOP_TO_BOTTOM } }) { // .sourceDimensions CLAY_TEXT(CLAY_STRING("Source Dimensions"), infoTitleConfig); - CLAY(CLAY_ID("Clay__DebugViewElementInfoImageDimensions")) { + CLAY({ .id = CLAY_ID("Clay__DebugViewElementInfoImageDimensions") }) { CLAY_TEXT(CLAY_STRING("{ width: "), infoTextConfig); CLAY_TEXT(Clay__IntToString(imageConfig->sourceDimensions.width), infoTextConfig); CLAY_TEXT(CLAY_STRING(", height: "), infoTextConfig); @@ -2885,13 +2999,13 @@ void Clay__RenderDebugView(void) { } // Image Preview CLAY_TEXT(CLAY_STRING("Preview"), infoTitleConfig); - CLAY(CLAY_LAYOUT({ .sizing = { CLAY_SIZING_GROW(0, imageConfig->sourceDimensions.width) }}), Clay__AttachElementConfig(CLAY__INIT(Clay_ElementConfigUnion) { .imageElementConfig = imageConfig }, CLAY__ELEMENT_CONFIG_TYPE_IMAGE)) {} + CLAY({ .layout = { .sizing = { CLAY_SIZING_GROW(0, imageConfig->sourceDimensions.width) }}, .image = { imageConfig } }) {} } break; } - case CLAY__ELEMENT_CONFIG_TYPE_SCROLL_CONTAINER: { + case CLAY__ELEMENT_CONFIG_TYPE_SCROLL: { Clay_ScrollElementConfig *scrollConfig = elementConfig->config.scrollElementConfig; - CLAY(CLAY_LAYOUT({ .padding = attributeConfigPadding, .childGap = 8, .layoutDirection = CLAY_TOP_TO_BOTTOM })) { + CLAY({ .layout = { .padding = attributeConfigPadding, .childGap = 8, .layoutDirection = CLAY_TOP_TO_BOTTOM } }) { // .vertical CLAY_TEXT(CLAY_STRING("Vertical"), infoTitleConfig); CLAY_TEXT(scrollConfig->vertical ? CLAY_STRING("true") : CLAY_STRING("false") , infoTextConfig); @@ -2901,12 +3015,12 @@ void Clay__RenderDebugView(void) { } break; } - case CLAY__ELEMENT_CONFIG_TYPE_FLOATING_CONTAINER: { + case CLAY__ELEMENT_CONFIG_TYPE_FLOATING: { Clay_FloatingElementConfig *floatingConfig = elementConfig->config.floatingElementConfig; - CLAY(CLAY_LAYOUT({ .padding = attributeConfigPadding, .childGap = 8, .layoutDirection = CLAY_TOP_TO_BOTTOM })) { + CLAY({ .layout = { .padding = attributeConfigPadding, .childGap = 8, .layoutDirection = CLAY_TOP_TO_BOTTOM } }) { // .offset CLAY_TEXT(CLAY_STRING("Offset"), infoTitleConfig); - CLAY(CLAY_LAYOUT(CLAY__DEFAULT_STRUCT)) { + CLAY({}) { CLAY_TEXT(CLAY_STRING("{ x: "), infoTextConfig); CLAY_TEXT(Clay__IntToString(floatingConfig->offset.x), infoTextConfig); CLAY_TEXT(CLAY_STRING(", y: "), infoTextConfig); @@ -2915,7 +3029,7 @@ void Clay__RenderDebugView(void) { } // .expand CLAY_TEXT(CLAY_STRING("Expand"), infoTitleConfig); - CLAY(CLAY_LAYOUT(CLAY__DEFAULT_STRUCT)) { + CLAY({}) { CLAY_TEXT(CLAY_STRING("{ width: "), infoTextConfig); CLAY_TEXT(Clay__IntToString(floatingConfig->expand.width), infoTextConfig); CLAY_TEXT(CLAY_STRING(", height: "), infoTextConfig); @@ -2932,9 +3046,9 @@ void Clay__RenderDebugView(void) { } break; } - case CLAY__ELEMENT_CONFIG_TYPE_BORDER_CONTAINER: { + case CLAY__ELEMENT_CONFIG_TYPE_BORDER: { Clay_BorderElementConfig *borderConfig = elementConfig->config.borderElementConfig; - CLAY(CLAY_ID("Clay__DebugViewElementInfoBorderBody"), CLAY_LAYOUT({ .padding = attributeConfigPadding, .childGap = 8, .layoutDirection = CLAY_TOP_TO_BOTTOM })) { + 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); @@ -2950,9 +3064,6 @@ void Clay__RenderDebugView(void) { // .betweenChildren CLAY_TEXT(CLAY_STRING("Border Between Children"), infoTitleConfig); Clay__RenderDebugViewBorder(5, borderConfig->betweenChildren, infoTextConfig); - // .cornerRadius - CLAY_TEXT(CLAY_STRING("Corner Radius"), infoTitleConfig); - Clay__RenderDebugViewCornerRadius(borderConfig->cornerRadius, infoTextConfig); } break; } @@ -2962,16 +3073,16 @@ void Clay__RenderDebugView(void) { } } } else { - CLAY(CLAY_ID("Clay__DebugViewWarningsScrollPane"), CLAY_LAYOUT({ .sizing = {CLAY_SIZING_GROW(0), CLAY_SIZING_FIXED(300)}, .childGap = 6, .layoutDirection = CLAY_TOP_TO_BOTTOM }), CLAY_SCROLL({ .horizontal = true, .vertical = true }), CLAY_RECTANGLE({ .color = CLAY__DEBUGVIEW_COLOR_2 })) { + 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_TextElementConfig *warningConfig = CLAY_TEXT_CONFIG({ .textColor = CLAY__DEBUGVIEW_COLOR_4, .fontSize = 16, .wrapMode = CLAY_TEXT_WRAP_NONE }); - CLAY(CLAY_ID("Clay__DebugViewWarningItemHeader"), CLAY_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({ .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(CLAY_ID("Clay__DebugViewWarningsTopBorder"), CLAY_LAYOUT({ .sizing = { .width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_FIXED(1)} }), CLAY_RECTANGLE({ .color = {200, 200, 200, 255} })) {} + CLAY({ .id = CLAY_ID("Clay__DebugViewWarningsTopBorder"), .layout = { .sizing = { .width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_FIXED(1)} }, .rectangle = { .color = {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]; - CLAY(CLAY_IDI("Clay__DebugViewWarningItem", i), CLAY_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({ .id = CLAY_IDI("Clay__DebugViewWarningItem", i), .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(warning.baseMessage, warningConfig); if (warning.dynamicMessage.length > 0) { CLAY_TEXT(warning.dynamicMessage, warningConfig); @@ -3155,8 +3266,8 @@ void Clay_SetPointerState(Clay_Vector2 position, bool isPointerDown) { } Clay_LayoutElement *rootElement = Clay_LayoutElementArray_Get(&context->layoutElements, root->layoutElementIndex); - if (found && Clay__ElementHasConfig(rootElement, CLAY__ELEMENT_CONFIG_TYPE_FLOATING_CONTAINER) && - Clay__FindElementConfigWithType(rootElement, CLAY__ELEMENT_CONFIG_TYPE_FLOATING_CONTAINER).floatingElementConfig->pointerCaptureMode == CLAY_POINTER_CAPTURE_MODE_CAPTURE) { + if (found && Clay__ElementHasConfig(rootElement, CLAY__ELEMENT_CONFIG_TYPE_FLOATING) && + Clay__FindElementConfigWithType(rootElement, CLAY__ELEMENT_CONFIG_TYPE_FLOATING).floatingElementConfig->pointerCaptureMode == CLAY_POINTER_CAPTURE_MODE_CAPTURE) { break; } } @@ -3277,7 +3388,7 @@ void Clay_UpdateScrollContainers(bool enableDragScrolling, Clay_Vector2 scrollDe if (highestPriorityElementIndex > -1 && highestPriorityScrollData) { Clay_LayoutElement *scrollElement = highestPriorityScrollData->layoutElement; - Clay_ScrollElementConfig *scrollConfig = Clay__FindElementConfigWithType(scrollElement, CLAY__ELEMENT_CONFIG_TYPE_SCROLL_CONTAINER).scrollElementConfig; + Clay_ScrollElementConfig *scrollConfig = Clay__FindElementConfigWithType(scrollElement, CLAY__ELEMENT_CONFIG_TYPE_SCROLL).scrollElementConfig; bool canScrollVertically = scrollConfig->vertical && highestPriorityScrollData->contentSize.height > scrollElement->dimensions.height; bool canScrollHorizontally = scrollConfig->horizontal && highestPriorityScrollData->contentSize.width > scrollElement->dimensions.width; // Handle wheel scroll @@ -3340,9 +3451,10 @@ void Clay_BeginLayout(void) { } context->booleanWarnings = CLAY__INIT(Clay_BooleanWarnings) CLAY__DEFAULT_STRUCT; Clay__OpenElement(); - CLAY_ID("Clay__RootContainer"); - CLAY_LAYOUT({ .sizing = {CLAY_SIZING_FIXED((rootDimensions.width)), CLAY_SIZING_FIXED(rootDimensions.height)} }); - Clay__ElementPostConfiguration(); + Clay__ConfigureOpenElement((Clay_ElementDeclaration) { + .id = CLAY_ID("Clay__RootContainer"), + .layout = { .sizing = {CLAY_SIZING_FIXED((rootDimensions.width)), CLAY_SIZING_FIXED(rootDimensions.height)} } + }); Clay__int32_tArray_Add(&context->openLayoutElementStack, 0); Clay__LayoutElementTreeRootArray_Add(&context->layoutElementTreeRoots, CLAY__INIT(Clay__LayoutElementTreeRoot) { .layoutElementIndex = 0 }); } @@ -3360,7 +3472,12 @@ Clay_RenderCommandArray Clay_EndLayout(void) { } if (context->booleanWarnings.maxElementsExceeded) { 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 }, .text = CLAY__INIT(Clay_StringSlice) { .length = message.length, .chars = message.chars, .baseChars = message.chars }, .commandType = CLAY_RENDER_COMMAND_TYPE_TEXT }); + 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 } }, + .commandType = CLAY_RENDER_COMMAND_TYPE_TEXT + }); } else { Clay__CalculateFinalLayout(); } @@ -3430,7 +3547,7 @@ Clay_ScrollContainerData Clay_GetScrollContainerData(Clay_ElementId id) { .scrollPosition = &scrollContainerData->scrollPosition, .scrollContainerDimensions = { scrollContainerData->boundingBox.width, scrollContainerData->boundingBox.height }, .contentDimensions = scrollContainerData->contentSize, - .config = *Clay__FindElementConfigWithType(scrollContainerData->layoutElement, CLAY__ELEMENT_CONFIG_TYPE_SCROLL_CONTAINER).scrollElementConfig, + .config = *Clay__FindElementConfigWithType(scrollContainerData->layoutElement, CLAY__ELEMENT_CONFIG_TYPE_SCROLL).scrollElementConfig, .found = true }; } @@ -3488,7 +3605,7 @@ void Clay_SetMaxElementCount(int32_t maxElementCount) { context->maxElementCount = maxElementCount; } else { Clay__defaultMaxElementCount = maxElementCount; // TODO: Fix this - Clay__defaultMaxMeasureTextWordCacheCount = maxElementCount * 2; + Clay__defaultMaxMeasureTextWordCacheCount = maxElementCount * 2; } } diff --git a/examples/SDL2-video-demo/CMakeLists.txt b/examples/SDL2-video-demo/CMakeLists.txt index ace8592..4dffd2b 100644 --- a/examples/SDL2-video-demo/CMakeLists.txt +++ b/examples/SDL2-video-demo/CMakeLists.txt @@ -45,10 +45,10 @@ target_link_libraries(SDL2_video_demo PUBLIC ) if(MSVC) - set(CMAKE_C_FLAGS_DEBUG "/D CLAY_DEBUG") + set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}") else() - set(CMAKE_C_FLAGS_DEBUG "-Wall -Werror -Wno-error=missing-braces -DCLAY_DEBUG") - set(CMAKE_C_FLAGS_RELEASE "-O3") + set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}") + set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}") endif() add_custom_command( diff --git a/examples/SDL2-video-demo/main.c b/examples/SDL2-video-demo/main.c index e8c3413..ceccb26 100644 --- a/examples/SDL2-video-demo/main.c +++ b/examples/SDL2-video-demo/main.c @@ -9,265 +9,10 @@ #include #include #include - -const int FONT_ID_BODY_16 = 0; -Clay_Color COLOR_WHITE = { 255, 255, 255, 255}; +#include "../shared-layouts/clay-video-demo.c" SDL_Surface *sample_image; -void RenderHeaderButton(Clay_String text) { - CLAY( - CLAY_LAYOUT({ .padding = { 16, 16, 8, 8 }}), - CLAY_RECTANGLE({ - .color = { 140, 140, 140, 255 }, - .cornerRadius = 5 - }) - ) { - CLAY_TEXT(text, CLAY_TEXT_CONFIG({ - .fontId = FONT_ID_BODY_16, - .fontSize = 16, - .textColor = { 255, 255, 255, 255 } - })); - } -} - -void RenderDropdownMenuItem(Clay_String text) { - CLAY(CLAY_LAYOUT({ .padding = CLAY_PADDING_ALL(16)})) { - CLAY_TEXT(text, CLAY_TEXT_CONFIG({ - .fontId = FONT_ID_BODY_16, - .fontSize = 16, - .textColor = { 255, 255, 255, 255 } - })); - } -} - -typedef struct { - Clay_String title; - Clay_String contents; -} Document; - -typedef struct { - Document *documents; - uint32_t length; -} DocumentArray; - -DocumentArray documents = { - .documents = NULL, - .length = 5 -}; - -uint32_t selectedDocumentIndex = 0; - -void HandleSidebarInteraction( - Clay_ElementId elementId, - Clay_PointerData pointerData, - intptr_t userData -) { - // If this button was clicked - if (pointerData.state == CLAY_POINTER_DATA_PRESSED_THIS_FRAME) { - if (userData >= 0 && userData < documents.length) { - // Select the corresponding document - selectedDocumentIndex = userData; - } - } -} - -static Clay_RenderCommandArray CreateLayout() { - Clay_BeginLayout(); - Clay_Sizing layoutExpand = { - .width = CLAY_SIZING_GROW(0), - .height = CLAY_SIZING_GROW(0) - }; - - Clay_RectangleElementConfig contentBackgroundConfig = { - .color = { 90, 90, 90, 255 }, - .cornerRadius = 8 - }; - - Clay_BeginLayout(); - // Build UI here - CLAY( - CLAY_ID("OuterContainer"), - CLAY_RECTANGLE({ .color = { 43, 41, 51, 255 } }), - CLAY_LAYOUT({ - .layoutDirection = CLAY_TOP_TO_BOTTOM, - .sizing = layoutExpand, - .padding = CLAY_PADDING_ALL(16), - .childGap = 16 - }) - ) { - // Child elements go inside braces - CLAY( - CLAY_ID("HeaderBar"), - CLAY_RECTANGLE(contentBackgroundConfig), - CLAY_LAYOUT({ - .sizing = { - .height = CLAY_SIZING_FIXED(60), - .width = CLAY_SIZING_GROW(0) - }, - .padding = { 16 }, - .childGap = 16, - .childAlignment = { - .y = CLAY_ALIGN_Y_CENTER - } - }) - ) { - // Header buttons go here - CLAY( - CLAY_LAYOUT({ .padding = { 16, 16, 8, 8 }}), - CLAY_BORDER_ALL({ 2, COLOR_WHITE }) - ) { - CLAY( - CLAY_LAYOUT({ .padding = { 8, 8, 8, 8 }}), - CLAY_IMAGE({ sample_image, { 23, 42 } }) - ) {} - } - CLAY( - CLAY_ID("FileButton"), - CLAY_LAYOUT({ .padding = { 16, 16, 8, 8 }}), - CLAY_RECTANGLE({ - .color = { 140, 140, 140, 255 }, - .cornerRadius = 5 - }) - ) { - CLAY_TEXT(CLAY_STRING("File"), CLAY_TEXT_CONFIG({ - .fontId = FONT_ID_BODY_16, - .fontSize = 16, - .textColor = { 255, 255, 255, 255 } - })); - - bool fileMenuVisible = - Clay_PointerOver(Clay_GetElementId(CLAY_STRING("FileButton"))) - || - Clay_PointerOver(Clay_GetElementId(CLAY_STRING("FileMenu"))); - - if (fileMenuVisible) { // Below has been changed slightly to fix the small bug where the menu would dismiss when mousing over the top gap - CLAY( - CLAY_ID("FileMenu"), - CLAY_FLOATING({ - .attachment = { - .parent = CLAY_ATTACH_POINT_LEFT_BOTTOM - }, - }), - CLAY_LAYOUT({ - .padding = {0, 8 } - }) - ) { - CLAY( - CLAY_LAYOUT({ - .layoutDirection = CLAY_TOP_TO_BOTTOM, - .sizing = { - .width = CLAY_SIZING_FIXED(200) - }, - }), - CLAY_RECTANGLE({ - .color = { 40, 40, 40, 255 }, - .cornerRadius = 8 - }) - ) { - // Render dropdown items here - RenderDropdownMenuItem(CLAY_STRING("New")); - RenderDropdownMenuItem(CLAY_STRING("Open")); - RenderDropdownMenuItem(CLAY_STRING("Close")); - } - } - } - } - RenderHeaderButton(CLAY_STRING("Edit")); - CLAY(CLAY_LAYOUT({ .sizing = { CLAY_SIZING_GROW(0) }})) {} - RenderHeaderButton(CLAY_STRING("Upload")); - RenderHeaderButton(CLAY_STRING("Media")); - RenderHeaderButton(CLAY_STRING("Support")); - } - - CLAY( - CLAY_ID("LowerContent"), - CLAY_LAYOUT({ .sizing = layoutExpand, .childGap = 16 }) - ) { - CLAY( - CLAY_ID("Sidebar"), - CLAY_RECTANGLE(contentBackgroundConfig), - CLAY_LAYOUT({ - .layoutDirection = CLAY_TOP_TO_BOTTOM, - .padding = CLAY_PADDING_ALL(16), - .childGap = 8, - .sizing = { - .width = CLAY_SIZING_FIXED(250), - .height = CLAY_SIZING_GROW(0) - } - }) - ) { - for (int i = 0; i < documents.length; i++) { - Document document = documents.documents[i]; - Clay_LayoutConfig sidebarButtonLayout = { - .sizing = { .width = CLAY_SIZING_GROW(0) }, - .padding = CLAY_PADDING_ALL(16) - }; - - if (i == selectedDocumentIndex) { - CLAY( - CLAY_LAYOUT(sidebarButtonLayout), - CLAY_RECTANGLE({ - .color = { 120, 120, 120, 255 }, - .cornerRadius = 8, - }) - ) { - CLAY_TEXT(document.title, CLAY_TEXT_CONFIG({ - .fontId = FONT_ID_BODY_16, - .fontSize = 20, - .textColor = { 255, 255, 255, 255 } - })); - } - } else { - CLAY( - CLAY_LAYOUT(sidebarButtonLayout), - Clay_OnHover(HandleSidebarInteraction, i), - Clay_Hovered() - ? CLAY_RECTANGLE({ - .color = { 120, 120, 120, 120 }, - .cornerRadius = 8 - }) - : 0 - ) { - CLAY_TEXT(document.title, CLAY_TEXT_CONFIG({ - .fontId = FONT_ID_BODY_16, - .fontSize = 20, - .textColor = { 255, 255, 255, 255 } - })); - } - } - } - } - - CLAY( - CLAY_ID("MainContent"), - CLAY_RECTANGLE(contentBackgroundConfig), - CLAY_SCROLL({ .vertical = true }), - CLAY_LAYOUT({ - .layoutDirection = CLAY_TOP_TO_BOTTOM, - .childGap = 16, - .padding = CLAY_PADDING_ALL(16), - .sizing = layoutExpand - }) - ) { - Document selectedDocument = documents.documents[selectedDocumentIndex]; - CLAY_TEXT(selectedDocument.title, CLAY_TEXT_CONFIG({ - .fontId = FONT_ID_BODY_16, - .fontSize = 24, - .textColor = COLOR_WHITE - })); - CLAY_TEXT(selectedDocument.contents, CLAY_TEXT_CONFIG({ - .fontId = FONT_ID_BODY_16, - .fontSize = 24, - .textColor = COLOR_WHITE - })); - } - } - } - - return Clay_EndLayout(); -} - void HandleClayErrors(Clay_ErrorData errorData) { printf("%s", errorData.errorText.chars); } @@ -328,6 +73,7 @@ int main(int argc, char *argv[]) { Uint64 NOW = SDL_GetPerformanceCounter(); Uint64 LAST = 0; double deltaTime = 0; + ClayVideoDemo_Data demoData = ClayVideoDemo_Initialize(); while (true) { Clay_Vector2 scrollDelta = {}; @@ -345,6 +91,7 @@ int main(int argc, char *argv[]) { LAST = NOW; NOW = SDL_GetPerformanceCounter(); deltaTime = (double)((NOW - LAST)*1000 / (double)SDL_GetPerformanceFrequency() ); + printf("%f\n", deltaTime); int mouseX = 0; int mouseY = 0; @@ -361,7 +108,7 @@ int main(int argc, char *argv[]) { SDL_GetWindowSize(window, &windowWidth, &windowHeight); Clay_SetLayoutDimensions((Clay_Dimensions) { (float)windowWidth, (float)windowHeight }); - Clay_RenderCommandArray renderCommands = CreateLayout(); + Clay_RenderCommandArray renderCommands = ClayVideoDemo_CreateLayout(&demoData); SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); SDL_RenderClear(renderer); diff --git a/examples/SDL3-simple-demo/CMakeLists.txt b/examples/SDL3-simple-demo/CMakeLists.txt index 4a86f0e..df467a9 100644 --- a/examples/SDL3-simple-demo/CMakeLists.txt +++ b/examples/SDL3-simple-demo/CMakeLists.txt @@ -4,8 +4,8 @@ cmake_minimum_required(VERSION 3.27) project(clay_examples_sdl3_simple_demo C) set(CMAKE_C_STANDARD 99) -set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -g") -set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -O3") +set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}") +set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}") include(FetchContent) set(FETCHCONTENT_QUIET FALSE) diff --git a/examples/SDL3-simple-demo/main.c b/examples/SDL3-simple-demo/main.c index 2b89dbb..67f1f51 100644 --- a/examples/SDL3-simple-demo/main.c +++ b/examples/SDL3-simple-demo/main.c @@ -9,6 +9,7 @@ #include #include "../../renderers/SDL3/clay_renderer_SDL3.c" +#include "../shared-layouts/clay-video-demo.c" static const Uint32 FONT_ID = 0; @@ -19,6 +20,7 @@ static const Clay_Color COLOR_LIGHT = (Clay_Color) {224, 215, 210, 255}; typedef struct app_state { SDL_Window *window; SDL_Renderer *renderer; + ClayVideoDemo_Data demoData; } AppState; static inline Clay_Dimensions SDL_MeasureText(Clay_StringSlice text, Clay_TextElementConfig *config, uintptr_t userData) @@ -33,75 +35,6 @@ static inline Clay_Dimensions SDL_MeasureText(Clay_StringSlice text, Clay_TextEl return (Clay_Dimensions) { (float) width, (float) height }; } -static void Label(const Clay_String text, const int cornerRadius) -{ - CLAY(CLAY_LAYOUT({ .padding = {8, 8} }), - CLAY_RECTANGLE({ - .color = Clay_Hovered() ? COLOR_BLUE : COLOR_ORANGE, - .cornerRadius = cornerRadius, - })) { - CLAY_TEXT(text, CLAY_TEXT_CONFIG({ - .textColor = { 255, 255, 255, 255 }, - .fontId = FONT_ID, - .fontSize = 24, - })); - } -} - -static void LabelBorder(const Clay_String text, const int cornerRadius, const int thickness) -{ - CLAY( - CLAY_LAYOUT({ - .padding = {16, 16, 8, 8 } }), - CLAY_BORDER_OUTSIDE_RADIUS( - thickness, - COLOR_BLUE, - cornerRadius) - ){ - CLAY_TEXT(text, CLAY_TEXT_CONFIG({ - .textColor = { 255, 255, 255, 255 }, - .fontId = FONT_ID, - .fontSize = 24, - })); - } -} - -static Clay_RenderCommandArray Clay_CreateLayout() -{ - Clay_BeginLayout(); - CLAY(CLAY_ID("MainContent"), - CLAY_LAYOUT({ - .sizing = { - .width = CLAY_SIZING_GROW(), - .height = CLAY_SIZING_GROW(), - }, - .childAlignment = { - .x = CLAY_ALIGN_X_CENTER, - .y = CLAY_ALIGN_Y_CENTER, - }, - .childGap = 10, - .padding = { 10, 10 }, - .layoutDirection = CLAY_TOP_TO_BOTTOM, - }), - CLAY_BORDER({ - .left = { 20, COLOR_BLUE }, - .right = { 20, COLOR_BLUE }, - .bottom = { 20, COLOR_BLUE } - }), - CLAY_RECTANGLE({ - .color = COLOR_LIGHT, - }) - ) { - Label(CLAY_STRING("Rounded - Button 1"), 10); - Label(CLAY_STRING("Straight - Button 2") , 0); - Label(CLAY_STRING("Rounded+ - Button 3") , 20); - LabelBorder(CLAY_STRING("Border - Button 4"), 0, 5); - LabelBorder(CLAY_STRING("RoundedBorder - Button 5"), 10, 5); - LabelBorder(CLAY_STRING("RoundedBorder - Button 6"), 40, 15); - } - return Clay_EndLayout(); -} - void HandleClayErrors(Clay_ErrorData errorData) { printf("%s", errorData.errorText.chars); } @@ -147,6 +80,8 @@ SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[]) Clay_Initialize(clayMemory, (Clay_Dimensions) { (float) width, (float) height }, (Clay_ErrorHandler) { HandleClayErrors }); Clay_SetMeasureTextFunction(SDL_MeasureText, 0); + state->demoData = ClayVideoDemo_Initialize(); + *appstate = state; return SDL_APP_CONTINUE; } @@ -180,7 +115,7 @@ SDL_AppResult SDL_AppIterate(void *appstate) { AppState *state = appstate; - Clay_RenderCommandArray render_commands = Clay_CreateLayout(); + Clay_RenderCommandArray render_commands = ClayVideoDemo_CreateLayout(&state->demoData); SDL_SetRenderDrawColor(state->renderer, 0, 0, 0, 255); SDL_RenderClear(state->renderer); diff --git a/examples/cairo-pdf-rendering/CMakeLists.txt b/examples/cairo-pdf-rendering/CMakeLists.txt index 1f321dd..bdfe4e7 100644 --- a/examples/cairo-pdf-rendering/CMakeLists.txt +++ b/examples/cairo-pdf-rendering/CMakeLists.txt @@ -4,7 +4,6 @@ set(CMAKE_C_STANDARD 99) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../../cmake") - add_executable(clay_examples_cairo_pdf_rendering main.c) find_package(Cairo REQUIRED) @@ -13,8 +12,8 @@ target_compile_options(clay_examples_cairo_pdf_rendering PUBLIC) target_include_directories(clay_examples_cairo_pdf_rendering PUBLIC . ${CAIRO_INCLUDE_DIRS}) target_link_libraries(clay_examples_cairo_pdf_rendering PUBLIC Cairo::Cairo) -set(CMAKE_C_FLAGS_DEBUG "-Wall -Werror -Wno-error=missing-braces") -set(CMAKE_C_FLAGS_RELEASE "-O3") +set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}") +set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}") add_custom_command( TARGET clay_examples_cairo_pdf_rendering POST_BUILD diff --git a/examples/cairo-pdf-rendering/main.c b/examples/cairo-pdf-rendering/main.c index f9fc793..6b70ce4 100644 --- a/examples/cairo-pdf-rendering/main.c +++ b/examples/cairo-pdf-rendering/main.c @@ -37,32 +37,21 @@ void Layout() { static Clay_Color BACKGROUND = { 0xF4, 0xEB, 0xE6, 255 }; static Clay_Color ACCENT = { 0xFA, 0xE0, 0xD4, 255 }; - CLAY(CLAY_LAYOUT({ .sizing = { CLAY_SIZING_GROW(0), CLAY_SIZING_GROW(0) }, - .layoutDirection = CLAY_TOP_TO_BOTTOM }), - CLAY_RECTANGLE({ .color = BACKGROUND })) { - CLAY(CLAY_ID("PageMargins"), - CLAY_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})) { - + CLAY({ .layout = { .sizing = { CLAY_SIZING_GROW(0), CLAY_SIZING_GROW(0) }, + .layoutDirection = CLAY_TOP_TO_BOTTOM }, + .rectangle = { .color = 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(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({.fontFamily = CLAY_STRING("Calistoga"), .textColor = PRIMARY, .fontSize = 24})); // Feature Box - CLAY(CLAY_LAYOUT({ .sizing = { CLAY_SIZING_GROW(0), CLAY_SIZING_FIT(0) }, .childGap = 10 })) { - CLAY(CLAY_LAYOUT({ .sizing = { CLAY_SIZING_GROW(0), CLAY_SIZING_FIT(0) }}), CLAY_RECTANGLE({ - .color = ACCENT, - .cornerRadius = CLAY_CORNER_RADIUS(12), - })) { - CLAY(CLAY_LAYOUT({.padding = CLAY_PADDING_ALL(20), .childGap = 4, .layoutDirection = CLAY_TOP_TO_BOTTOM })) { + 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 = {.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(CLAY_STRING("- Declarative syntax"), @@ -75,29 +64,29 @@ void Layout() { CLAY_TEXT_CONFIG({ .textColor = PRIMARY, .fontSize = 14, .fontFamily = CLAY_STRING("Quicksand SemiBold") })); } } - CLAY(CLAY_LAYOUT({ + 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 - }), CLAY_RECTANGLE({ .color = ACCENT, .cornerRadius = CLAY_CORNER_RADIUS(8) })) { + }, .rectangle = { .color = ACCENT }, .shared = {.cornerRadius = CLAY_CORNER_RADIUS(8)}}) { // Profile picture - CLAY(CLAY_LAYOUT({ + 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 }}), CLAY_BORDER_OUTSIDE_RADIUS(2, PRIMARY, 10)) { - CLAY(CLAY_LAYOUT({ .sizing = { CLAY_SIZING_FIXED(32), CLAY_SIZING_FIXED(32) } }), CLAY_IMAGE({ .sourceDimensions = { 32, 32 }, .path = CLAY_STRING("resources/check.png") })); + .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") }}); } } } - CLAY(CLAY_LAYOUT({ .sizing = { CLAY_SIZING_GROW(0), CLAY_SIZING_FIXED(16) } })); + CLAY({ .layout = { .sizing = { CLAY_SIZING_GROW(0), CLAY_SIZING_FIXED(16) } }}); - CLAY(CLAY_LAYOUT({ .sizing = { CLAY_SIZING_GROW(0), CLAY_SIZING_GROW(0) }, .childGap = 10, .layoutDirection = CLAY_TOP_TO_BOTTOM })) { + 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(CLAY_LAYOUT({ .padding = CLAY_PADDING_ALL(10) }), CLAY_RECTANGLE({ .color = ACCENT, .cornerRadius = CLAY_CORNER_RADIUS(10) })) { + CLAY({ .layout = { .padding = CLAY_PADDING_ALL(10) }, .rectangle = { .color = ACCENT }, .shared = { .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. " @@ -136,11 +125,12 @@ int main(void) { uint64_t totalMemorySize = Clay_MinMemorySize(); Clay_Arena clayMemory = Clay_CreateArenaWithCapacityAndMemory(totalMemorySize, malloc(totalMemorySize)); - Clay_SetMeasureTextFunction(Clay_Cairo_MeasureText); // We initialize Clay with the same size Clay_Initialize(clayMemory, (Clay_Dimensions) { width, height }, (Clay_ErrorHandler) { HandleClayErrors }); + Clay_SetMeasureTextFunction(Clay_Cairo_MeasureText, 0); + Clay_BeginLayout(); // Here you can now create the declarative clay layout. diff --git a/examples/clay-official-website/CMakeLists.txt b/examples/clay-official-website/CMakeLists.txt index 9702d21..b64f447 100644 --- a/examples/clay-official-website/CMakeLists.txt +++ b/examples/clay-official-website/CMakeLists.txt @@ -7,5 +7,3 @@ add_executable(clay_official_website main.c) target_compile_options(clay_official_website PUBLIC -Wall -Werror -Wno-unknown-pragmas -Wno-error=missing-braces) target_include_directories(clay_official_website PUBLIC .) - -set(CMAKE_C_FLAGS_RELEASE "-O3") \ No newline at end of file diff --git a/examples/clay-official-website/build/clay/index.wasm b/examples/clay-official-website/build/clay/index.wasm index 3435138..6125d2a 100755 Binary files a/examples/clay-official-website/build/clay/index.wasm and b/examples/clay-official-website/build/clay/index.wasm differ diff --git a/examples/cpp-project-example/CMakeLists.txt b/examples/cpp-project-example/CMakeLists.txt index 24422d7..4ddcf39 100644 --- a/examples/cpp-project-example/CMakeLists.txt +++ b/examples/cpp-project-example/CMakeLists.txt @@ -11,6 +11,6 @@ add_executable(clay_examples_cpp_project_example main.cpp) target_include_directories(clay_examples_cpp_project_example PUBLIC .) if(NOT MSVC) - set(CMAKE_CXX_FLAGS_DEBUG "-Werror -Wall") - set(CMAKE_CXX_FLAGS_RELEASE "-O3") + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}") + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}") endif() diff --git a/examples/cpp-project-example/main.cpp b/examples/cpp-project-example/main.cpp index 363e8ef..0d52406 100644 --- a/examples/cpp-project-example/main.cpp +++ b/examples/cpp-project-example/main.cpp @@ -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(CLAY_RECTANGLE({ .color = {255,255,255,0} }), CLAY_LAYOUT(layoutElement)) { + CLAY({ .layout = layoutElement, .rectangle = { .color = {255,255,255,0} } }) { CLAY_TEXT(CLAY_STRING(""), CLAY_TEXT_CONFIG({ .fontId = 0 })); } Clay_EndLayout(); diff --git a/examples/introducing-clay-video-demo/CMakeLists.txt b/examples/introducing-clay-video-demo/CMakeLists.txt index a59d678..48c5983 100644 --- a/examples/introducing-clay-video-demo/CMakeLists.txt +++ b/examples/introducing-clay-video-demo/CMakeLists.txt @@ -28,8 +28,8 @@ target_link_libraries(clay_examples_introducing_clay_video_demo PUBLIC raylib) if(MSVC) set(CMAKE_C_FLAGS_DEBUG "/D CLAY_DEBUG") else() - set(CMAKE_C_FLAGS_DEBUG "-Wall -Werror -Wno-error=missing-braces -DCLAY_DEBUG") - set(CMAKE_C_FLAGS_RELEASE "-O3") + set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}") + set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}") endif() add_custom_command( diff --git a/examples/introducing-clay-video-demo/main.c b/examples/introducing-clay-video-demo/main.c index 7f3ae24..9f188c4 100644 --- a/examples/introducing-clay-video-demo/main.c +++ b/examples/introducing-clay-video-demo/main.c @@ -1,81 +1,14 @@ #define CLAY_IMPLEMENTATION #include "../../clay.h" #include "../../renderers/raylib/clay_renderer_raylib.c" - -const int FONT_ID_BODY_16 = 0; -Clay_Color COLOR_WHITE = { 255, 255, 255, 255}; - -void RenderHeaderButton(Clay_String text) { - CLAY( - CLAY_LAYOUT({ .padding = { 16, 16, 8, 8 }}), - CLAY_RECTANGLE({ - .color = { 140, 140, 140, 255 }, - .cornerRadius = 5 - }) - ) { - CLAY_TEXT(text, CLAY_TEXT_CONFIG({ - .fontId = FONT_ID_BODY_16, - .fontSize = 16, - .textColor = { 255, 255, 255, 255 } - })); - } -} - -void RenderDropdownMenuItem(Clay_String text) { - CLAY(CLAY_LAYOUT({ .padding = CLAY_PADDING_ALL(16)})) { - CLAY_TEXT(text, CLAY_TEXT_CONFIG({ - .fontId = FONT_ID_BODY_16, - .fontSize = 16, - .textColor = { 255, 255, 255, 255 } - })); - } -} - -typedef struct { - Clay_String title; - Clay_String contents; -} Document; - -typedef struct { - Document *documents; - uint32_t length; -} DocumentArray; - -DocumentArray documents = { - .documents = NULL, // TODO figure out if it's possible to const init this list - .length = 5 -}; - -uint32_t selectedDocumentIndex = 0; - -void HandleSidebarInteraction( - Clay_ElementId elementId, - Clay_PointerData pointerData, - intptr_t userData -) { - // If this button was clicked - if (pointerData.state == CLAY_POINTER_DATA_PRESSED_THIS_FRAME) { - if (userData >= 0 && userData < documents.length) { - // Select the corresponding document - selectedDocumentIndex = userData; - } - } -} +#include "../shared-layouts/clay-video-demo.c" // This function is new since the video was published void HandleClayErrors(Clay_ErrorData errorData) { printf("%s", errorData.errorText.chars); } - int main(void) { - 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") }, - }; Clay_Raylib_Initialize(1024, 768, "Introducing Clay Demo", FLAG_WINDOW_RESIZABLE | FLAG_WINDOW_HIGHDPI | FLAG_MSAA_4X_HINT | FLAG_VSYNC_HINT); // Extra parameters to this function are new since the video was published uint64_t clayRequiredMemory = Clay_MinMemorySize(); @@ -91,11 +24,13 @@ int main(void) { }; SetTextureFilter(Raylib_fonts[FONT_ID_BODY_16].font.texture, TEXTURE_FILTER_BILINEAR); + ClayVideoDemo_Data data = ClayVideoDemo_Initialize(); + while (!WindowShouldClose()) { // Run once per frame Clay_SetLayoutDimensions((Clay_Dimensions) { - .width = GetScreenWidth(), - .height = GetScreenHeight() + .width = GetScreenWidth(), + .height = GetScreenHeight() }); Vector2 mousePosition = GetMousePosition(); @@ -110,189 +45,7 @@ int main(void) { GetFrameTime() ); - Clay_Sizing layoutExpand = { - .width = CLAY_SIZING_GROW(0), - .height = CLAY_SIZING_GROW(0) - }; - - Clay_RectangleElementConfig contentBackgroundConfig = { - .color = { 90, 90, 90, 255 }, - .cornerRadius = CLAY_CORNER_RADIUS(8) - }; - - Clay_BeginLayout(); - // Build UI here - CLAY( - CLAY_ID("OuterContainer"), - CLAY_RECTANGLE({ .color = { 43, 41, 51, 255 } }), - CLAY_LAYOUT({ - .layoutDirection = CLAY_TOP_TO_BOTTOM, - .sizing = layoutExpand, - .padding = CLAY_PADDING_ALL(16), - .childGap = 16 - }) - ) { - // Child elements go inside braces - CLAY( - CLAY_ID("HeaderBar"), - CLAY_RECTANGLE(contentBackgroundConfig), - CLAY_LAYOUT({ - .sizing = { - .height = CLAY_SIZING_FIXED(60), - .width = CLAY_SIZING_GROW(0) - }, - .padding = { 16, 16, 0, 0 }, - .childGap = 16, - .childAlignment = { - .y = CLAY_ALIGN_Y_CENTER - } - }) - ) { - // Header buttons go here - CLAY( - CLAY_ID("FileButton"), - CLAY_LAYOUT({ .padding = { 16, 16, 8, 8 }}), - CLAY_RECTANGLE({ - .color = { 140, 140, 140, 255 }, - .cornerRadius = CLAY_CORNER_RADIUS(5) - }) - ) { - CLAY_TEXT(CLAY_STRING("File"), CLAY_TEXT_CONFIG({ - .fontId = FONT_ID_BODY_16, - .fontSize = 16, - .textColor = { 255, 255, 255, 255 } - })); - - bool fileMenuVisible = - Clay_PointerOver(Clay_GetElementId(CLAY_STRING("FileButton"))) - || - Clay_PointerOver(Clay_GetElementId(CLAY_STRING("FileMenu"))); - - if (fileMenuVisible) { // Below has been changed slightly to fix the small bug where the menu would dismiss when mousing over the top gap - CLAY( - CLAY_ID("FileMenu"), - CLAY_FLOATING({ - .attachment = { - .parent = CLAY_ATTACH_POINT_LEFT_BOTTOM - }, - }), - CLAY_LAYOUT({ - .padding = {0, 0, 8, 8 } - }) - ) { - CLAY( - CLAY_LAYOUT({ - .layoutDirection = CLAY_TOP_TO_BOTTOM, - .sizing = { - .width = CLAY_SIZING_FIXED(200) - }, - }), - CLAY_RECTANGLE({ - .color = { 40, 40, 40, 255 }, - .cornerRadius = CLAY_CORNER_RADIUS(8) - }) - ) { - // Render dropdown items here - RenderDropdownMenuItem(CLAY_STRING("New")); - RenderDropdownMenuItem(CLAY_STRING("Open")); - RenderDropdownMenuItem(CLAY_STRING("Close")); - } - } - } - } - RenderHeaderButton(CLAY_STRING("Edit")); - CLAY(CLAY_LAYOUT({ .sizing = { CLAY_SIZING_GROW(0) }})) {} - RenderHeaderButton(CLAY_STRING("Upload")); - RenderHeaderButton(CLAY_STRING("Media")); - RenderHeaderButton(CLAY_STRING("Support")); - } - - CLAY( - CLAY_ID("LowerContent"), - CLAY_LAYOUT({ .sizing = layoutExpand, .childGap = 16 }) - ) { - CLAY( - CLAY_ID("Sidebar"), - CLAY_RECTANGLE(contentBackgroundConfig), - CLAY_LAYOUT({ - .layoutDirection = CLAY_TOP_TO_BOTTOM, - .padding = CLAY_PADDING_ALL(16), - .childGap = 8, - .sizing = { - .width = CLAY_SIZING_FIXED(250), - .height = CLAY_SIZING_GROW(0) - } - }) - ) { - for (int i = 0; i < documents.length; i++) { - Document document = documents.documents[i]; - Clay_LayoutConfig sidebarButtonLayout = { - .sizing = { .width = CLAY_SIZING_GROW(0) }, - .padding = CLAY_PADDING_ALL(16) - }; - - if (i == selectedDocumentIndex) { - CLAY( - CLAY_LAYOUT(sidebarButtonLayout), - CLAY_RECTANGLE({ - .color = { 120, 120, 120, 255 }, - .cornerRadius = CLAY_CORNER_RADIUS(8), - }) - ) { - CLAY_TEXT(document.title, CLAY_TEXT_CONFIG({ - .fontId = FONT_ID_BODY_16, - .fontSize = 20, - .textColor = { 255, 255, 255, 255 } - })); - } - } else { - CLAY( - CLAY_LAYOUT(sidebarButtonLayout), - Clay_OnHover(HandleSidebarInteraction, i), - Clay_Hovered() - ? CLAY_RECTANGLE({ - .color = { 120, 120, 120, 120 }, - .cornerRadius = CLAY_CORNER_RADIUS(8) - }) - : 0 - ) { - CLAY_TEXT(document.title, CLAY_TEXT_CONFIG({ - .fontId = FONT_ID_BODY_16, - .fontSize = 20, - .textColor = { 255, 255, 255, 255 } - })); - } - } - } - } - - CLAY( - CLAY_ID("MainContent"), - CLAY_RECTANGLE(contentBackgroundConfig), - CLAY_SCROLL({ .vertical = true }), - CLAY_LAYOUT({ - .layoutDirection = CLAY_TOP_TO_BOTTOM, - .childGap = 16, - .padding = CLAY_PADDING_ALL(16), - .sizing = layoutExpand - }) - ) { - Document selectedDocument = documents.documents[selectedDocumentIndex]; - CLAY_TEXT(selectedDocument.title, CLAY_TEXT_CONFIG({ - .fontId = FONT_ID_BODY_16, - .fontSize = 24, - .textColor = COLOR_WHITE - })); - CLAY_TEXT(selectedDocument.contents, CLAY_TEXT_CONFIG({ - .fontId = FONT_ID_BODY_16, - .fontSize = 24, - .textColor = COLOR_WHITE - })); - } - } - } - - Clay_RenderCommandArray renderCommands = Clay_EndLayout(); + Clay_RenderCommandArray renderCommands = ClayVideoDemo_CreateLayout(&data); BeginDrawing(); ClearBackground(BLACK); diff --git a/examples/raylib-multi-context/CMakeLists.txt b/examples/raylib-multi-context/CMakeLists.txt index 9179ec1..24853b5 100644 --- a/examples/raylib-multi-context/CMakeLists.txt +++ b/examples/raylib-multi-context/CMakeLists.txt @@ -26,7 +26,7 @@ target_include_directories(clay_examples_raylib_multi_context PUBLIC .) target_link_libraries(clay_examples_raylib_multi_context PUBLIC raylib) set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}") -set(CMAKE_C_FLAGS_RELEASE "-O3") +set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}") add_custom_command( TARGET clay_examples_raylib_multi_context POST_BUILD diff --git a/examples/raylib-multi-context/main.c b/examples/raylib-multi-context/main.c index 1d3925a..7cb975b 100644 --- a/examples/raylib-multi-context/main.c +++ b/examples/raylib-multi-context/main.c @@ -1,87 +1,13 @@ #define CLAY_IMPLEMENTATION #include "../../clay.h" #include "../../renderers/raylib/clay_renderer_raylib.c" +#include "../shared-layouts/clay-video-demo.c" -const int FONT_ID_BODY_16 = 0; -Clay_Color COLOR_WHITE = { 255, 255, 255, 255}; - -void RenderHeaderButton(Clay_String text) { - CLAY( - CLAY_LAYOUT({ .padding = { 16, 16, 8, 8 }}), - CLAY_RECTANGLE({ - .color = { 140, 140, 140, 255 }, - .cornerRadius = CLAY_CORNER_RADIUS(5) - }) - ) { - CLAY_TEXT(text, CLAY_TEXT_CONFIG({ - .fontId = FONT_ID_BODY_16, - .fontSize = 16, - .textColor = { 255, 255, 255, 255 } - })); - } -} - -void RenderDropdownMenuItem(Clay_String text) { - CLAY(CLAY_LAYOUT({ .padding = CLAY_PADDING_ALL(16)})) { - CLAY_TEXT(text, CLAY_TEXT_CONFIG({ - .fontId = FONT_ID_BODY_16, - .fontSize = 16, - .textColor = { 255, 255, 255, 255 } - })); - } -} - -typedef struct { - Clay_String title; - Clay_String contents; -} Document; - -typedef struct { - Document *documents; - int32_t length; -} DocumentArray; - -DocumentArray documents = { - .documents = NULL, // TODO figure out if it's possible to const init this list - .length = 5 -}; - -int32_t selectedDocumentIndexTop = 0; -int32_t selectedDocumentIndexBottom = 0; - -typedef struct { - int32_t requestedDocumentIndex; - int32_t* selectedDocumentIndex; -} SidebarClickData; - -void HandleSidebarInteraction( - Clay_ElementId elementId, - Clay_PointerData pointerData, - intptr_t userData -) { - SidebarClickData *clickData = (SidebarClickData*)userData; - // If this button was clicked - if (pointerData.state == CLAY_POINTER_DATA_PRESSED_THIS_FRAME) { - if (clickData->requestedDocumentIndex >= 0 && clickData->requestedDocumentIndex < documents.length) { - // Select the corresponding document - *clickData->selectedDocumentIndex = clickData->requestedDocumentIndex; - } - } -} - -// This function is new since the video was published void HandleClayErrors(Clay_ErrorData errorData) { printf("%s", errorData.errorText.chars); } -typedef struct { - intptr_t next; - intptr_t memory; -} Arena; - -Arena frameArena = {0}; - -Clay_RenderCommandArray CreateLayout(Clay_Context* context, float yOffset, int32_t* documentIndex) { +Clay_RenderCommandArray CreateLayout(Clay_Context* context, ClayVideoDemo_Data *data) { Clay_SetCurrentContext(context); Clay_SetDebugModeEnabled(true); // Run once per frame @@ -89,141 +15,22 @@ Clay_RenderCommandArray CreateLayout(Clay_Context* context, float yOffset, int32 .width = GetScreenWidth(), .height = GetScreenHeight() / 2 }); - Vector2 mousePosition = GetMousePosition(); - mousePosition.y -= yOffset; + mousePosition.y -= data->yOffset; Vector2 scrollDelta = GetMouseWheelMoveV(); Clay_SetPointerState( - (Clay_Vector2) { mousePosition.x, mousePosition.y }, - IsMouseButtonDown(0) + (Clay_Vector2) { mousePosition.x, mousePosition.y }, + IsMouseButtonDown(0) ); Clay_UpdateScrollContainers( - true, - (Clay_Vector2) { scrollDelta.x, scrollDelta.y }, - GetFrameTime() + true, + (Clay_Vector2) { scrollDelta.x, scrollDelta.y }, + GetFrameTime() ); - - Clay_Sizing layoutExpand = { - .width = CLAY_SIZING_GROW(0), - .height = CLAY_SIZING_GROW(0) - }; - - Clay_RectangleElementConfig contentBackgroundConfig = { - .color = { 90, 90, 90, 255 }, - .cornerRadius = CLAY_CORNER_RADIUS(8) - }; - - Clay_BeginLayout(); - // Build UI here - CLAY( - CLAY_ID("OuterContainer"), - CLAY_RECTANGLE({ .color = { 43, 41, 51, 255 } }), - CLAY_LAYOUT({ - .layoutDirection = CLAY_TOP_TO_BOTTOM, - .sizing = layoutExpand, - .padding = CLAY_PADDING_ALL(16), - .childGap = 16 - }) - ) { - CLAY( - CLAY_ID("LowerContent"), - CLAY_LAYOUT({ .sizing = layoutExpand, .childGap = 16 }) - ) { - CLAY( - CLAY_ID("Sidebar"), - CLAY_RECTANGLE(contentBackgroundConfig), - CLAY_LAYOUT({ - .layoutDirection = CLAY_TOP_TO_BOTTOM, - .padding = CLAY_PADDING_ALL(16), - .childGap = 8, - .sizing = { - .width = CLAY_SIZING_FIXED(250), - .height = CLAY_SIZING_GROW(0) - } - }) - ) { - for (int i = 0; i < documents.length; i++) { - Document document = documents.documents[i]; - Clay_LayoutConfig sidebarButtonLayout = { - .sizing = { .width = CLAY_SIZING_GROW(0) }, - .padding = CLAY_PADDING_ALL(16) - }; - - if (i == *documentIndex) { - CLAY( - CLAY_LAYOUT(sidebarButtonLayout), - CLAY_RECTANGLE({ - .color = { 120, 120, 120, 255 }, - .cornerRadius = CLAY_CORNER_RADIUS(8), - }) - ) { - CLAY_TEXT(document.title, CLAY_TEXT_CONFIG({ - .fontId = FONT_ID_BODY_16, - .fontSize = 20, - .textColor = { 255, 255, 255, 255 } - })); - } - } else { - SidebarClickData *clickData = (SidebarClickData *)frameArena.next; - *clickData = (SidebarClickData) { .requestedDocumentIndex = i, .selectedDocumentIndex = documentIndex }; - frameArena.next += sizeof(SidebarClickData); - CLAY( - CLAY_LAYOUT(sidebarButtonLayout), - Clay_OnHover(HandleSidebarInteraction, (intptr_t)clickData), - Clay_Hovered() - ? CLAY_RECTANGLE({ - .color = { 120, 120, 120, 120 }, - .cornerRadius = CLAY_CORNER_RADIUS(8) - }) - : (void)0 - ) { - CLAY_TEXT(document.title, CLAY_TEXT_CONFIG({ - .fontId = FONT_ID_BODY_16, - .fontSize = 20, - .textColor = { 255, 255, 255, 255 } - })); - } - } - } - } - - CLAY( - CLAY_ID("MainContent"), - CLAY_RECTANGLE(contentBackgroundConfig), - CLAY_SCROLL({ .vertical = true }), - CLAY_LAYOUT({ - .layoutDirection = CLAY_TOP_TO_BOTTOM, - .childGap = 16, - .padding = CLAY_PADDING_ALL(16), - .sizing = layoutExpand - }) - ) { - Document selectedDocument = documents.documents[*documentIndex]; - CLAY_TEXT(selectedDocument.title, CLAY_TEXT_CONFIG({ - .fontId = FONT_ID_BODY_16, - .fontSize = 24, - .textColor = COLOR_WHITE - })); - CLAY_TEXT(selectedDocument.contents, CLAY_TEXT_CONFIG({ - .fontId = FONT_ID_BODY_16, - .fontSize = 24, - .textColor = COLOR_WHITE - })); - } - } - } - - Clay_RenderCommandArray renderCommands = Clay_EndLayout(); - for (int i = 0; i < renderCommands.length; ++i) { - Clay_RenderCommandArray_Get(&renderCommands,i)->boundingBox.y += yOffset; - } - return renderCommands; + return ClayVideoDemo_CreateLayout(data); } - int main(void) { - frameArena = (Arena) { .memory = (intptr_t)malloc(1024) }; - frameArena.next = frameArena.memory; 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.") }, @@ -240,12 +47,14 @@ int main(void) { .width = GetScreenWidth(), .height = GetScreenHeight() / 2 }, (Clay_ErrorHandler) { HandleClayErrors }); // This final argument is new since the video was published + ClayVideoDemo_Data dataTop = ClayVideoDemo_Initialize(); Clay_Arena clayMemoryBottom = Clay_CreateArenaWithCapacityAndMemory(clayRequiredMemory, malloc(clayRequiredMemory)); Clay_Context *clayContextBottom = Clay_Initialize(clayMemoryBottom, (Clay_Dimensions) { .width = GetScreenWidth(), .height = GetScreenHeight() / 2 }, (Clay_ErrorHandler) { HandleClayErrors }); // This final argument is new since the video was published + ClayVideoDemo_Data dataBottom = ClayVideoDemo_Initialize(); Clay_SetMeasureTextFunction(Raylib_MeasureText, 0); Raylib_fonts[FONT_ID_BODY_16] = (Raylib_Font) { @@ -255,9 +64,9 @@ int main(void) { SetTextureFilter(Raylib_fonts[FONT_ID_BODY_16].font.texture, TEXTURE_FILTER_BILINEAR); while (!WindowShouldClose()) { - frameArena.next = frameArena.memory; - Clay_RenderCommandArray renderCommandsTop = CreateLayout(clayContextTop, 0, &selectedDocumentIndexTop); - Clay_RenderCommandArray renderCommandsBottom = CreateLayout(clayContextBottom, GetScreenHeight() / 2, &selectedDocumentIndexBottom); + dataBottom.yOffset = GetScreenHeight() / 2; + Clay_RenderCommandArray renderCommandsTop = CreateLayout(clayContextTop, &dataTop); + Clay_RenderCommandArray renderCommandsBottom = CreateLayout(clayContextBottom, &dataBottom); BeginDrawing(); ClearBackground(BLACK); Clay_Raylib_Render(renderCommandsTop); diff --git a/examples/raylib-sidebar-scrolling-container/CMakeLists.txt b/examples/raylib-sidebar-scrolling-container/CMakeLists.txt index 94ee26b..a8072f6 100644 --- a/examples/raylib-sidebar-scrolling-container/CMakeLists.txt +++ b/examples/raylib-sidebar-scrolling-container/CMakeLists.txt @@ -25,10 +25,10 @@ target_include_directories(clay_examples_raylib_sidebar_scrolling_container PUBL target_link_libraries(clay_examples_raylib_sidebar_scrolling_container PUBLIC raylib) if(MSVC) - set(CMAKE_C_FLAGS_DEBUG "/D CLAY_DEBUG") + set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}") else() set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}") - set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -O3") + set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}") endif() add_custom_command( diff --git a/examples/raylib-sidebar-scrolling-container/main.c b/examples/raylib-sidebar-scrolling-container/main.c index 1b486d7..7d01d49 100644 --- a/examples/raylib-sidebar-scrolling-container/main.c +++ b/examples/raylib-sidebar-scrolling-container/main.c @@ -19,11 +19,17 @@ void HandleHeaderButtonInteraction(Clay_ElementId elementId, Clay_PointerData po } } +Clay_ElementDeclaration headerButtonStyle = { + .layout = {.padding = {16, 16, 8, 8}}, + .rectangle = { .color = COLOR_BLUE } +}; + // Examples of re-usable "Components" void RenderHeaderButton(Clay_String text) { - CLAY(CLAY_LAYOUT({ .padding = {16, 16, 8, 8} }), - CLAY_RECTANGLE({ .color = Clay_Hovered() ? COLOR_BLUE : COLOR_ORANGE }), - Clay_OnHover(HandleHeaderButtonInteraction, 1)) { + CLAY(headerButtonStyle) { + if (Clay_Hovered()) { + Clay_CurrentConfigRectangle()->color = COLOR_ORANGE; + } CLAY_TEXT(text, CLAY_TEXT_CONFIG(headerTextConfig)); } } @@ -33,52 +39,53 @@ Clay_RectangleElementConfig dropdownRectangleConfig = { .color = {180, 180, 180, Clay_TextElementConfig dropdownTextElementConfig = { .fontSize = 24, .textColor = {255,255,255,255} }; void RenderDropdownTextItem(int index) { - CLAY(CLAY_IDI("ScrollContainerItem", index), CLAY_LAYOUT(dropdownTextItemLayout), CLAY_RECTANGLE(dropdownRectangleConfig)) { + CLAY({ .id = CLAY_IDI("ScrollContainerItem", index), .layout = dropdownTextItemLayout, .rectangle = dropdownRectangleConfig }) { CLAY_TEXT(CLAY_STRING("I'm a text field in a scroll container."), &dropdownTextElementConfig); } } Clay_RenderCommandArray CreateLayout() { Clay_BeginLayout(); - CLAY(CLAY_ID("OuterContainer"), CLAY_LAYOUT({ .sizing = { .width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_GROW(0) }, .padding = { 16, 16, 16, 16 }, .childGap = 16 }), CLAY_RECTANGLE({ .color = {200, 200, 200, 255} })) { - CLAY(CLAY_ID("SideBar"), CLAY_LAYOUT({ .layoutDirection = CLAY_TOP_TO_BOTTOM, .sizing = { .width = CLAY_SIZING_FIXED(300), .height = CLAY_SIZING_GROW(0) }, .padding = {16, 16, 16, 16 }, .childGap = 16 }), CLAY_RECTANGLE({ .color = {150, 150, 255, 255} })) { - CLAY(CLAY_ID("ProfilePictureOuter"), CLAY_LAYOUT({ .sizing = { .width = CLAY_SIZING_GROW(0) }, .padding = { 8, 8, 8, 8 }, .childGap = 8, .childAlignment = { .y = CLAY_ALIGN_Y_CENTER } }), CLAY_RECTANGLE({ .color = {130, 130, 255, 255} })) { - CLAY(CLAY_ID("ProfilePicture"), CLAY_LAYOUT({ .sizing = { .width = CLAY_SIZING_FIXED(60), .height = CLAY_SIZING_FIXED(60) } }), CLAY_IMAGE({ .imageData = &profilePicture, .sourceDimensions = {60, 60} })) {} + 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("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(CLAY_ID("SidebarBlob1"), CLAY_LAYOUT({ .sizing = { .width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_FIXED(50) }}), CLAY_RECTANGLE({ .color = {110, 110, 255, 255} })) {} - CLAY(CLAY_ID("SidebarBlob2"), CLAY_LAYOUT({ .sizing = { .width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_FIXED(50) }}), CLAY_RECTANGLE({ .color = {110, 110, 255, 255} })) {} - CLAY(CLAY_ID("SidebarBlob3"), CLAY_LAYOUT({ .sizing = { .width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_FIXED(50) }}), CLAY_RECTANGLE({ .color = {110, 110, 255, 255} })) {} - CLAY(CLAY_ID("SidebarBlob4"), CLAY_LAYOUT({ .sizing = { .width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_FIXED(50) }}), CLAY_RECTANGLE({ .color = {110, 110, 255, 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(CLAY_ID("RightPanel"), CLAY_LAYOUT({ .layoutDirection = CLAY_TOP_TO_BOTTOM, .sizing = { .width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_GROW(0) }, .childGap = 16 })) { - CLAY(CLAY_ID("HeaderBar"), CLAY_LAYOUT({ .sizing = { .width = CLAY_SIZING_GROW(0) }, .childAlignment = { .x = CLAY_ALIGN_X_RIGHT }, .padding = {8, 8, 8, 8 }, .childGap = 8 }), CLAY_RECTANGLE({ .color = {180, 180, 180, 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} }}) { RenderHeaderButton(CLAY_STRING("Header Item 1")); RenderHeaderButton(CLAY_STRING("Header Item 2")); RenderHeaderButton(CLAY_STRING("Header Item 3")); } - CLAY(CLAY_ID("MainContent"), - CLAY_SCROLL({ .vertical = true }), - CLAY_LAYOUT({ .layoutDirection = CLAY_TOP_TO_BOTTOM, .padding = {16, 16, 16, 16}, .childGap = 16, .sizing = { CLAY_SIZING_GROW(0) } }), - CLAY_RECTANGLE({ .color = {200, 200, 255, 255} })) + 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} } + }) { - CLAY(CLAY_ID("FloatingContainer"), - CLAY_LAYOUT({ .sizing = { .width = CLAY_SIZING_FIXED(300), .height = CLAY_SIZING_FIXED(300) }, .padding = { 16, 16, 16, 16 }}), - CLAY_FLOATING({ .zIndex = 1, .attachment = { CLAY_ATTACH_POINT_CENTER_TOP, CLAY_ATTACH_POINT_CENTER_TOP }, .offset = {0, 0} }), - CLAY_BORDER_OUTSIDE({ .color = {80, 80, 80, 255}, .width = 2 }), - CLAY_RECTANGLE({ .color = {140,80, 200, 200 }}) - ) { + CLAY({ .id = CLAY_ID("FloatingContainer"), + .layout = { .sizing = { .width = CLAY_SIZING_FIXED(300), .height = CLAY_SIZING_FIXED(300) }, .padding = { 16, 16, 16, 16 }}, + .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 }} + }) { CLAY_TEXT(CLAY_STRING("I'm an inline floating container."), CLAY_TEXT_CONFIG({ .fontSize = 24, .textColor = {255,255,255,255} })); } 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(CLAY_ID("Photos2"), CLAY_LAYOUT({ .childGap = 16, .padding = { 16, 16, 16, 16 }}), CLAY_RECTANGLE({ .color = {180, 180, 220, 255} })) { - CLAY(CLAY_ID("Picture4"), CLAY_LAYOUT({ .sizing = { .width = CLAY_SIZING_FIXED(120), .height = CLAY_SIZING_FIXED(120) }}), CLAY_IMAGE({ .imageData = &profilePicture, .sourceDimensions = {120, 120} })) {} - CLAY(CLAY_ID("Picture5"), CLAY_LAYOUT({ .sizing = { .width = CLAY_SIZING_FIXED(120), .height = CLAY_SIZING_FIXED(120) }}), CLAY_IMAGE({ .imageData = &profilePicture, .sourceDimensions = {120, 120} })) {} - CLAY(CLAY_ID("Picture6"), CLAY_LAYOUT({ .sizing = { .width = CLAY_SIZING_FIXED(120), .height = CLAY_SIZING_FIXED(120) }}), CLAY_IMAGE({ .imageData = &profilePicture, .sourceDimensions = {120, 120} })) {} + CLAY({ .id = CLAY_ID("Photos2"), .layout = { .childGap = 16, .padding = { 16, 16, 16, 16 }}, .rectangle = { .color = {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} }}) {} } CLAY_TEXT(CLAY_STRING("Faucibus purus in massa tempor nec. Nec ullamcorper sit amet risus nullam eget felis eget nunc. Diam vulputate ut pharetra sit amet aliquam id diam. Lacus suspendisse faucibus interdum posuere lorem. A diam sollicitudin tempor id. Amet massa vitae tortor condimentum lacinia. Aliquet nibh praesent tristique magna."), @@ -87,13 +94,13 @@ Clay_RenderCommandArray CreateLayout() { 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(CLAY_ID("Photos"), CLAY_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} }), CLAY_RECTANGLE({ .color = {180, 180, 220, 255} })) { - CLAY(CLAY_ID("Picture2"), CLAY_LAYOUT({ .sizing = { .width = CLAY_SIZING_FIXED(120), .height = CLAY_SIZING_FIXED(120) }}), CLAY_IMAGE({ .imageData = &profilePicture, .sourceDimensions = {120, 120} })) {} - CLAY(CLAY_ID("Picture1"), CLAY_LAYOUT({ .childAlignment = { .x = CLAY_ALIGN_X_CENTER }, .layoutDirection = CLAY_TOP_TO_BOTTOM, .padding = {8, 8, 8, 8} }), CLAY_RECTANGLE({ .color = {170, 170, 220, 255} })) { - CLAY(CLAY_ID("ProfilePicture2"), CLAY_LAYOUT({ .sizing = { .width = CLAY_SIZING_FIXED(60), .height = CLAY_SIZING_FIXED(60) }}), CLAY_IMAGE({ .imageData = &profilePicture, .sourceDimensions = {60, 60} })) {} + 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("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("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} })); } - CLAY(CLAY_ID("Picture3"), CLAY_LAYOUT({ .sizing = { .width = CLAY_SIZING_FIXED(120), .height = CLAY_SIZING_FIXED(120) }}), CLAY_IMAGE({ .imageData = &profilePicture, .sourceDimensions = {120, 120} })) {} + CLAY({ .id = CLAY_ID("Picture3"), .layout = { .sizing = { .width = CLAY_SIZING_FIXED(120), .height = CLAY_SIZING_FIXED(120) }}, .image = { .imageData = &profilePicture, .sourceDimensions = {120, 120} }}) {} } CLAY_TEXT(CLAY_STRING("Amet cursus sit amet dictum sit amet justo donec. Et malesuada fames ac turpis egestas maecenas. A lacus vestibulum sed arcu non odio euismod lacinia. Gravida neque convallis a cras. Dui nunc mattis enim ut tellus elementum sagittis vitae et. Orci sagittis eu volutpat odio facilisis mauris. Neque gravida in fermentum et sollicitudin ac orci. Ultrices dui sapien eget mi proin sed libero. Euismod quis viverra nibh cras pulvinar mattis. Diam volutpat commodo sed egestas egestas. In fermentum posuere urna nec tincidunt praesent semper. Integer eget aliquet nibh praesent tristique magna.\nId cursus metus aliquam eleifend mi in. Sed pulvinar proin gravida hendrerit lectus a. Etiam tempor orci eu lobortis elementum nibh tellus. Nullam vehicula ipsum a arcu cursus vitae. Elit scelerisque mauris pellentesque pulvinar pellentesque habitant morbi tristique senectus. Condimentum lacinia quis vel eros donec ac odio. Mattis pellentesque id nibh tortor id aliquet lectus. Turpis egestas integer eget aliquet nibh praesent tristique. Porttitor massa id neque aliquam vestibulum morbi. Mauris commodo quis imperdiet massa tincidunt nunc pulvinar sapien et. Nunc scelerisque viverra mauris in aliquam sem fringilla. Suspendisse ultrices gravida dictum fusce ut placerat orci nulla.\nLacus laoreet non curabitur gravida arcu ac tortor dignissim. Urna nec tincidunt praesent semper feugiat nibh sed pulvinar. Tristique senectus et netus et malesuada fames ac. Nunc aliquet bibendum enim facilisis gravida. Egestas maecenas pharetra convallis posuere morbi leo urna molestie. Sapien nec sagittis aliquam malesuada bibendum arcu vitae elementum curabitur. Ac turpis egestas maecenas pharetra convallis posuere morbi leo urna. Viverra vitae congue eu consequat. Aliquet enim tortor at auctor urna. Ornare massa eget egestas purus viverra accumsan in nisl nisi. Elit pellentesque habitant morbi tristique senectus et netus et malesuada.\nSuspendisse ultrices gravida dictum fusce ut placerat orci nulla pellentesque. Lobortis feugiat vivamus at augue eget arcu. Vitae justo eget magna fermentum iaculis eu. Gravida rutrum quisque non tellus orci. Ipsum faucibus vitae aliquet nec. Nullam non nisi est sit amet. Nunc consequat interdum varius sit amet mattis vulputate enim. Sem fringilla ut morbi tincidunt augue interdum. Vitae purus faucibus ornare suspendisse. Massa tincidunt nunc pulvinar sapien et. Fringilla ut morbi tincidunt augue interdum velit euismod in. Donec massa sapien faucibus et. Est placerat in egestas erat imperdiet. Gravida rutrum quisque non tellus. Morbi non arcu risus quis varius quam quisque id diam. Habitant morbi tristique senectus et netus et malesuada fames ac. Eget lorem dolor sed viverra.\nOrnare massa eget egestas purus viverra. Varius vel pharetra vel turpis nunc eget lorem. Consectetur purus ut faucibus pulvinar elementum. Placerat in egestas erat imperdiet sed euismod nisi. Interdum velit euismod in pellentesque massa placerat duis ultricies lacus. Aliquam nulla facilisi cras fermentum odio eu. Est pellentesque elit ullamcorper dignissim cras tincidunt. Nunc sed id semper risus in hendrerit gravida rutrum. A pellentesque sit amet porttitor eget dolor morbi. Pellentesque habitant morbi tristique senectus et netus et malesuada fames. Nisl nunc mi ipsum faucibus vitae aliquet nec ullamcorper. Sed id semper risus in hendrerit gravida. Tincidunt praesent semper feugiat nibh. Aliquet lectus proin nibh nisl condimentum id venenatis a. Enim sit amet venenatis urna cursus eget. In egestas erat imperdiet sed euismod nisi porta lorem mollis. Lacinia quis vel eros donec ac odio tempor orci. Donec pretium vulputate sapien nec sagittis aliquam malesuada bibendum arcu. Erat pellentesque adipiscing commodo elit at.\nEgestas sed sed risus pretium quam vulputate. Vitae congue mauris rhoncus aenean vel elit scelerisque mauris pellentesque. Aliquam malesuada bibendum arcu vitae elementum. Congue mauris rhoncus aenean vel elit scelerisque mauris. Pellentesque dignissim enim sit amet venenatis urna cursus. Et malesuada fames ac turpis egestas sed tempus urna. Vel fringilla est ullamcorper eget nulla facilisi etiam dignissim. Nibh cras pulvinar mattis nunc sed blandit libero. Fringilla est ullamcorper eget nulla facilisi etiam dignissim. Aenean euismod elementum nisi quis eleifend quam adipiscing vitae proin. Mauris pharetra et ultrices neque ornare aenean euismod elementum. Ornare quam viverra orci sagittis eu. Odio ut sem nulla pharetra diam sit amet nisl suscipit. Ornare lectus sit amet est. Ullamcorper sit amet risus nullam eget. Tincidunt lobortis feugiat vivamus at augue eget arcu dictum.\nUrna nec tincidunt praesent semper feugiat nibh. Ut venenatis tellus in metus vulputate eu scelerisque felis. Cursus risus at ultrices mi tempus. In pellentesque massa placerat duis ultricies lacus sed turpis. Platea dictumst quisque sagittis purus. Cras adipiscing enim eu turpis egestas. Egestas sed tempus urna et pharetra pharetra. Netus et malesuada fames ac turpis egestas integer eget aliquet. Ac turpis egestas sed tempus. Sed lectus vestibulum mattis ullamcorper velit sed. Ante metus dictum at tempor commodo ullamcorper a. Augue neque gravida in fermentum et sollicitudin ac. Praesent semper feugiat nibh sed pulvinar proin gravida. Metus aliquam eleifend mi in nulla posuere sollicitudin aliquam ultrices. Neque gravida in fermentum et sollicitudin ac orci phasellus egestas.\nRidiculus mus mauris vitae ultricies. Morbi quis commodo odio aenean. Duis ultricies lacus sed turpis. Non pulvinar neque laoreet suspendisse interdum consectetur. Scelerisque eleifend donec pretium vulputate sapien nec sagittis aliquam. Volutpat est velit egestas dui id ornare arcu odio ut. Viverra tellus in hac habitasse platea dictumst vestibulum rhoncus est. Vestibulum lectus mauris ultrices eros. Sed blandit libero volutpat sed cras ornare. Id leo in vitae turpis massa sed elementum tempus. Gravida dictum fusce ut placerat orci nulla pellentesque. Pretium quam vulputate dignissim suspendisse in. Nisl suscipit adipiscing bibendum est ultricies integer quis auctor. Risus viverra adipiscing at in tellus. Turpis nunc eget lorem dolor sed viverra ipsum. Senectus et netus et malesuada fames ac. Habitasse platea dictumst vestibulum rhoncus est. Nunc sed id semper risus in hendrerit gravida. Felis eget velit aliquet sagittis id. Eget felis eget nunc lobortis.\nMaecenas pharetra convallis posuere morbi leo. Maecenas volutpat blandit aliquam etiam. A condimentum vitae sapien pellentesque habitant morbi tristique senectus et. Pulvinar mattis nunc sed blandit libero volutpat sed. Feugiat in ante metus dictum at tempor commodo ullamcorper. Vel pharetra vel turpis nunc eget lorem dolor. Est placerat in egestas erat imperdiet sed euismod. Quisque non tellus orci ac auctor augue mauris augue. Placerat vestibulum lectus mauris ultrices eros in cursus turpis. Enim nunc faucibus a pellentesque sit. Adipiscing vitae proin sagittis nisl. Iaculis at erat pellentesque adipiscing commodo elit at imperdiet. Aliquam sem fringilla ut morbi.\nArcu odio ut sem nulla pharetra diam sit amet nisl. Non diam phasellus vestibulum lorem sed. At erat pellentesque adipiscing commodo elit at. Lacus luctus accumsan tortor posuere ac ut consequat. Et malesuada fames ac turpis egestas integer. Tristique magna sit amet purus. A condimentum vitae sapien pellentesque habitant. Quis varius quam quisque id diam vel quam. Est ullamcorper eget nulla facilisi etiam dignissim diam quis. Augue interdum velit euismod in pellentesque massa. Elit scelerisque mauris pellentesque pulvinar pellentesque habitant. Vulputate eu scelerisque felis imperdiet. Nibh tellus molestie nunc non blandit massa. Velit euismod in pellentesque massa placerat. Sed cras ornare arcu dui. Ut sem viverra aliquet eget sit. Eu lobortis elementum nibh tellus molestie nunc non. Blandit libero volutpat sed cras ornare arcu dui vivamus.\nSit amet aliquam id diam maecenas. Amet risus nullam eget felis eget nunc lobortis mattis aliquam. Magna sit amet purus gravida. Egestas purus viverra accumsan in nisl nisi. Leo duis ut diam quam. Ante metus dictum at tempor commodo ullamcorper. Ac turpis egestas integer eget. Fames ac turpis egestas integer eget aliquet nibh. Sem integer vitae justo eget magna fermentum. Semper auctor neque vitae tempus quam pellentesque nec nam aliquam. Vestibulum mattis ullamcorper velit sed. Consectetur adipiscing elit duis tristique sollicitudin nibh. Massa id neque aliquam vestibulum morbi blandit cursus risus.\nCursus sit amet dictum sit amet justo donec enim diam. Egestas erat imperdiet sed euismod. Nullam vehicula ipsum a arcu cursus vitae congue mauris. Habitasse platea dictumst vestibulum rhoncus est pellentesque elit. Duis ultricies lacus sed turpis tincidunt id aliquet risus feugiat. Faucibus ornare suspendisse sed nisi lacus sed viverra. Pretium fusce id velit ut tortor pretium viverra. Fermentum odio eu feugiat pretium nibh ipsum consequat nisl vel. Senectus et netus et malesuada. Tellus pellentesque eu tincidunt tortor aliquam. Aenean sed adipiscing diam donec adipiscing tristique risus nec feugiat. Quis vel eros donec ac odio. Id interdum velit laoreet id donec ultrices tincidunt.\nMassa id neque aliquam vestibulum morbi blandit cursus risus at. Enim tortor at auctor urna nunc id cursus metus. Lorem ipsum dolor sit amet consectetur. At quis risus sed vulputate odio. Facilisis mauris sit amet massa vitae tortor condimentum lacinia quis. Et malesuada fames ac turpis egestas maecenas. Bibendum arcu vitae elementum curabitur vitae nunc sed velit dignissim. Viverra orci sagittis eu volutpat odio facilisis mauris. Adipiscing bibendum est ultricies integer quis auctor elit sed. Neque viverra justo nec ultrices dui sapien. Elementum nibh tellus molestie nunc non blandit massa enim. Euismod elementum nisi quis eleifend quam adipiscing vitae proin sagittis. Faucibus ornare suspendisse sed nisi. Quis viverra nibh cras pulvinar mattis nunc sed blandit. Tristique senectus et netus et. Magnis dis parturient montes nascetur ridiculus mus.\nDolor magna eget est lorem ipsum dolor. Nibh sit amet commodo nulla. Donec pretium vulputate sapien nec sagittis aliquam malesuada. Cras adipiscing enim eu turpis egestas pretium. Cras ornare arcu dui vivamus arcu felis bibendum ut tristique. Mus mauris vitae ultricies leo integer. In nulla posuere sollicitudin aliquam ultrices sagittis orci. Quis hendrerit dolor magna eget. Nisl tincidunt eget nullam non. Vitae congue eu consequat ac felis donec et odio. Vivamus at augue eget arcu dictum varius duis at. Ornare quam viverra orci sagittis.\nErat nam at lectus urna duis convallis. Massa placerat duis ultricies lacus sed turpis tincidunt id aliquet. Est ullamcorper eget nulla facilisi etiam dignissim diam. Arcu vitae elementum curabitur vitae nunc sed velit dignissim sodales. Tortor vitae purus faucibus ornare suspendisse sed nisi lacus. Neque viverra justo nec ultrices dui sapien eget mi proin. Viverra accumsan in nisl nisi scelerisque eu ultrices. Consequat interdum varius sit amet mattis. In aliquam sem fringilla ut morbi. Eget arcu dictum varius duis at. Nulla aliquet porttitor lacus luctus accumsan tortor posuere. Arcu bibendum at varius vel pharetra vel turpis. Hac habitasse platea dictumst quisque sagittis purus sit amet. Sapien eget mi proin sed libero enim sed. Quam elementum pulvinar etiam non quam lacus suspendisse faucibus interdum. Semper viverra nam libero justo. Fusce ut placerat orci nulla pellentesque dignissim enim sit amet. Et malesuada fames ac turpis egestas maecenas pharetra convallis posuere.\nTurpis egestas sed tempus urna et pharetra pharetra massa. Gravida in fermentum et sollicitudin ac orci phasellus. Ornare suspendisse sed nisi lacus sed viverra tellus in. Fames ac turpis egestas maecenas pharetra convallis posuere. Mi proin sed libero enim sed faucibus turpis. Sit amet mauris commodo quis imperdiet massa tincidunt nunc. Ut etiam sit amet nisl purus in mollis nunc. Habitasse platea dictumst quisque sagittis purus sit amet volutpat consequat. Eget aliquet nibh praesent tristique magna. Sit amet est placerat in egestas erat. Commodo sed egestas egestas fringilla. Enim nulla aliquet porttitor lacus luctus accumsan tortor posuere ac. Et molestie ac feugiat sed lectus vestibulum mattis ullamcorper. Dignissim convallis aenean et tortor at risus viverra. Morbi blandit cursus risus at ultrices mi. Ac turpis egestas integer eget aliquet nibh praesent tristique magna.\nVolutpat sed cras ornare arcu dui. Egestas erat imperdiet sed euismod nisi porta lorem mollis aliquam. Viverra justo nec ultrices dui sapien. Amet risus nullam eget felis eget nunc lobortis. Metus aliquam eleifend mi in. Ut eu sem integer vitae. Auctor elit sed vulputate mi sit amet. Nisl nisi scelerisque eu ultrices. Dictum fusce ut placerat orci nulla. Pellentesque habitant morbi tristique senectus et. Auctor elit sed vulputate mi sit. Tincidunt arcu non sodales neque. Mi in nulla posuere sollicitudin aliquam. Morbi non arcu risus quis varius quam quisque id diam. Cras adipiscing enim eu turpis egestas pretium aenean pharetra magna. At auctor urna nunc id cursus metus aliquam. Mauris a diam maecenas sed enim ut sem viverra. Nunc scelerisque viverra mauris in. In iaculis nunc sed augue lacus viverra vitae congue eu. Volutpat blandit aliquam etiam erat velit scelerisque in dictum non."), @@ -101,14 +108,14 @@ Clay_RenderCommandArray CreateLayout() { } } - CLAY(CLAY_ID("Blob4Floating2"), CLAY_FLOATING({ .zIndex = 1, .parentId = Clay_GetElementId(CLAY_STRING("SidebarBlob4")).id })) { - CLAY(CLAY_ID("ScrollContainer"), CLAY_LAYOUT({ .sizing = { .height = CLAY_SIZING_FIXED(200) }, .childGap = 2 }), CLAY_SCROLL({ .vertical = true })) { - CLAY(CLAY_ID("FloatingContainer2"), CLAY_LAYOUT({ }), CLAY_FLOATING({ .zIndex = 1 })) { - CLAY(CLAY_ID("FloatingContainerInner"), CLAY_LAYOUT({ .sizing = { .width = CLAY_SIZING_FIXED(300), .height = CLAY_SIZING_FIXED(300) }, .padding = {16, 16, 16, 16} }), CLAY_RECTANGLE({ .color = {140,80, 200, 200} })) { + 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_TEXT(CLAY_STRING("I'm an inline floating container."), CLAY_TEXT_CONFIG({ .fontSize = 24, .textColor = {255,255,255,255} })); } } - CLAY(CLAY_ID("ScrollContainerInner"), CLAY_LAYOUT({ .layoutDirection = CLAY_TOP_TO_BOTTOM }), CLAY_RECTANGLE({ .color = {160, 160, 160, 255} })) { + CLAY({ .id = CLAY_ID("ScrollContainerInner"), .layout = { .layoutDirection = CLAY_TOP_TO_BOTTOM }, .rectangle = { .color = {160, 160, 160, 255} } }) { for (int i = 0; i < 100; i++) { RenderDropdownTextItem(i); } @@ -117,18 +124,19 @@ Clay_RenderCommandArray CreateLayout() { } Clay_ScrollContainerData scrollData = Clay_GetScrollContainerData(Clay_GetElementId(CLAY_STRING("MainContent"))); if (scrollData.found) { - CLAY(CLAY_ID("ScrollBar"), - CLAY_FLOATING({ + CLAY({ .id = CLAY_ID("ScrollBar"), + .floating = { .offset = { .y = -(scrollData.scrollPosition->y / scrollData.contentDimensions.height) * scrollData.scrollContainerDimensions.height }, .zIndex = 1, .parentId = Clay_GetElementId(CLAY_STRING("MainContent")).id, .attachment = {.element = CLAY_ATTACH_POINT_RIGHT_TOP, .parent = CLAY_ATTACH_POINT_RIGHT_TOP} - }) - ) { - CLAY(CLAY_ID("ScrollBarButton"), - CLAY_LAYOUT({ .sizing = {CLAY_SIZING_FIXED(12), CLAY_SIZING_FIXED((scrollData.scrollContainerDimensions.height / scrollData.contentDimensions.height) * scrollData.scrollContainerDimensions.height) }}), - CLAY_RECTANGLE({ .cornerRadius = {6}, .color = Clay_PointerOver(Clay__HashString(CLAY_STRING("ScrollBar"), 0, 0)) ? (Clay_Color){100, 100, 140, 150} : (Clay_Color){120, 120, 160, 150} }) - ) {} + } + }) { + 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) } + }) {} } } } diff --git a/examples/raylib-sidebar-scrolling-container/multi-compilation-unit.c b/examples/raylib-sidebar-scrolling-container/multi-compilation-unit.c index 2c1a473..a357cec 100644 --- a/examples/raylib-sidebar-scrolling-container/multi-compilation-unit.c +++ b/examples/raylib-sidebar-scrolling-container/multi-compilation-unit.c @@ -3,7 +3,7 @@ // NOTE: This file only exists to make sure that clay works when included in multiple translation units. void SatisfyCompiler() { - CLAY(CLAY_ID("SatisfyCompiler"), CLAY_LAYOUT({})) { + CLAY({ .id = CLAY_ID("SatisfyCompiler") }) { CLAY_TEXT(CLAY_STRING("Test"), CLAY_TEXT_CONFIG({ .fontId = 0, .fontSize = 24 })); } } \ No newline at end of file diff --git a/examples/shared-layouts/clay-video-demo.c b/examples/shared-layouts/clay-video-demo.c new file mode 100644 index 0000000..3042893 --- /dev/null +++ b/examples/shared-layouts/clay-video-demo.c @@ -0,0 +1,279 @@ +#include "../../clay.h" +#include + +const int FONT_ID_BODY_16 = 0; +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) } + }) { + CLAY_TEXT(text, CLAY_TEXT_CONFIG({ + .fontId = FONT_ID_BODY_16, + .fontSize = 16, + .textColor = { 255, 255, 255, 255 } + })); + } +} + +void RenderDropdownMenuItem(Clay_String text) { + CLAY({.layout = { .padding = CLAY_PADDING_ALL(16)}}) { + CLAY_TEXT(text, CLAY_TEXT_CONFIG({ + .fontId = FONT_ID_BODY_16, + .fontSize = 16, + .textColor = { 255, 255, 255, 255 } + })); + } +} + +typedef struct { + Clay_String title; + Clay_String contents; +} Document; + +typedef struct { + Document *documents; + uint32_t length; +} DocumentArray; + +Document documentsRaw[5] ={ + { .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") }, +}; + +DocumentArray documents = { + .length = 5, + .documents = documentsRaw +}; + +typedef struct { + intptr_t offset; + intptr_t memory; +} ClayVideoDemo_Arena; + +typedef struct { + int32_t selectedDocumentIndex; + float yOffset; + ClayVideoDemo_Arena frameArena; +} ClayVideoDemo_Data; + +typedef struct { + int32_t requestedDocumentIndex; + int32_t* selectedDocumentIndex; +} SidebarClickData; + +void HandleSidebarInteraction( + Clay_ElementId elementId, + Clay_PointerData pointerData, + intptr_t userData +) { + SidebarClickData *clickData = (SidebarClickData*)userData; + // If this button was clicked + if (pointerData.state == CLAY_POINTER_DATA_PRESSED_THIS_FRAME) { + if (clickData->requestedDocumentIndex >= 0 && clickData->requestedDocumentIndex < documents.length) { + // Select the corresponding document + *clickData->selectedDocumentIndex = clickData->requestedDocumentIndex; + } + } +} + +ClayVideoDemo_Data ClayVideoDemo_Initialize() { + ClayVideoDemo_Data data = { + .frameArena = { .memory = (intptr_t)malloc(1024) } + }; + return data; +} + +Clay_RenderCommandArray ClayVideoDemo_CreateLayout(ClayVideoDemo_Data *data) { + data->frameArena.offset = 0; + + Clay_BeginLayout(); + + Clay_Sizing layoutExpand = { + .width = CLAY_SIZING_GROW(0), + .height = CLAY_SIZING_GROW(0) + }; + + Clay_RectangleElementConfig contentBackgroundConfig = { + .color = { 90, 90, 90, 255 }, + }; + + // Build UI here + CLAY({ .id = CLAY_ID("OuterContainer"), + .rectangle = { .color = { 43, 41, 51, 255 } }, + .layout = { + .layoutDirection = CLAY_TOP_TO_BOTTOM, + .sizing = layoutExpand, + .padding = CLAY_PADDING_ALL(16), + .childGap = 16 + } + }) { + // Child elements go inside braces + CLAY({ .id = CLAY_ID("HeaderBar"), + .rectangle = contentBackgroundConfig, + .layout = { + .sizing = { + .height = CLAY_SIZING_FIXED(60), + .width = CLAY_SIZING_GROW(0) + }, + .padding = { 16, 16, 0, 0 }, + .childGap = 16, + .childAlignment = { + .y = CLAY_ALIGN_Y_CENTER + } + }, + .shared = { .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) } + }) { + CLAY_TEXT(CLAY_STRING("File"), CLAY_TEXT_CONFIG({ + .fontId = FONT_ID_BODY_16, + .fontSize = 16, + .textColor = { 255, 255, 255, 255 } + })); + + bool fileMenuVisible = + Clay_PointerOver(Clay_GetElementId(CLAY_STRING("FileButton"))) + || + Clay_PointerOver(Clay_GetElementId(CLAY_STRING("FileMenu"))); + + if (fileMenuVisible) { // Below has been changed slightly to fix the small bug where the menu would dismiss when mousing over the top gap + CLAY({ .id = CLAY_ID("FileMenu"), + .floating = { + .attachment = { + .parent = CLAY_ATTACH_POINT_LEFT_BOTTOM + }, + }, + .layout = { + .padding = {0, 0, 8, 8 } + } + }) { + CLAY({ + .layout = { + .layoutDirection = CLAY_TOP_TO_BOTTOM, + .sizing = { + .width = CLAY_SIZING_FIXED(200) + }, + }, + .rectangle ={ + .color = { 40, 40, 40, 255 }, + }, + .shared = { .cornerRadius = CLAY_CORNER_RADIUS(8) } + }) { + // Render dropdown items here + RenderDropdownMenuItem(CLAY_STRING("New")); + RenderDropdownMenuItem(CLAY_STRING("Open")); + RenderDropdownMenuItem(CLAY_STRING("Close")); + } + } + } + } + RenderHeaderButton(CLAY_STRING("Edit")); + CLAY({ .layout = { .sizing = { CLAY_SIZING_GROW(0) }}}) {} + RenderHeaderButton(CLAY_STRING("Upload")); + RenderHeaderButton(CLAY_STRING("Media")); + RenderHeaderButton(CLAY_STRING("Support")); + } + + CLAY({ + .id = CLAY_ID("LowerContent"), + .layout = { .sizing = layoutExpand, .childGap = 16 } + }) { + CLAY({ + .id = CLAY_ID("Sidebar"), + .rectangle = contentBackgroundConfig, + .layout = { + .layoutDirection = CLAY_TOP_TO_BOTTOM, + .padding = CLAY_PADDING_ALL(16), + .childGap = 8, + .sizing = { + .width = CLAY_SIZING_FIXED(250), + .height = CLAY_SIZING_GROW(0) + } + } + }) { + for (int i = 0; i < documents.length; i++) { + Document document = documents.documents[i]; + Clay_LayoutConfig sidebarButtonLayout = { + .sizing = { .width = CLAY_SIZING_GROW(0) }, + .padding = CLAY_PADDING_ALL(16) + }; + + if (i == data->selectedDocumentIndex) { + CLAY({ + .layout = sidebarButtonLayout, + .rectangle = { + .color = { 120, 120, 120, 255 }, + }, + .shared = { .cornerRadius = CLAY_CORNER_RADIUS(8) } + }) { + CLAY_TEXT(document.title, CLAY_TEXT_CONFIG({ + .fontId = FONT_ID_BODY_16, + .fontSize = 20, + .textColor = { 255, 255, 255, 255 } + })); + } + } else { + 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_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, + .textColor = { 255, 255, 255, 255 } + })); + } + } + } + } + + CLAY({ .id = CLAY_ID("MainContent"), + .rectangle = contentBackgroundConfig, + .scroll = { .vertical = true }, + .layout = { + .layoutDirection = CLAY_TOP_TO_BOTTOM, + .childGap = 16, + .padding = CLAY_PADDING_ALL(16), + .sizing = layoutExpand + } + }) { + Document selectedDocument = documents.documents[data->selectedDocumentIndex]; + CLAY_TEXT(selectedDocument.title, CLAY_TEXT_CONFIG({ + .fontId = FONT_ID_BODY_16, + .fontSize = 24, + .textColor = COLOR_WHITE + })); + CLAY_TEXT(selectedDocument.contents, CLAY_TEXT_CONFIG({ + .fontId = FONT_ID_BODY_16, + .fontSize = 24, + .textColor = COLOR_WHITE + })); + } + } + } + + Clay_RenderCommandArray renderCommands = Clay_EndLayout(); + for (int32_t i = 0; i < renderCommands.length; i++) { + Clay_RenderCommandArray_Get(&renderCommands, i)->boundingBox.y += data->yOffset; + } + return renderCommands; +} \ No newline at end of file diff --git a/renderers/cairo/clay_renderer_cairo.c b/renderers/cairo/clay_renderer_cairo.c index c8e3c16..ff3813e 100644 --- a/renderers/cairo/clay_renderer_cairo.c +++ b/renderers/cairo/clay_renderer_cairo.c @@ -83,12 +83,12 @@ static inline char *Clay_Cairo__NullTerminate(Clay_String *str) { } // Measure text using cairo's *toy* text API. -static inline Clay_Dimensions Clay_Cairo_MeasureText(Clay_String *str, Clay_TextElementConfig *config, uintptr_t userData) { +static inline Clay_Dimensions Clay_Cairo_MeasureText(Clay_StringSlice str, Clay_TextElementConfig *config, uintptr_t userData) { // Edge case: Clay computes the width of a whitespace character // 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. - if(str->length == 1 && str->chars[0] == ' ') { + if(str.length == 1 && str.chars[0] == ' ') { cairo_text_extents_t te; cairo_text_extents(Clay__Cairo, " ", &te); return (Clay_Dimensions) { @@ -102,7 +102,8 @@ static inline Clay_Dimensions Clay_Cairo_MeasureText(Clay_String *str, Clay_Text } // Ensure string is null-terminated for Cairo - char *text = Clay_Cairo__NullTerminate(str); + Clay_String toTerminate = (Clay_String){ str.length, str.chars }; + char *text = Clay_Cairo__NullTerminate(&toTerminate); char *font_family = Clay_Cairo__NullTerminate(&config->fontFamily); // Save and reset the Cairo context to avoid unwanted transformations @@ -195,6 +196,7 @@ void Clay_Cairo_Render(Clay_RenderCommandArray commands) { 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: { @@ -205,21 +207,21 @@ void Clay_Cairo_Render(Clay_RenderCommandArray commands) { cairo_set_source_rgba(cr, CLAY_TO_CAIRO(color)); cairo_new_sub_path(cr); - cairo_arc(cr, bb.x + config->cornerRadius.topLeft, - bb.y + config->cornerRadius.topLeft, - config->cornerRadius.topLeft, + cairo_arc(cr, bb.x + cornerRadius.topLeft, + bb.y + cornerRadius.topLeft, + cornerRadius.topLeft, M_PI, 3 * M_PI / 2); // 180° to 270° - cairo_arc(cr, bb.x + bb.width - config->cornerRadius.topRight, - bb.y + config->cornerRadius.topRight, - config->cornerRadius.topRight, + cairo_arc(cr, bb.x + bb.width - cornerRadius.topRight, + bb.y + cornerRadius.topRight, + cornerRadius.topRight, 3 * M_PI / 2, 2 * M_PI); // 270° to 360° - cairo_arc(cr, bb.x + bb.width - config->cornerRadius.bottomRight, - bb.y + bb.height - config->cornerRadius.bottomRight, - config->cornerRadius.bottomRight, + cairo_arc(cr, bb.x + bb.width - cornerRadius.bottomRight, + bb.y + bb.height - cornerRadius.bottomRight, + cornerRadius.bottomRight, 0, M_PI / 2); // 0° to 90° - cairo_arc(cr, bb.x + config->cornerRadius.bottomLeft, - bb.y + bb.height - config->cornerRadius.bottomLeft, - config->cornerRadius.bottomLeft, + cairo_arc(cr, bb.x + cornerRadius.bottomLeft, + bb.y + bb.height - cornerRadius.bottomLeft, + cornerRadius.bottomLeft, M_PI / 2, M_PI); // 90° to 180° cairo_close_path(cr); @@ -229,7 +231,8 @@ 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. - char *text = Clay_Cairo__NullTerminate(&command->text); + Clay_String toTerminate = (Clay_String){ command->textOrSharedConfig.text.length, command->textOrSharedConfig.text.chars }; + char *text = Clay_Cairo__NullTerminate(&toTerminate); char *font_family = Clay_Cairo__NullTerminate(&command->config.textElementConfig->fontFamily); Clay_BoundingBox bb = command->boundingBox; @@ -252,10 +255,10 @@ void Clay_Cairo_Render(Clay_RenderCommandArray commands) { Clay_BorderElementConfig *config = command->config.borderElementConfig; Clay_BoundingBox bb = command->boundingBox; - 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; + 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; // Draw the top border if (config->top.width > 0) { diff --git a/renderers/raylib/clay_renderer_raylib.c b/renderers/raylib/clay_renderer_raylib.c index 0c3ac59..44acd84 100644 --- a/renderers/raylib/clay_renderer_raylib.c +++ b/renderers/raylib/clay_renderer_raylib.c @@ -138,7 +138,7 @@ 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->text; + Clay_StringSlice text = renderCommand->textOrSharedConfig.text; char *cloned = (char *)malloc(text.length + 1); memcpy(cloned, text.chars, text.length); cloned[text.length] = '\0'; @@ -167,8 +167,9 @@ void Clay_Raylib_Render(Clay_RenderCommandArray renderCommands) } case CLAY_RENDER_COMMAND_TYPE_RECTANGLE: { Clay_RectangleElementConfig *config = renderCommand->config.rectangleElementConfig; - if (config->cornerRadius.topLeft > 0) { - float radius = (config->cornerRadius.topLeft * 2) / (float)((boundingBox.width > boundingBox.height) ? boundingBox.height : boundingBox.width); + 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)); } else { DrawRectangle(boundingBox.x, boundingBox.y, boundingBox.width, boundingBox.height, CLAY_COLOR_TO_RAYLIB_COLOR(config->color)); @@ -177,33 +178,34 @@ void Clay_Raylib_Render(Clay_RenderCommandArray renderCommands) } case CLAY_RENDER_COMMAND_TYPE_BORDER: { Clay_BorderElementConfig *config = renderCommand->config.borderElementConfig; + Clay_CornerRadius cornerRadius = renderCommand->textOrSharedConfig.sharedConfig->cornerRadius; // Left border if (config->left.width > 0) { - DrawRectangle((int)roundf(boundingBox.x), (int)roundf(boundingBox.y + config->cornerRadius.topLeft), (int)config->left.width, (int)roundf(boundingBox.height - config->cornerRadius.topLeft - config->cornerRadius.bottomLeft), CLAY_COLOR_TO_RAYLIB_COLOR(config->left.color)); + 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)); } // Right border if (config->right.width > 0) { - DrawRectangle((int)roundf(boundingBox.x + boundingBox.width - config->right.width), (int)roundf(boundingBox.y + config->cornerRadius.topRight), (int)config->right.width, (int)roundf(boundingBox.height - config->cornerRadius.topRight - config->cornerRadius.bottomRight), CLAY_COLOR_TO_RAYLIB_COLOR(config->right.color)); + 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)); } // Top border if (config->top.width > 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->top.width, CLAY_COLOR_TO_RAYLIB_COLOR(config->top.color)); + 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)); } // Bottom border if (config->bottom.width > 0) { - DrawRectangle((int)roundf(boundingBox.x + config->cornerRadius.bottomLeft), (int)roundf(boundingBox.y + boundingBox.height - config->bottom.width), (int)roundf(boundingBox.width - config->cornerRadius.bottomLeft - config->cornerRadius.bottomRight), (int)config->bottom.width, CLAY_COLOR_TO_RAYLIB_COLOR(config->bottom.color)); + 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->cornerRadius.topLeft > 0) { - DrawRing((Vector2) { roundf(boundingBox.x + config->cornerRadius.topLeft), roundf(boundingBox.y + config->cornerRadius.topLeft) }, roundf(config->cornerRadius.topLeft - config->top.width), config->cornerRadius.topLeft, 180, 270, 10, CLAY_COLOR_TO_RAYLIB_COLOR(config->top.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.topRight > 0) { - DrawRing((Vector2) { roundf(boundingBox.x + boundingBox.width - config->cornerRadius.topRight), roundf(boundingBox.y + config->cornerRadius.topRight) }, roundf(config->cornerRadius.topRight - config->top.width), config->cornerRadius.topRight, 270, 360, 10, CLAY_COLOR_TO_RAYLIB_COLOR(config->top.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.bottomLeft > 0) { - DrawRing((Vector2) { roundf(boundingBox.x + config->cornerRadius.bottomLeft), roundf(boundingBox.y + boundingBox.height - config->cornerRadius.bottomLeft) }, roundf(config->cornerRadius.bottomLeft - config->top.width), config->cornerRadius.bottomLeft, 90, 180, 10, CLAY_COLOR_TO_RAYLIB_COLOR(config->bottom.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.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->bottom.width), config->cornerRadius.bottomRight, 0.1, 90, 10, CLAY_COLOR_TO_RAYLIB_COLOR(config->bottom.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)); } break; }