diff --git a/CMakeLists.txt b/CMakeLists.txt index 4151a04..cba1691 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,6 +9,7 @@ add_subdirectory("examples/cpp-project-example") if(NOT MSVC) add_subdirectory("examples/raylib-sidebar-scrolling-container") add_subdirectory("examples/multi-context-raylib-sidebar-scrolling-container") + add_subdirectory("examples/raylib-multi-context") # add_subdirectory("examples/cairo-pdf-rendering") Some issue with github actions populating cairo, disable for now add_subdirectory("examples/clay-official-website") add_subdirectory("examples/introducing-clay-video-demo") diff --git a/README.md b/README.md index 6663a79..8421279 100644 --- a/README.md +++ b/README.md @@ -442,6 +442,36 @@ The debug tooling by default will render as a panel to the right side of the scr _The official Clay website with debug tooling visible_ +### Running more than one Clay instance + +Clay allows you to run more than one instance in a program. To do this, [Clay_Initialize](#clay_initialize) returns a [Clay_Context*](#clay_context) reference. You can activate a specific instance using [Clay_SetCurrentContext](#clay_setcurrentcontext). If [Clay_SetCurrentContext](#clay_setcurrentcontext) is not called, then Clay will default to using the context from the most recently called [Clay_Initialize](#clay_initialize). + +**⚠ Important: Do not render instances across different threads simultaneously, as Clay does not currently support proper multi-threading.** + +```c++ +// Define separate arenas for the instances. +Clay_Arena arena1, arena2; +// ... allocate arenas + +// Initialize both instances, storing the context for each one. +Clay_Context* instance1 = Clay_Initialize(arena1, layoutDimensions, errorHandler); +Clay_Context* instance2 = Clay_Initialize(arena2, layoutDimensions, errorHandler); + +// In the program's render function, activate each instance before executing clay commands and macros. +Clay_SetCurrentContext(instance1); +Clay_BeginLayout(); +// ... declare layout for instance1 +Clay_RenderCommandArray renderCommands1 = Clay_EndLayout(); +render(renderCommands1); + +// Switch to the second instance +Clay_SetCurrentContext(instance2); +Clay_BeginLayout(); +// ... declare layout for instance2 +Clay_RenderCommandArray renderCommands2 = Clay_EndLayout(); +render(renderCommands2); +``` + # API ### Naming Conventions @@ -486,7 +516,7 @@ Takes a pointer to a function that can be used to measure the `width, height` di `void Clay_SetMaxElementCount(uint32_t maxElementCount)` -Updates the internal maximum element count, allowing clay to allocate larger UI hierarchies. +Sets the internal maximum element count that will be used in subsequent [Clay_Initialize()](#clay_initialize) and [Clay_MinMemorySize()](#clay_minmemorysize) calls, allowing clay to allocate larger UI hierarchies. **Note: You will need to reinitialize clay, after calling [Clay_MinMemorySize()](#clay_minmemorysize) to calculate updated memory requirements.** @@ -494,17 +524,29 @@ Updates the internal maximum element count, allowing clay to allocate larger UI `void Clay_SetMaxMeasureTextCacheWordCount(uint32_t maxMeasureTextCacheWordCount)` -Updates the internal text measurement cache size, allowing clay to allocate more text. The value represents how many seperate words can be stored in the text measurement cache. +Sets the internal text measurement cache size that will be used in subsequent [Clay_Initialize()](#clay_initialize) and [Clay_MinMemorySize()](#clay_minmemorysize) calls, allowing clay to allocate more text. The value represents how many separate words can be stored in the text measurement cache. **Note: You will need to reinitialize clay, after calling [Clay_MinMemorySize()](#clay_minmemorysize) to calculate updated memory requirements.** ### Clay_Initialize -`void Clay_Initialize(Clay_Arena arena, Clay_Dimensions layoutDimensions, Clay_ErrorHandler errorHandler)` +`Clay_Context* Clay_Initialize(Clay_Arena arena, Clay_Dimensions layoutDimensions, Clay_ErrorHandler errorHandler)` -Initializes the internal memory mapping, sets the internal dimensions for layout, and binds an error handler for clay to use when something goes wrong. +Initializes the internal memory mapping, sets the internal dimensions for layout, and binds an error handler for clay to use when something goes wrong. Returns a [Clay_Context*](#clay_context) that can optionally be given to [Clay_SetCurrentContext](#clay_setcurrentcontext) to allow running multiple instances of clay in the same program, and sets it as the current context. See [Running more than one Clay instance](#running-more-than-one-clay-instance). -Reference: [Clay_Arena](#clay_createarenawithcapacityandmemory), [Clay_ErrorHandler](#clay_errorhandler) +Reference: [Clay_Arena](#clay_createarenawithcapacityandmemory), [Clay_ErrorHandler](#clay_errorhandler), [Clay_SetCurrentContext](#clay_setcurrentcontext) + +### Clay_SetCurrentContext + +`void Clay_SetCurrentContext(Clay_Context* context)` + +Sets the context that subsequent clay commands will operate on. You can get this reference from [Clay_Initialize](#clay_initialize) or [Clay_GetCurrentContext](#clay_getcurrentcontext). See [Running more than one Clay instance](#running-more-than-one-clay-instance). + +### Clay_GetCurrentContext + +`Clay_Context* Clay_GetCurrentContext()` + +Returns the context that clay commands are currently operating on, or null if no context has been set. See [Running more than one Clay instance](#running-more-than-one-clay-instance). ### Clay_SetLayoutDimensions diff --git a/clay.h b/clay.h index c9b72aa..2773583 100644 --- a/clay.h +++ b/clay.h @@ -84,7 +84,7 @@ #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)) @@ -94,7 +94,10 @@ #define CLAY__STRING_LENGTH(s) ((sizeof(s) / sizeof((s)[0])) - sizeof((s)[0])) -#define CLAY_STRING(string) (CLAY__INIT(Clay_String) { .length = CLAY__STRING_LENGTH(string), .chars = (string) }) +#define CLAY__ENSURE_STRING_LITERAL(x) ("" x "") + +// Note: If an error led you here, it's because CLAY_STRING can only be used with string literals, i.e. CLAY_STRING("SomeString") and not CLAY_STRING(yourString) +#define CLAY_STRING(string) (CLAY__INIT(Clay_String) { .length = CLAY__STRING_LENGTH(CLAY__ENSURE_STRING_LITERAL(string)), .chars = (string) }) static uint8_t CLAY__ELEMENT_DEFINITION_LATCH; @@ -125,7 +128,14 @@ static uint8_t CLAY__ELEMENT_DEFINITION_LATCH; */ #define CLAY(...) \ for (\ - CLAY__ELEMENT_DEFINITION_LATCH = (Clay__OpenElement(CLAY__CONFIG_WRAPPER(Clay_ElementDeclaration, __VA_ARGS__)), Clay__ElementPostConfiguration(), 0); \ + CLAY__ELEMENT_DEFINITION_LATCH = (Clay__OpenElement(CLAY__CONFIG_WRAPPER(Clay_ElementDeclaration, __VA_ARGS__)), 0); \ + CLAY__ELEMENT_DEFINITION_LATCH < 1; \ + ++CLAY__ELEMENT_DEFINITION_LATCH, Clay__CloseElement() \ + ) + +#define CLAY_REUSE(...) \ + for (\ + CLAY__ELEMENT_DEFINITION_LATCH = (Clay__OpenElementPointer(__VA_ARGS__), Clay__ElementPostConfiguration(), 0); \ CLAY__ELEMENT_DEFINITION_LATCH < 1; \ ++CLAY__ELEMENT_DEFINITION_LATCH, Clay__CloseElement() \ ) @@ -475,7 +485,7 @@ CLAY__TYPEDEF(Clay_PointerData, struct { CLAY__TYPEDEF(Clay_ElementDeclaration, struct t { Clay_ElementId id; - Clay_LayoutConfig layoutConfig; + Clay_LayoutConfig layout; Clay_RectangleElementConfig rectangle; Clay_ImageElementConfig image; Clay_FloatingElementConfig floating; @@ -577,6 +587,9 @@ extern uint32_t Clay__debugViewWidth; #endif Clay_Context *Clay__currentContext; +int32_t Clay__defaultMaxElementCount = 8192; +int32_t Clay__defaultMaxMeasureTextWordCacheCount = 16384; + void Clay__ErrorHandlerFunctionDefault(Clay_ErrorData errorText) { (void) errorText; } @@ -1802,94 +1815,61 @@ void Clay__GenerateIdForAnonymousElement(Clay_LayoutElement *openLayoutElement) } 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; - } +// 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 +// 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: { - // 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_Get(&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_Get(&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_Get(&context->layoutElementClipElementIds, parentItem->layoutElement - context->layoutElements.internalArray); - } - } - Clay__LayoutElementTreeRootArray_Add(&context->layoutElementTreeRoots, CLAY__INIT(Clay__LayoutElementTreeRoot) { - .layoutElementIndex = Clay__int32_tArray_Get(&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); - } - break; - } - case CLAY__ELEMENT_CONFIG_TYPE_CUSTOM: break; - case CLAY__ELEMENT_CONFIG_TYPE_IMAGE: { - Clay__LayoutElementPointerArray_Add(&context->imageElementPointers, openLayoutElement); - break; - } - case CLAY__ELEMENT_CONFIG_TYPE_TEXT: - default: break; - } - } - context->elementConfigBuffer.length -= openLayoutElement->elementConfigs.length; +// 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); +// } +// break; +// } +// case CLAY__ELEMENT_CONFIG_TYPE_CUSTOM: break; +// case CLAY__ELEMENT_CONFIG_TYPE_IMAGE: { +// Clay__LayoutElementPointerArray_Add(&context->imageElementPointers, openLayoutElement); +// break; +// } +// case CLAY__ELEMENT_CONFIG_TYPE_TEXT: +// default: break; +// } +// } +// context->elementConfigBuffer.length -= openLayoutElement->elementConfigs.length; } void Clay__CloseElement(void) { @@ -1996,44 +1976,100 @@ bool Clay__MemCmp(char *a, char *b, int length) { return true; } -void Clay__OpenElement(Clay_ElementDeclaration declaration) { +void Clay__OpenElementPointer(const Clay_ElementDeclaration* declaration) { Clay_Context* context = Clay_GetCurrentContext(); if (context->layoutElements.length == context->layoutElements.capacity - 1 || context->booleanWarnings.maxElementsExceeded) { context->booleanWarnings.maxElementsExceeded = true; return; } Clay_LayoutElement layoutElement = CLAY__DEFAULT_STRUCT; - Clay_LayoutElementArray_Add(&context->layoutElements, layoutElement); + Clay_LayoutElement* openLayoutElement = Clay_LayoutElementArray_Add(&context->layoutElements, layoutElement); Clay__int32_tArray_Add(&context->openLayoutElementStack, context->layoutElements.length - 1); if (context->openClipElementStack.length > 0) { Clay__int32_tArray_Set(&context->layoutElementClipElementIds, context->layoutElements.length - 1, Clay__int32_tArray_Get(&context->openClipElementStack, (int)context->openClipElementStack.length - 1)); } else { Clay__int32_tArray_Set(&context->layoutElementClipElementIds, context->layoutElements.length - 1, 0); } - Clay__GetOpenLayoutElement()->layoutConfig = Clay__StoreLayoutConfig(declaration.layoutConfig); - if (declaration.id.id != 0) { - Clay__AttachId(declaration.id); + openLayoutElement->layoutConfig = Clay__StoreLayoutConfig(declaration->layout); + if (declaration->id.id != 0) { + Clay__AttachId(declaration->id); + } else { + Clay__GenerateIdForAnonymousElement(openLayoutElement); } - if (!Clay__MemCmp((char *)(&declaration.rectangle), (char *)(&CLAY__RECTANGLE_ELEMENT_CONFIG_DEFAULT), sizeof(Clay_RectangleElementConfig))) { - Clay__AttachElementConfig(CLAY__INIT(Clay_ElementConfigUnion) { .rectangleElementConfig = Clay__StoreRectangleElementConfig(declaration.rectangle) }, CLAY__ELEMENT_CONFIG_TYPE_RECTANGLE); + + openLayoutElement->elementConfigs.internalArray = &context->elementConfigs.internalArray[context->elementConfigs.length]; + if (!Clay__MemCmp((char *)(&declaration->rectangle), (char *)(&CLAY__RECTANGLE_ELEMENT_CONFIG_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__IMAGE_ELEMENT_CONFIG_DEFAULT), sizeof(Clay_ImageElementConfig))) { - Clay__AttachElementConfig(CLAY__INIT(Clay_ElementConfigUnion) { .imageElementConfig = Clay__StoreImageElementConfig(declaration.image) }, CLAY__ELEMENT_CONFIG_TYPE_IMAGE); + if (!Clay__MemCmp((char *)(&declaration->image), (char *)(&CLAY__IMAGE_ELEMENT_CONFIG_DEFAULT), sizeof(Clay_ImageElementConfig))) { + Clay__AttachElementConfig(CLAY__INIT(Clay_ElementConfigUnion) { .imageElementConfig = Clay__StoreImageElementConfig(declaration->image) }, CLAY__ELEMENT_CONFIG_TYPE_IMAGE); + Clay__LayoutElementPointerArray_Add(&context->imageElementPointers, openLayoutElement); } - if (!Clay__MemCmp((char *)(&declaration.floating), (char *)(&CLAY__FLOATING_ELEMENT_CONFIG_DEFAULT), sizeof(Clay_FloatingElementConfig))) { - Clay__AttachElementConfig(CLAY__INIT(Clay_ElementConfigUnion) { .floatingElementConfig = Clay__StoreFloatingElementConfig(declaration.floating) }, CLAY__ELEMENT_CONFIG_TYPE_FLOATING_CONTAINER); + if (!Clay__MemCmp((char *)(&declaration->floating), (char *)(&CLAY__FLOATING_ELEMENT_CONFIG_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_Get(&context->openLayoutElementStack, context->openLayoutElementStack.length - 2)); + if (!hierarchicalParent) { + return; // TODO error handler + } + 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_Get(&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_Get(&context->layoutElementClipElementIds, parentItem->layoutElement - context->layoutElements.internalArray); + } + } + Clay__LayoutElementTreeRootArray_Add(&context->layoutElementTreeRoots, CLAY__INIT(Clay__LayoutElementTreeRoot) { + .layoutElementIndex = Clay__int32_tArray_Get(&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_CONTAINER); } - if (!Clay__MemCmp((char *)(&declaration.custom), (char *)(&CLAY__CUSTOM_ELEMENT_CONFIG_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->custom), (char *)(&CLAY__CUSTOM_ELEMENT_CONFIG_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.scroll), (char *)(&CLAY__SCROLL_ELEMENT_CONFIG_DEFAULT), sizeof(Clay_ScrollElementConfig))) { - Clay__AttachElementConfig(CLAY__INIT(Clay_ElementConfigUnion) { .scrollElementConfig = Clay__StoreScrollElementConfig(declaration.scroll) }, CLAY__ELEMENT_CONFIG_TYPE_SCROLL_CONTAINER); + if (!Clay__MemCmp((char *)(&declaration->scroll), (char *)(&CLAY__SCROLL_ELEMENT_CONFIG_DEFAULT), sizeof(Clay_ScrollElementConfig))) { + Clay__AttachElementConfig(CLAY__INIT(Clay_ElementConfigUnion) { .scrollElementConfig = Clay__StoreScrollElementConfig(declaration->scroll) }, 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); + } } - if (!Clay__MemCmp((char *)(&declaration.border), (char *)(&CLAY__BORDER_ELEMENT_CONFIG_DEFAULT), sizeof(Clay_BorderElementConfig))) { - Clay__AttachElementConfig(CLAY__INIT(Clay_ElementConfigUnion) { .borderElementConfig = Clay__StoreBorderElementConfig(declaration.border) }, CLAY__ELEMENT_CONFIG_TYPE_BORDER_CONTAINER); + if (!Clay__MemCmp((char *)(&declaration->border), (char *)(&CLAY__BORDER_ELEMENT_CONFIG_DEFAULT), sizeof(Clay_BorderElementConfig))) { + Clay__AttachElementConfig(CLAY__INIT(Clay_ElementConfigUnion) { .borderElementConfig = Clay__StoreBorderElementConfig(declaration->border) }, CLAY__ELEMENT_CONFIG_TYPE_BORDER_CONTAINER); } } +void Clay__OpenElement(const Clay_ElementDeclaration declaration) { + Clay__OpenElementPointer(&declaration); +} + void Clay__OpenTextElement(Clay_String text, Clay_TextElementConfig *textConfig) { Clay_Context* context = Clay_GetCurrentContext(); if (context->layoutElements.length == context->layoutElements.capacity - 1 || context->booleanWarnings.maxElementsExceeded) { @@ -2043,26 +2079,30 @@ void Clay__OpenTextElement(Clay_String text, Clay_TextElementConfig *textConfig) Clay_LayoutElement *parentElement = Clay__GetOpenLayoutElement(); parentElement->childrenOrTextContent.children.length++; - Clay__OpenElement((Clay_ElementDeclaration){ }); - 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_Get(&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) { + 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__InitializeEphemeralMemory(Clay_Context* context) { @@ -2076,7 +2116,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); @@ -2939,7 +2978,8 @@ void Clay__AttachElementConfig(Clay_ElementConfigUnion config, Clay__ElementConf } Clay_LayoutElement *openLayoutElement = Clay__GetOpenLayoutElement(); openLayoutElement->elementConfigs.length++; - Clay__ElementConfigArray_Add(&context->elementConfigBuffer, CLAY__INIT(Clay_ElementConfig) { .type = type, .config = config }); + openLayoutElement->configsEnabled |= type; + Clay__ElementConfigArray_Add(&context->elementConfigs, 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__RECTANGLE_ELEMENT_CONFIG_DEFAULT : Clay__RectangleElementConfigArray_Add(&Clay_GetCurrentContext()->rectangleElementConfigs, config); } @@ -2950,596 +2990,596 @@ Clay_CustomElementConfig * Clay__StoreCustomElementConfig(Clay_CustomElementConf Clay_ScrollElementConfig * Clay__StoreScrollElementConfig(Clay_ScrollElementConfig config) { return Clay_GetCurrentContext()->booleanWarnings.maxElementsExceeded ? &CLAY__SCROLL_ELEMENT_CONFIG_DEFAULT : Clay__ScrollElementConfigArray_Add(&Clay_GetCurrentContext()->scrollElementConfigs, config); } Clay_BorderElementConfig * Clay__StoreBorderElementConfig(Clay_BorderElementConfig config) { return Clay_GetCurrentContext()->booleanWarnings.maxElementsExceeded ? &CLAY__BORDER_ELEMENT_CONFIG_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}; -Clay_Color CLAY__DEBUGVIEW_COLOR_3 = {141, 133, 135, 255}; -Clay_Color CLAY__DEBUGVIEW_COLOR_4 = {238, 226, 231, 255}; -Clay_Color CLAY__DEBUGVIEW_COLOR_SELECTED_ROW = {102, 80, 78, 255}; -const int32_t CLAY__DEBUGVIEW_ROW_HEIGHT = 30; -const int32_t CLAY__DEBUGVIEW_OUTER_PADDING = 10; -const int32_t CLAY__DEBUGVIEW_INDENT_WIDTH = 16; -Clay_TextElementConfig Clay__DebugView_TextNameConfig = {.textColor = {238, 226, 231, 255}, .fontSize = 16, .wrapMode = CLAY_TEXT_WRAP_NONE }; -Clay_LayoutConfig Clay__DebugView_ScrollViewItemLayoutConfig = CLAY__DEFAULT_STRUCT; - -CLAY__TYPEDEF(Clay__DebugElementConfigTypeLabelConfig, struct { - Clay_String label; - Clay_Color color; -}); - -Clay__DebugElementConfigTypeLabelConfig Clay__DebugGetElementConfigTypeLabel(Clay__ElementConfigType type) { - switch (type) { - case CLAY__ELEMENT_CONFIG_TYPE_RECTANGLE: return CLAY__INIT(Clay__DebugElementConfigTypeLabelConfig) { CLAY_STRING("Rectangle"), {243,134,48,255} }; - case CLAY__ELEMENT_CONFIG_TYPE_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_CUSTOM: return CLAY__INIT(Clay__DebugElementConfigTypeLabelConfig) { CLAY_STRING("Custom"), {11,72,107,255} }; - default: break; - } - return CLAY__INIT(Clay__DebugElementConfigTypeLabelConfig) { CLAY_STRING("Error"), {0,0,0,255} }; -} - -CLAY__TYPEDEF(Clay__RenderDebugLayoutData, struct { - int32_t rowCount; - int32_t selectedElementRowIndex; -}); - -// Returns row count -Clay__RenderDebugLayoutData Clay__RenderDebugLayoutElementsList(int32_t initialRootsLength, int32_t highlightedRowIndex) { - Clay_Context* context = Clay_GetCurrentContext(); - Clay__int32_tArray dfsBuffer = context->reusableElementIndexBuffer; - Clay__DebugView_ScrollViewItemLayoutConfig = CLAY__INIT(Clay_LayoutConfig) { .sizing = { .height = CLAY_SIZING_FIXED(CLAY__DEBUGVIEW_ROW_HEIGHT) }, .childGap = 6, .childAlignment = { .y = CLAY_ALIGN_Y_CENTER }}; - Clay__RenderDebugLayoutData layoutData = CLAY__DEFAULT_STRUCT; - - uint32_t highlightedElementId = 0; - - for (int32_t rootIndex = 0; rootIndex < initialRootsLength; ++rootIndex) { - dfsBuffer.length = 0; - Clay__LayoutElementTreeRoot *root = Clay__LayoutElementTreeRootArray_Get(&context->layoutElementTreeRoots, rootIndex); - 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(CLAY__DEFAULT_STRUCT)}, .padding = {CLAY__DEBUGVIEW_INDENT_WIDTH / 2, 0} })) { - CLAY(CLAY_IDI("Clay__DebugView_EmptyRow", rootIndex), CLAY_LAYOUT({ .sizing = { .width = CLAY_SIZING_GROW(CLAY__DEFAULT_STRUCT), .height = CLAY_SIZING_FIXED((float)CLAY__DEBUGVIEW_ROW_HEIGHT) }}), CLAY_BORDER({ .top = { .width = 1, .color = CLAY__DEBUGVIEW_COLOR_3 } })) {} - } - layoutData.rowCount++; - } - while (dfsBuffer.length > 0) { - int32_t currentElementIndex = Clay__int32_tArray_Get(&dfsBuffer, (int)dfsBuffer.length - 1); - Clay_LayoutElement *currentElement = Clay_LayoutElementArray_Get(&context->layoutElements, (int)currentElementIndex); - if (context->treeNodeVisited.internalArray[dfsBuffer.length - 1]) { - if (!Clay__ElementHasConfig(currentElement, CLAY__ELEMENT_CONFIG_TYPE_TEXT) && currentElement->childrenOrTextContent.children.length > 0) { - Clay__CloseElement(); - Clay__CloseElement(); - Clay__CloseElement(); - } - dfsBuffer.length--; - continue; - } - - if (highlightedRowIndex == layoutData.rowCount) { - if (context->pointerInfo.state == CLAY_POINTER_DATA_PRESSED_THIS_FRAME) { - context->debugSelectedElementId = currentElement->id; - } - highlightedElementId = currentElement->id; - } - - context->treeNodeVisited.internalArray[dfsBuffer.length - 1] = true; - Clay_LayoutElementHashMapItem *currentElementData = Clay__GetHashMapItem(currentElement->id); - bool offscreen = Clay__ElementIsOffscreen(¤tElementData->boundingBox); - if (context->debugSelectedElementId == currentElement->id) { - layoutData.selectedElementRowIndex = layoutData.rowCount; - } - CLAY(CLAY_IDI("Clay__DebugView_ElementOuter", currentElement->id), Clay__AttachLayoutConfig(&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_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) })) {} - } - } - // Collisions and offscreen info - if (currentElementData) { - if (currentElementData->debugData->collision) { - CLAY(CLAY_LAYOUT({ .padding = { 8, 2 } }), CLAY_BORDER_OUTSIDE_RADIUS(1, (CLAY__INIT(Clay_Color){177, 147, 8, 255}), 4)) { - CLAY_TEXT(CLAY_STRING("Duplicate ID"), CLAY_TEXT_CONFIG({ .textColor = CLAY__DEBUGVIEW_COLOR_3, .fontSize = 16 })); - } - } - if (offscreen) { - CLAY(CLAY_LAYOUT({ .padding = { 8, 2 } }), CLAY_BORDER_OUTSIDE_RADIUS(1, CLAY__DEBUGVIEW_COLOR_3, 4)) { - CLAY_TEXT(CLAY_STRING("Offscreen"), CLAY_TEXT_CONFIG({ .textColor = CLAY__DEBUGVIEW_COLOR_3, .fontSize = 16 })); - } - } - } - Clay_String idString = context->layoutElementIdStrings.internalArray[currentElementIndex]; - if (idString.length > 0) { - CLAY_TEXT(idString, offscreen ? CLAY_TEXT_CONFIG({ .textColor = CLAY__DEBUGVIEW_COLOR_3, .fontSize = 16 }) : &Clay__DebugView_TextNameConfig); - } - for (int32_t elementConfigIndex = 0; elementConfigIndex < currentElement->elementConfigs.length; ++elementConfigIndex) { - Clay_ElementConfig *elementConfig = Clay__ElementConfigArraySlice_Get(¤tElement->elementConfigs, elementConfigIndex); - Clay__DebugElementConfigTypeLabelConfig config = Clay__DebugGetElementConfigTypeLabel(elementConfig->type); - Clay_Color backgroundColor = config.color; - backgroundColor.a = 90; - CLAY(CLAY_LAYOUT({ .padding = { 8, 2 } }), CLAY_RECTANGLE({ .color = backgroundColor, .cornerRadius = CLAY_CORNER_RADIUS(4) }), CLAY_BORDER_OUTSIDE_RADIUS(1, config.color, 4)) { - CLAY_TEXT(config.label, CLAY_TEXT_CONFIG({ .textColor = offscreen ? CLAY__DEBUGVIEW_COLOR_3 : CLAY__DEBUGVIEW_COLOR_4, .fontSize = 16 })); - } - } - } - - // Render the text contents below the element as a non-interactive row - if (Clay__ElementHasConfig(currentElement, CLAY__ELEMENT_CONFIG_TYPE_TEXT)) { - 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_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) { - CLAY_TEXT(CLAY_STRING("..."), rawTextConfig); - } - CLAY_TEXT(CLAY_STRING("\""), rawTextConfig); - } - } else if (currentElement->childrenOrTextContent.children.length > 0) { - Clay__OpenElement(); - CLAY_LAYOUT({ .padding = { 8 , 0} }); - Clay__ElementPostConfiguration(); - 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__OpenElement(); - CLAY_LAYOUT({ .layoutDirection = CLAY_TOP_TO_BOTTOM }); - Clay__ElementPostConfiguration(); - } - - layoutData.rowCount++; - if (!(Clay__ElementHasConfig(currentElement, CLAY__ELEMENT_CONFIG_TYPE_TEXT) || (currentElementData && currentElementData->debugData->collapsed))) { - for (int32_t i = currentElement->childrenOrTextContent.children.length - 1; i >= 0; --i) { - Clay__int32_tArray_Add(&dfsBuffer, currentElement->childrenOrTextContent.children.elements[i]); - context->treeNodeVisited.internalArray[dfsBuffer.length - 1] = false; // TODO needs to be ranged checked - } - } - } - } - - if (context->pointerInfo.state == CLAY_POINTER_DATA_PRESSED_THIS_FRAME) { - Clay_ElementId collapseButtonId = Clay__HashString(CLAY_STRING("Clay__DebugView_CollapseElement"), 0, 0); - for (int32_t i = (int)context->pointerOverIds.length - 1; i >= 0; i--) { - Clay_ElementId *elementId = Clay__ElementIdArray_Get(&context->pointerOverIds, i); - if (elementId->baseId == collapseButtonId.baseId) { - Clay_LayoutElementHashMapItem *highlightedItem = Clay__GetHashMapItem(elementId->offset); - highlightedItem->debugData->collapsed = !highlightedItem->debugData->collapsed; - break; - } - } - } - - if (highlightedElementId) { - CLAY(CLAY_ID("Clay__DebugView_ElementHighlight"), CLAY_LAYOUT({ .sizing = {CLAY_SIZING_GROW(CLAY__DEFAULT_STRUCT), CLAY_SIZING_GROW(CLAY__DEFAULT_STRUCT)} }), CLAY_FLOATING({ .zIndex = 65535, .parentId = highlightedElementId })) { - CLAY(CLAY_ID("Clay__DebugView_ElementHighlightRectangle"), CLAY_LAYOUT({ .sizing = {CLAY_SIZING_GROW(CLAY__DEFAULT_STRUCT), CLAY_SIZING_GROW(CLAY__DEFAULT_STRUCT)} }), CLAY_RECTANGLE({.color = Clay__debugViewHighlightColor })) {} - } - } - return layoutData; -} - -void Clay__RenderDebugLayoutSizing(Clay_SizingAxis sizing, Clay_TextElementConfig *infoTextConfig) { - Clay_String sizingLabel = CLAY_STRING("GROW"); - if (sizing.type == CLAY__SIZING_TYPE_FIT) { - sizingLabel = CLAY_STRING("FIT"); - } else if (sizing.type == CLAY__SIZING_TYPE_PERCENT) { - sizingLabel = CLAY_STRING("PERCENT"); - } - CLAY_TEXT(sizingLabel, infoTextConfig); - if (sizing.type == CLAY__SIZING_TYPE_GROW || sizing.type == CLAY__SIZING_TYPE_FIT) { - CLAY_TEXT(CLAY_STRING("("), infoTextConfig); - if (sizing.size.minMax.min != 0) { - CLAY_TEXT(CLAY_STRING("min: "), infoTextConfig); - CLAY_TEXT(Clay__IntToString(sizing.size.minMax.min), infoTextConfig); - if (sizing.size.minMax.max != CLAY__MAXFLOAT) { - CLAY_TEXT(CLAY_STRING(", "), infoTextConfig); - } - } - if (sizing.size.minMax.max != CLAY__MAXFLOAT) { - CLAY_TEXT(CLAY_STRING("max: "), infoTextConfig); - CLAY_TEXT(Clay__IntToString(sizing.size.minMax.max), infoTextConfig); - } - CLAY_TEXT(CLAY_STRING(")"), infoTextConfig); - } -} - -void Clay__RenderDebugViewElementConfigHeader(Clay_String elementId, Clay__ElementConfigType type) { - Clay__DebugElementConfigTypeLabelConfig config = Clay__DebugGetElementConfigTypeLabel(type); - Clay_Color backgroundColor = config.color; - backgroundColor.a = 90; - CLAY(CLAY_LAYOUT({ .sizing = { CLAY_SIZING_GROW(CLAY__DEFAULT_STRUCT), CLAY_SIZING_FIXED(CLAY__DEBUGVIEW_ROW_HEIGHT + 8)}, .padding = { .x = CLAY__DEBUGVIEW_OUTER_PADDING }, .childAlignment = { .y = CLAY_ALIGN_Y_CENTER } })) { - CLAY(CLAY_LAYOUT({ .padding = { 8, 2 } }), CLAY_RECTANGLE({ .color = backgroundColor, .cornerRadius = CLAY_CORNER_RADIUS(4) }), CLAY_BORDER_OUTSIDE_RADIUS(1, config.color, 4)) { - CLAY_TEXT(config.label, CLAY_TEXT_CONFIG({ .textColor = CLAY__DEBUGVIEW_COLOR_4, .fontSize = 16 })); - } - CLAY(CLAY_LAYOUT({ .sizing = { .width = CLAY_SIZING_GROW(CLAY__DEFAULT_STRUCT) } })) {} - 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_TEXT(CLAY_STRING("{ r: "), textConfig); - CLAY_TEXT(Clay__IntToString(color.r), textConfig); - CLAY_TEXT(CLAY_STRING(", g: "), textConfig); - CLAY_TEXT(Clay__IntToString(color.g), textConfig); - CLAY_TEXT(CLAY_STRING(", b: "), textConfig); - CLAY_TEXT(Clay__IntToString(color.b), textConfig); - 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) })) {} - } - } -} - -void Clay__RenderDebugViewCornerRadius(Clay_CornerRadius cornerRadius, Clay_TextElementConfig *textConfig) { - CLAY(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); - CLAY_TEXT(Clay__IntToString(cornerRadius.topRight), textConfig); - CLAY_TEXT(CLAY_STRING(", bottomLeft: "), textConfig); - CLAY_TEXT(Clay__IntToString(cornerRadius.bottomLeft), textConfig); - CLAY_TEXT(CLAY_STRING(", bottomRight: "), textConfig); - CLAY_TEXT(Clay__IntToString(cornerRadius.bottomRight), textConfig); - CLAY_TEXT(CLAY_STRING(" }"), textConfig); - } -} - -void Clay__RenderDebugViewBorder(int32_t index, Clay_Border border, Clay_TextElementConfig *textConfig) { - (void) index; - CLAY(CLAY_LAYOUT({ .childAlignment = {.y = CLAY_ALIGN_Y_CENTER} })) { - CLAY_TEXT(CLAY_STRING("{ width: "), textConfig); - CLAY_TEXT(Clay__IntToString(border.width), textConfig); - CLAY_TEXT(CLAY_STRING(", color: "), textConfig); - Clay__RenderDebugViewColor(border.color, textConfig); - CLAY_TEXT(CLAY_STRING(" }"), textConfig); - } -} - -void HandleDebugViewCloseButtonInteraction(Clay_ElementId elementId, Clay_PointerData pointerInfo, intptr_t userData) { - Clay_Context* context = Clay_GetCurrentContext(); - (void) elementId; (void) pointerInfo; (void) userData; - if (pointerInfo.state == CLAY_POINTER_DATA_PRESSED_THIS_FRAME) { - context->debugModeEnabled = false; - } -} - -void Clay__RenderDebugView() { - Clay_Context* context = Clay_GetCurrentContext(); - Clay_ElementId closeButtonId = Clay__HashString(CLAY_STRING("Clay__DebugViewTopHeaderCloseButtonOuter"), 0, 0); - if (context->pointerInfo.state == CLAY_POINTER_DATA_PRESSED_THIS_FRAME) { - for (int32_t i = 0; i < context->pointerOverIds.length; ++i) { - Clay_ElementId *elementId = Clay__ElementIdArray_Get(&context->pointerOverIds, i); - if (elementId->id == closeButtonId.id) { - context->debugModeEnabled = false; - return; - } - } - } - - uint32_t initialRootsLength = context->layoutElementTreeRoots.length; - uint32_t initialElementsLength = context->layoutElements.length; - Clay_TextElementConfig *infoTextConfig = CLAY_TEXT_CONFIG({ .textColor = CLAY__DEBUGVIEW_COLOR_4, .fontSize = 16, .wrapMode = CLAY_TEXT_WRAP_NONE }); - Clay_TextElementConfig *infoTitleConfig = CLAY_TEXT_CONFIG({ .textColor = CLAY__DEBUGVIEW_COLOR_3, .fontSize = 16, .wrapMode = CLAY_TEXT_WRAP_NONE }); - Clay_ElementId scrollId = Clay__HashString(CLAY_STRING("Clay__DebugViewOuterScrollPane"), 0, 0); - float scrollYOffset = 0; - for (int32_t i = 0; i < context->scrollContainerDatas.length; ++i) { - Clay__ScrollContainerDataInternal *scrollContainerData = Clay__ScrollContainerDataInternalArray_Get(&context->scrollContainerDatas, i); - if (scrollContainerData->elementId == scrollId.id) { - if (!context->externalScrollHandlingEnabled) { - scrollYOffset = scrollContainerData->scrollPosition.y; - } - break; - } - } - int32_t highlightedRow = context->pointerInfo.position.y < context->layoutDimensions.height - 300 - ? (int32_t)((context->pointerInfo.position.y - scrollYOffset) / (float)CLAY__DEBUGVIEW_ROW_HEIGHT) - 1 - : -1; - if (context->pointerInfo.position.x < context->layoutDimensions.width - (float)Clay__debugViewWidth) { - highlightedRow = -1; - } - Clay__RenderDebugLayoutData layoutData = CLAY__DEFAULT_STRUCT; - CLAY(CLAY_ID("Clay__DebugView"), - CLAY_FLOATING({ .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(CLAY__DEFAULT_STRUCT), CLAY_SIZING_FIXED(CLAY__DEBUGVIEW_ROW_HEIGHT)}, .padding = {CLAY__DEBUGVIEW_OUTER_PADDING, 0}, .childAlignment = {.y = CLAY_ALIGN_Y_CENTER} }), CLAY_RECTANGLE({ .color = CLAY__DEBUGVIEW_COLOR_2 })) { - CLAY_TEXT(CLAY_STRING("Clay Debug Tools"), infoTextConfig); - CLAY(CLAY_LAYOUT({ .sizing = { CLAY_SIZING_GROW(CLAY__DEFAULT_STRUCT), CLAY__DEFAULT_STRUCT } })) {} - // 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_TEXT(CLAY_STRING("x"), CLAY_TEXT_CONFIG({ .textColor = CLAY__DEBUGVIEW_COLOR_4, .fontSize = 16 })); - } - } - CLAY(CLAY_LAYOUT({ .sizing = {CLAY_SIZING_GROW(CLAY__DEFAULT_STRUCT), CLAY_SIZING_FIXED(1)} }), CLAY_RECTANGLE({ .color = CLAY__DEBUGVIEW_COLOR_3 })) {} - CLAY(Clay__AttachId(scrollId), CLAY_LAYOUT({ .sizing = {CLAY_SIZING_GROW(CLAY__DEFAULT_STRUCT), CLAY_SIZING_GROW(CLAY__DEFAULT_STRUCT)} }), CLAY_SCROLL({ .horizontal = true, .vertical = true })) { - CLAY(CLAY_LAYOUT({ .sizing = {CLAY_SIZING_GROW(CLAY__DEFAULT_STRUCT), CLAY_SIZING_GROW(CLAY__DEFAULT_STRUCT)}, .layoutDirection = CLAY_TOP_TO_BOTTOM }), CLAY_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(CLAY__DEFAULT_STRUCT), CLAY_SIZING_GROW(CLAY__DEFAULT_STRUCT)} }), CLAY_FLOATING({ .pointerCaptureMode = CLAY_POINTER_CAPTURE_MODE_PASSTHROUGH })) { - CLAY(CLAY_LAYOUT({ .sizing = {CLAY_SIZING_GROW(CLAY__DEFAULT_STRUCT), CLAY_SIZING_GROW(CLAY__DEFAULT_STRUCT)}, .padding = {.x = 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 })) {} - 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) { - rowColor = CLAY__DEBUGVIEW_COLOR_SELECTED_ROW; - } - if (i == highlightedRow) { - rowColor.r *= 1.25f; - rowColor.g *= 1.25f; - rowColor.b *= 1.25f; - } - CLAY(CLAY_LAYOUT({ .sizing = {CLAY_SIZING_GROW(CLAY__DEFAULT_STRUCT), CLAY_SIZING_FIXED(CLAY__DEBUGVIEW_ROW_HEIGHT)}, .layoutDirection = CLAY_TOP_TO_BOTTOM }), CLAY_RECTANGLE({ .color = rowColor })) {} - } - } - } - CLAY(CLAY_LAYOUT({ .sizing = {.width = CLAY_SIZING_GROW(CLAY__DEFAULT_STRUCT), .height = CLAY_SIZING_FIXED(1)} }), CLAY_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(CLAY__DEFAULT_STRUCT), 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(CLAY__DEFAULT_STRUCT), CLAY_SIZING_FIXED(CLAY__DEBUGVIEW_ROW_HEIGHT + 8)}, .padding = {CLAY__DEBUGVIEW_OUTER_PADDING, 0}, .childAlignment = {.y = CLAY_ALIGN_Y_CENTER} })) { - CLAY_TEXT(CLAY_STRING("Layout Config"), infoTextConfig); - CLAY(CLAY_LAYOUT({ .sizing = { CLAY_SIZING_GROW(CLAY__DEFAULT_STRUCT), CLAY__DEFAULT_STRUCT } })) {} - if (selectedItem->elementId.stringId.length != 0) { - CLAY_TEXT(selectedItem->elementId.stringId, infoTitleConfig); - if (selectedItem->elementId.offset != 0) { - CLAY_TEXT(CLAY_STRING(" ("), infoTitleConfig); - CLAY_TEXT(Clay__IntToString(selectedItem->elementId.offset), infoTitleConfig); - CLAY_TEXT(CLAY_STRING(")"), infoTitleConfig); - } - } - } - // Clay_LayoutConfig debug info - CLAY(CLAY_LAYOUT({ .padding = {CLAY__DEBUGVIEW_OUTER_PADDING, 8}, .childGap = 8, .layoutDirection = CLAY_TOP_TO_BOTTOM })) { - // .boundingBox - CLAY_TEXT(CLAY_STRING("Bounding Box"), infoTitleConfig); - CLAY(CLAY_LAYOUT(CLAY__DEFAULT_STRUCT)) { - CLAY_TEXT(CLAY_STRING("{ x: "), infoTextConfig); - CLAY_TEXT(Clay__IntToString(selectedItem->boundingBox.x), infoTextConfig); - CLAY_TEXT(CLAY_STRING(", y: "), infoTextConfig); - CLAY_TEXT(Clay__IntToString(selectedItem->boundingBox.y), infoTextConfig); - CLAY_TEXT(CLAY_STRING(", width: "), infoTextConfig); - CLAY_TEXT(Clay__IntToString(selectedItem->boundingBox.width), infoTextConfig); - CLAY_TEXT(CLAY_STRING(", height: "), infoTextConfig); - CLAY_TEXT(Clay__IntToString(selectedItem->boundingBox.height), infoTextConfig); - CLAY_TEXT(CLAY_STRING(" }"), infoTextConfig); - } - // .layoutDirection - CLAY_TEXT(CLAY_STRING("Layout Direction"), infoTitleConfig); - Clay_LayoutConfig *layoutConfig = selectedItem->layoutElement->layoutConfig; - 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_TEXT(CLAY_STRING("width: "), infoTextConfig); - Clay__RenderDebugLayoutSizing(layoutConfig->sizing.width, infoTextConfig); - } - CLAY(CLAY_LAYOUT(CLAY__DEFAULT_STRUCT)) { - 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_TEXT(CLAY_STRING("{ x: "), infoTextConfig); - CLAY_TEXT(Clay__IntToString(layoutConfig->padding.x), infoTextConfig); - CLAY_TEXT(CLAY_STRING(", y: "), infoTextConfig); - CLAY_TEXT(Clay__IntToString(layoutConfig->padding.y), infoTextConfig); - CLAY_TEXT(CLAY_STRING(" }"), infoTextConfig); - } - // .childGap - CLAY_TEXT(CLAY_STRING("Child Gap"), infoTitleConfig); - CLAY_TEXT(Clay__IntToString(layoutConfig->childGap), infoTextConfig); - // .childAlignment - CLAY_TEXT(CLAY_STRING("Child Alignment"), infoTitleConfig); - CLAY(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) { - alignX = CLAY_STRING("CENTER"); - } else if (layoutConfig->childAlignment.x == CLAY_ALIGN_X_RIGHT) { - alignX = CLAY_STRING("RIGHT"); - } - CLAY_TEXT(alignX, infoTextConfig); - CLAY_TEXT(CLAY_STRING(", y: "), infoTextConfig); - Clay_String alignY = CLAY_STRING("TOP"); - if (layoutConfig->childAlignment.y == CLAY_ALIGN_Y_CENTER) { - alignY = CLAY_STRING("CENTER"); - } else if (layoutConfig->childAlignment.y == CLAY_ALIGN_Y_BOTTOM) { - alignY = CLAY_STRING("BOTTOM"); - } - CLAY_TEXT(alignY, infoTextConfig); - CLAY_TEXT(CLAY_STRING(" }"), infoTextConfig); - } - } - for (int32_t elementConfigIndex = 0; elementConfigIndex < selectedItem->layoutElement->elementConfigs.length; ++elementConfigIndex) { - 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_RECTANGLE: { - Clay_RectangleElementConfig *rectangleConfig = elementConfig->config.rectangleElementConfig; - CLAY(CLAY_LAYOUT({ .padding = {CLAY__DEBUGVIEW_OUTER_PADDING, 8}, .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 = {CLAY__DEBUGVIEW_OUTER_PADDING, 8}, .childGap = 8, .layoutDirection = CLAY_TOP_TO_BOTTOM })) { - // .fontSize - CLAY_TEXT(CLAY_STRING("Font Size"), infoTitleConfig); - CLAY_TEXT(Clay__IntToString(textConfig->fontSize), infoTextConfig); - // .fontId - CLAY_TEXT(CLAY_STRING("Font ID"), infoTitleConfig); - CLAY_TEXT(Clay__IntToString(textConfig->fontId), infoTextConfig); - // .lineHeight - CLAY_TEXT(CLAY_STRING("Line Height"), infoTitleConfig); - CLAY_TEXT(textConfig->lineHeight == 0 ? CLAY_STRING("auto") : Clay__IntToString(textConfig->lineHeight), infoTextConfig); - // .letterSpacing - CLAY_TEXT(CLAY_STRING("Letter Spacing"), infoTitleConfig); - CLAY_TEXT(Clay__IntToString(textConfig->letterSpacing), infoTextConfig); - // .lineSpacing - CLAY_TEXT(CLAY_STRING("Wrap Mode"), infoTitleConfig); - Clay_String wrapMode = CLAY_STRING("WORDS"); - if (textConfig->wrapMode == CLAY_TEXT_WRAP_NONE) { - wrapMode = CLAY_STRING("NONE"); - } else if (textConfig->wrapMode == CLAY_TEXT_WRAP_NEWLINES) { - wrapMode = CLAY_STRING("NEWLINES"); - } - CLAY_TEXT(wrapMode, infoTextConfig); - // .textColor - CLAY_TEXT(CLAY_STRING("Text Color"), infoTitleConfig); - Clay__RenderDebugViewColor(textConfig->textColor, infoTextConfig); - } - break; - } - case CLAY__ELEMENT_CONFIG_TYPE_IMAGE: { - Clay_ImageElementConfig *imageConfig = elementConfig->config.imageElementConfig; - CLAY(CLAY_ID("Clay__DebugViewElementInfoImageBody"), CLAY_LAYOUT({ .padding = {CLAY__DEBUGVIEW_OUTER_PADDING, 8}, .childGap = 8, .layoutDirection = CLAY_TOP_TO_BOTTOM })) { - // .sourceDimensions - CLAY_TEXT(CLAY_STRING("Source Dimensions"), infoTitleConfig); - CLAY(CLAY_ID("Clay__DebugViewElementInfoImageDimensions")) { - CLAY_TEXT(CLAY_STRING("{ width: "), infoTextConfig); - CLAY_TEXT(Clay__IntToString(imageConfig->sourceDimensions.width), infoTextConfig); - CLAY_TEXT(CLAY_STRING(", height: "), infoTextConfig); - CLAY_TEXT(Clay__IntToString(imageConfig->sourceDimensions.height), infoTextConfig); - CLAY_TEXT(CLAY_STRING(" }"), infoTextConfig); - } - // Image Preview - CLAY_TEXT(CLAY_STRING("Preview"), infoTitleConfig); - CLAY(CLAY_LAYOUT({ .sizing = { CLAY_SIZING_GROW({ .max = imageConfig->sourceDimensions.width }), CLAY__DEFAULT_STRUCT }}), Clay__AttachElementConfig(CLAY__INIT(Clay_ElementConfigUnion) { .imageElementConfig = imageConfig }, CLAY__ELEMENT_CONFIG_TYPE_IMAGE)) {} - } - break; - } - case CLAY__ELEMENT_CONFIG_TYPE_SCROLL_CONTAINER: { - Clay_ScrollElementConfig *scrollConfig = elementConfig->config.scrollElementConfig; - CLAY(CLAY_LAYOUT({ .padding = {CLAY__DEBUGVIEW_OUTER_PADDING, 8}, .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); - // .horizontal - CLAY_TEXT(CLAY_STRING("Horizontal"), infoTitleConfig); - CLAY_TEXT(scrollConfig->horizontal ? CLAY_STRING("true") : CLAY_STRING("false") , infoTextConfig); - } - break; - } - case CLAY__ELEMENT_CONFIG_TYPE_FLOATING_CONTAINER: { - Clay_FloatingElementConfig *floatingConfig = elementConfig->config.floatingElementConfig; - CLAY(CLAY_LAYOUT({ .padding = {CLAY__DEBUGVIEW_OUTER_PADDING, 8}, .childGap = 8, .layoutDirection = CLAY_TOP_TO_BOTTOM })) { - // .offset - CLAY_TEXT(CLAY_STRING("Offset"), infoTitleConfig); - CLAY(CLAY_LAYOUT(CLAY__DEFAULT_STRUCT)) { - CLAY_TEXT(CLAY_STRING("{ x: "), infoTextConfig); - CLAY_TEXT(Clay__IntToString(floatingConfig->offset.x), infoTextConfig); - CLAY_TEXT(CLAY_STRING(", y: "), infoTextConfig); - CLAY_TEXT(Clay__IntToString(floatingConfig->offset.y), infoTextConfig); - CLAY_TEXT(CLAY_STRING(" }"), infoTextConfig); - } - // .expand - CLAY_TEXT(CLAY_STRING("Expand"), infoTitleConfig); - CLAY(CLAY_LAYOUT(CLAY__DEFAULT_STRUCT)) { - CLAY_TEXT(CLAY_STRING("{ width: "), infoTextConfig); - CLAY_TEXT(Clay__IntToString(floatingConfig->expand.width), infoTextConfig); - CLAY_TEXT(CLAY_STRING(", height: "), infoTextConfig); - CLAY_TEXT(Clay__IntToString(floatingConfig->expand.height), infoTextConfig); - CLAY_TEXT(CLAY_STRING(" }"), infoTextConfig); - } - // .zIndex - CLAY_TEXT(CLAY_STRING("z-index"), infoTitleConfig); - CLAY_TEXT(Clay__IntToString(floatingConfig->zIndex), infoTextConfig); - // .parentId - CLAY_TEXT(CLAY_STRING("Parent"), infoTitleConfig); - Clay_LayoutElementHashMapItem *hashItem = Clay__GetHashMapItem(floatingConfig->parentId); - CLAY_TEXT(hashItem->elementId.stringId, infoTextConfig); - } - break; - } - case CLAY__ELEMENT_CONFIG_TYPE_BORDER_CONTAINER: { - Clay_BorderElementConfig *borderConfig = elementConfig->config.borderElementConfig; - CLAY(CLAY_ID("Clay__DebugViewElementInfoBorderBody"), CLAY_LAYOUT({ .padding = {CLAY__DEBUGVIEW_OUTER_PADDING, 8}, .childGap = 8, .layoutDirection = CLAY_TOP_TO_BOTTOM })) { - // .left - CLAY_TEXT(CLAY_STRING("Left Border"), infoTitleConfig); - Clay__RenderDebugViewBorder(1, borderConfig->left, infoTextConfig); - // .right - CLAY_TEXT(CLAY_STRING("Right Border"), infoTitleConfig); - Clay__RenderDebugViewBorder(2, borderConfig->right, infoTextConfig); - // .top - CLAY_TEXT(CLAY_STRING("Top Border"), infoTitleConfig); - Clay__RenderDebugViewBorder(3, borderConfig->top, infoTextConfig); - // .bottom - CLAY_TEXT(CLAY_STRING("Bottom Border"), infoTitleConfig); - Clay__RenderDebugViewBorder(4, borderConfig->bottom, infoTextConfig); - // .betweenChildren - CLAY_TEXT(CLAY_STRING("Border Between Children"), infoTitleConfig); - Clay__RenderDebugViewBorder(5, borderConfig->betweenChildren, infoTextConfig); - // .cornerRadius - CLAY_TEXT(CLAY_STRING("Corner Radius"), infoTitleConfig); - Clay__RenderDebugViewCornerRadius(borderConfig->cornerRadius, infoTextConfig); - } - break; - } - case CLAY__ELEMENT_CONFIG_TYPE_CUSTOM: - default: break; - } - } - } - } else { - CLAY(CLAY_ID("Clay__DebugViewWarningsScrollPane"), CLAY_LAYOUT({ .sizing = {CLAY_SIZING_GROW(CLAY__DEFAULT_STRUCT), 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_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, 0}, .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(CLAY__DEFAULT_STRUCT), .height = CLAY_SIZING_FIXED(1)} }), CLAY_RECTANGLE({ .color = {200, 200, 200, 255} })) {} - int32_t previousWarningsLength = (int)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, 0}, .childGap = 8, .childAlignment = {.y = CLAY_ALIGN_Y_CENTER} })) { - CLAY_TEXT(warning.baseMessage, warningConfig); - if (warning.dynamicMessage.length > 0) { - CLAY_TEXT(warning.dynamicMessage, warningConfig); - } - } - } - } - } - } -} -#pragma endregion +//#pragma region DebugTools +//Clay_Color CLAY__DEBUGVIEW_COLOR_1 = {58, 56, 52, 255}; +//Clay_Color CLAY__DEBUGVIEW_COLOR_2 = {62, 60, 58, 255}; +//Clay_Color CLAY__DEBUGVIEW_COLOR_3 = {141, 133, 135, 255}; +//Clay_Color CLAY__DEBUGVIEW_COLOR_4 = {238, 226, 231, 255}; +//Clay_Color CLAY__DEBUGVIEW_COLOR_SELECTED_ROW = {102, 80, 78, 255}; +//const int32_t CLAY__DEBUGVIEW_ROW_HEIGHT = 30; +//const int32_t CLAY__DEBUGVIEW_OUTER_PADDING = 10; +//const int32_t CLAY__DEBUGVIEW_INDENT_WIDTH = 16; +//Clay_TextElementConfig Clay__DebugView_TextNameConfig = {.textColor = {238, 226, 231, 255}, .fontSize = 16, .wrapMode = CLAY_TEXT_WRAP_NONE }; +//Clay_LayoutConfig Clay__DebugView_ScrollViewItemLayoutConfig = CLAY__DEFAULT_STRUCT; +// +//CLAY__TYPEDEF(Clay__DebugElementConfigTypeLabelConfig, struct { +// Clay_String label; +// Clay_Color color; +//}); +// +//Clay__DebugElementConfigTypeLabelConfig Clay__DebugGetElementConfigTypeLabel(Clay__ElementConfigType type) { +// switch (type) { +// case CLAY__ELEMENT_CONFIG_TYPE_RECTANGLE: return CLAY__INIT(Clay__DebugElementConfigTypeLabelConfig) { CLAY_STRING("Rectangle"), {243,134,48,255} }; +// case CLAY__ELEMENT_CONFIG_TYPE_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_CUSTOM: return CLAY__INIT(Clay__DebugElementConfigTypeLabelConfig) { CLAY_STRING("Custom"), {11,72,107,255} }; +// default: break; +// } +// return CLAY__INIT(Clay__DebugElementConfigTypeLabelConfig) { CLAY_STRING("Error"), {0,0,0,255} }; +//} +// +//CLAY__TYPEDEF(Clay__RenderDebugLayoutData, struct { +// int32_t rowCount; +// int32_t selectedElementRowIndex; +//}); +// +//// Returns row count +//Clay__RenderDebugLayoutData Clay__RenderDebugLayoutElementsList(int32_t initialRootsLength, int32_t highlightedRowIndex) { +// Clay_Context* context = Clay_GetCurrentContext(); +// Clay__int32_tArray dfsBuffer = context->reusableElementIndexBuffer; +// Clay__DebugView_ScrollViewItemLayoutConfig = CLAY__INIT(Clay_LayoutConfig) { .sizing = { .height = CLAY_SIZING_FIXED(CLAY__DEBUGVIEW_ROW_HEIGHT) }, .childGap = 6, .childAlignment = { .y = CLAY_ALIGN_Y_CENTER }}; +// Clay__RenderDebugLayoutData layoutData = CLAY__DEFAULT_STRUCT; +// +// uint32_t highlightedElementId = 0; +// +// for (int32_t rootIndex = 0; rootIndex < initialRootsLength; ++rootIndex) { +// dfsBuffer.length = 0; +// Clay__LayoutElementTreeRoot *root = Clay__LayoutElementTreeRootArray_Get(&context->layoutElementTreeRoots, rootIndex); +// 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(CLAY__DEFAULT_STRUCT)}, .padding = {CLAY__DEBUGVIEW_INDENT_WIDTH / 2, 0} })) { +// CLAY(CLAY_IDI("Clay__DebugView_EmptyRow", rootIndex), CLAY_LAYOUT({ .sizing = { .width = CLAY_SIZING_GROW(CLAY__DEFAULT_STRUCT), .height = CLAY_SIZING_FIXED((float)CLAY__DEBUGVIEW_ROW_HEIGHT) }}), CLAY_BORDER({ .top = { .width = 1, .color = CLAY__DEBUGVIEW_COLOR_3 } })) {} +// } +// layoutData.rowCount++; +// } +// while (dfsBuffer.length > 0) { +// int32_t currentElementIndex = Clay__int32_tArray_Get(&dfsBuffer, (int)dfsBuffer.length - 1); +// Clay_LayoutElement *currentElement = Clay_LayoutElementArray_Get(&context->layoutElements, (int)currentElementIndex); +// if (context->treeNodeVisited.internalArray[dfsBuffer.length - 1]) { +// if (!Clay__ElementHasConfig(currentElement, CLAY__ELEMENT_CONFIG_TYPE_TEXT) && currentElement->childrenOrTextContent.children.length > 0) { +// Clay__CloseElement(); +// Clay__CloseElement(); +// Clay__CloseElement(); +// } +// dfsBuffer.length--; +// continue; +// } +// +// if (highlightedRowIndex == layoutData.rowCount) { +// if (context->pointerInfo.state == CLAY_POINTER_DATA_PRESSED_THIS_FRAME) { +// context->debugSelectedElementId = currentElement->id; +// } +// highlightedElementId = currentElement->id; +// } +// +// context->treeNodeVisited.internalArray[dfsBuffer.length - 1] = true; +// Clay_LayoutElementHashMapItem *currentElementData = Clay__GetHashMapItem(currentElement->id); +// bool offscreen = Clay__ElementIsOffscreen(¤tElementData->boundingBox); +// if (context->debugSelectedElementId == currentElement->id) { +// layoutData.selectedElementRowIndex = layoutData.rowCount; +// } +// CLAY(CLAY_IDI("Clay__DebugView_ElementOuter", currentElement->id), Clay__AttachLayoutConfig(&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_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) })) {} +// } +// } +// // Collisions and offscreen info +// if (currentElementData) { +// if (currentElementData->debugData->collision) { +// CLAY(CLAY_LAYOUT({ .padding = { 8, 2 } }), CLAY_BORDER_OUTSIDE_RADIUS(1, (CLAY__INIT(Clay_Color){177, 147, 8, 255}), 4)) { +// CLAY_TEXT(CLAY_STRING("Duplicate ID"), CLAY_TEXT_CONFIG({ .textColor = CLAY__DEBUGVIEW_COLOR_3, .fontSize = 16 })); +// } +// } +// if (offscreen) { +// CLAY(CLAY_LAYOUT({ .padding = { 8, 2 } }), CLAY_BORDER_OUTSIDE_RADIUS(1, CLAY__DEBUGVIEW_COLOR_3, 4)) { +// CLAY_TEXT(CLAY_STRING("Offscreen"), CLAY_TEXT_CONFIG({ .textColor = CLAY__DEBUGVIEW_COLOR_3, .fontSize = 16 })); +// } +// } +// } +// Clay_String idString = context->layoutElementIdStrings.internalArray[currentElementIndex]; +// if (idString.length > 0) { +// CLAY_TEXT(idString, offscreen ? CLAY_TEXT_CONFIG({ .textColor = CLAY__DEBUGVIEW_COLOR_3, .fontSize = 16 }) : &Clay__DebugView_TextNameConfig); +// } +// for (int32_t elementConfigIndex = 0; elementConfigIndex < currentElement->elementConfigs.length; ++elementConfigIndex) { +// Clay_ElementConfig *elementConfig = Clay__ElementConfigArraySlice_Get(¤tElement->elementConfigs, elementConfigIndex); +// Clay__DebugElementConfigTypeLabelConfig config = Clay__DebugGetElementConfigTypeLabel(elementConfig->type); +// Clay_Color backgroundColor = config.color; +// backgroundColor.a = 90; +// CLAY(CLAY_LAYOUT({ .padding = { 8, 2 } }), CLAY_RECTANGLE({ .color = backgroundColor, .cornerRadius = CLAY_CORNER_RADIUS(4) }), CLAY_BORDER_OUTSIDE_RADIUS(1, config.color, 4)) { +// CLAY_TEXT(config.label, CLAY_TEXT_CONFIG({ .textColor = offscreen ? CLAY__DEBUGVIEW_COLOR_3 : CLAY__DEBUGVIEW_COLOR_4, .fontSize = 16 })); +// } +// } +// } +// +// // Render the text contents below the element as a non-interactive row +// if (Clay__ElementHasConfig(currentElement, CLAY__ELEMENT_CONFIG_TYPE_TEXT)) { +// 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_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) { +// CLAY_TEXT(CLAY_STRING("..."), rawTextConfig); +// } +// CLAY_TEXT(CLAY_STRING("\""), rawTextConfig); +// } +// } else if (currentElement->childrenOrTextContent.children.length > 0) { +// Clay__OpenElement(); +// CLAY_LAYOUT({ .padding = { 8 , 0} }); +// Clay__ElementPostConfiguration(); +// 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__OpenElement(); +// CLAY_LAYOUT({ .layoutDirection = CLAY_TOP_TO_BOTTOM }); +// Clay__ElementPostConfiguration(); +// } +// +// layoutData.rowCount++; +// if (!(Clay__ElementHasConfig(currentElement, CLAY__ELEMENT_CONFIG_TYPE_TEXT) || (currentElementData && currentElementData->debugData->collapsed))) { +// for (int32_t i = currentElement->childrenOrTextContent.children.length - 1; i >= 0; --i) { +// Clay__int32_tArray_Add(&dfsBuffer, currentElement->childrenOrTextContent.children.elements[i]); +// context->treeNodeVisited.internalArray[dfsBuffer.length - 1] = false; // TODO needs to be ranged checked +// } +// } +// } +// } +// +// if (context->pointerInfo.state == CLAY_POINTER_DATA_PRESSED_THIS_FRAME) { +// Clay_ElementId collapseButtonId = Clay__HashString(CLAY_STRING("Clay__DebugView_CollapseElement"), 0, 0); +// for (int32_t i = (int)context->pointerOverIds.length - 1; i >= 0; i--) { +// Clay_ElementId *elementId = Clay__ElementIdArray_Get(&context->pointerOverIds, i); +// if (elementId->baseId == collapseButtonId.baseId) { +// Clay_LayoutElementHashMapItem *highlightedItem = Clay__GetHashMapItem(elementId->offset); +// highlightedItem->debugData->collapsed = !highlightedItem->debugData->collapsed; +// break; +// } +// } +// } +// +// if (highlightedElementId) { +// CLAY(CLAY_ID("Clay__DebugView_ElementHighlight"), CLAY_LAYOUT({ .sizing = {CLAY_SIZING_GROW(CLAY__DEFAULT_STRUCT), CLAY_SIZING_GROW(CLAY__DEFAULT_STRUCT)} }), CLAY_FLOATING({ .zIndex = 65535, .parentId = highlightedElementId })) { +// CLAY(CLAY_ID("Clay__DebugView_ElementHighlightRectangle"), CLAY_LAYOUT({ .sizing = {CLAY_SIZING_GROW(CLAY__DEFAULT_STRUCT), CLAY_SIZING_GROW(CLAY__DEFAULT_STRUCT)} }), CLAY_RECTANGLE({.color = Clay__debugViewHighlightColor })) {} +// } +// } +// return layoutData; +//} +// +//void Clay__RenderDebugLayoutSizing(Clay_SizingAxis sizing, Clay_TextElementConfig *infoTextConfig) { +// Clay_String sizingLabel = CLAY_STRING("GROW"); +// if (sizing.type == CLAY__SIZING_TYPE_FIT) { +// sizingLabel = CLAY_STRING("FIT"); +// } else if (sizing.type == CLAY__SIZING_TYPE_PERCENT) { +// sizingLabel = CLAY_STRING("PERCENT"); +// } +// CLAY_TEXT(sizingLabel, infoTextConfig); +// if (sizing.type == CLAY__SIZING_TYPE_GROW || sizing.type == CLAY__SIZING_TYPE_FIT) { +// CLAY_TEXT(CLAY_STRING("("), infoTextConfig); +// if (sizing.size.minMax.min != 0) { +// CLAY_TEXT(CLAY_STRING("min: "), infoTextConfig); +// CLAY_TEXT(Clay__IntToString(sizing.size.minMax.min), infoTextConfig); +// if (sizing.size.minMax.max != CLAY__MAXFLOAT) { +// CLAY_TEXT(CLAY_STRING(", "), infoTextConfig); +// } +// } +// if (sizing.size.minMax.max != CLAY__MAXFLOAT) { +// CLAY_TEXT(CLAY_STRING("max: "), infoTextConfig); +// CLAY_TEXT(Clay__IntToString(sizing.size.minMax.max), infoTextConfig); +// } +// CLAY_TEXT(CLAY_STRING(")"), infoTextConfig); +// } +//} +// +//void Clay__RenderDebugViewElementConfigHeader(Clay_String elementId, Clay__ElementConfigType type) { +// Clay__DebugElementConfigTypeLabelConfig config = Clay__DebugGetElementConfigTypeLabel(type); +// Clay_Color backgroundColor = config.color; +// backgroundColor.a = 90; +// CLAY(CLAY_LAYOUT({ .sizing = { CLAY_SIZING_GROW(CLAY__DEFAULT_STRUCT), CLAY_SIZING_FIXED(CLAY__DEBUGVIEW_ROW_HEIGHT + 8)}, .padding = { .x = CLAY__DEBUGVIEW_OUTER_PADDING }, .childAlignment = { .y = CLAY_ALIGN_Y_CENTER } })) { +// CLAY(CLAY_LAYOUT({ .padding = { 8, 2 } }), CLAY_RECTANGLE({ .color = backgroundColor, .cornerRadius = CLAY_CORNER_RADIUS(4) }), CLAY_BORDER_OUTSIDE_RADIUS(1, config.color, 4)) { +// CLAY_TEXT(config.label, CLAY_TEXT_CONFIG({ .textColor = CLAY__DEBUGVIEW_COLOR_4, .fontSize = 16 })); +// } +// CLAY(CLAY_LAYOUT({ .sizing = { .width = CLAY_SIZING_GROW(CLAY__DEFAULT_STRUCT) } })) {} +// 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_TEXT(CLAY_STRING("{ r: "), textConfig); +// CLAY_TEXT(Clay__IntToString(color.r), textConfig); +// CLAY_TEXT(CLAY_STRING(", g: "), textConfig); +// CLAY_TEXT(Clay__IntToString(color.g), textConfig); +// CLAY_TEXT(CLAY_STRING(", b: "), textConfig); +// CLAY_TEXT(Clay__IntToString(color.b), textConfig); +// 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) })) {} +// } +// } +//} +// +//void Clay__RenderDebugViewCornerRadius(Clay_CornerRadius cornerRadius, Clay_TextElementConfig *textConfig) { +// CLAY(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); +// CLAY_TEXT(Clay__IntToString(cornerRadius.topRight), textConfig); +// CLAY_TEXT(CLAY_STRING(", bottomLeft: "), textConfig); +// CLAY_TEXT(Clay__IntToString(cornerRadius.bottomLeft), textConfig); +// CLAY_TEXT(CLAY_STRING(", bottomRight: "), textConfig); +// CLAY_TEXT(Clay__IntToString(cornerRadius.bottomRight), textConfig); +// CLAY_TEXT(CLAY_STRING(" }"), textConfig); +// } +//} +// +//void Clay__RenderDebugViewBorder(int32_t index, Clay_Border border, Clay_TextElementConfig *textConfig) { +// (void) index; +// CLAY(CLAY_LAYOUT({ .childAlignment = {.y = CLAY_ALIGN_Y_CENTER} })) { +// CLAY_TEXT(CLAY_STRING("{ width: "), textConfig); +// CLAY_TEXT(Clay__IntToString(border.width), textConfig); +// CLAY_TEXT(CLAY_STRING(", color: "), textConfig); +// Clay__RenderDebugViewColor(border.color, textConfig); +// CLAY_TEXT(CLAY_STRING(" }"), textConfig); +// } +//} +// +//void HandleDebugViewCloseButtonInteraction(Clay_ElementId elementId, Clay_PointerData pointerInfo, intptr_t userData) { +// Clay_Context* context = Clay_GetCurrentContext(); +// (void) elementId; (void) pointerInfo; (void) userData; +// if (pointerInfo.state == CLAY_POINTER_DATA_PRESSED_THIS_FRAME) { +// context->debugModeEnabled = false; +// } +//} +// +//void Clay__RenderDebugView() { +// Clay_Context* context = Clay_GetCurrentContext(); +// Clay_ElementId closeButtonId = Clay__HashString(CLAY_STRING("Clay__DebugViewTopHeaderCloseButtonOuter"), 0, 0); +// if (context->pointerInfo.state == CLAY_POINTER_DATA_PRESSED_THIS_FRAME) { +// for (int32_t i = 0; i < context->pointerOverIds.length; ++i) { +// Clay_ElementId *elementId = Clay__ElementIdArray_Get(&context->pointerOverIds, i); +// if (elementId->id == closeButtonId.id) { +// context->debugModeEnabled = false; +// return; +// } +// } +// } +// +// uint32_t initialRootsLength = context->layoutElementTreeRoots.length; +// uint32_t initialElementsLength = context->layoutElements.length; +// Clay_TextElementConfig *infoTextConfig = CLAY_TEXT_CONFIG({ .textColor = CLAY__DEBUGVIEW_COLOR_4, .fontSize = 16, .wrapMode = CLAY_TEXT_WRAP_NONE }); +// Clay_TextElementConfig *infoTitleConfig = CLAY_TEXT_CONFIG({ .textColor = CLAY__DEBUGVIEW_COLOR_3, .fontSize = 16, .wrapMode = CLAY_TEXT_WRAP_NONE }); +// Clay_ElementId scrollId = Clay__HashString(CLAY_STRING("Clay__DebugViewOuterScrollPane"), 0, 0); +// float scrollYOffset = 0; +// for (int32_t i = 0; i < context->scrollContainerDatas.length; ++i) { +// Clay__ScrollContainerDataInternal *scrollContainerData = Clay__ScrollContainerDataInternalArray_Get(&context->scrollContainerDatas, i); +// if (scrollContainerData->elementId == scrollId.id) { +// if (!context->externalScrollHandlingEnabled) { +// scrollYOffset = scrollContainerData->scrollPosition.y; +// } +// break; +// } +// } +// int32_t highlightedRow = context->pointerInfo.position.y < context->layoutDimensions.height - 300 +// ? (int32_t)((context->pointerInfo.position.y - scrollYOffset) / (float)CLAY__DEBUGVIEW_ROW_HEIGHT) - 1 +// : -1; +// if (context->pointerInfo.position.x < context->layoutDimensions.width - (float)Clay__debugViewWidth) { +// highlightedRow = -1; +// } +// Clay__RenderDebugLayoutData layoutData = CLAY__DEFAULT_STRUCT; +// CLAY(CLAY_ID("Clay__DebugView"), +// CLAY_FLOATING({ .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(CLAY__DEFAULT_STRUCT), CLAY_SIZING_FIXED(CLAY__DEBUGVIEW_ROW_HEIGHT)}, .padding = {CLAY__DEBUGVIEW_OUTER_PADDING, 0}, .childAlignment = {.y = CLAY_ALIGN_Y_CENTER} }), CLAY_RECTANGLE({ .color = CLAY__DEBUGVIEW_COLOR_2 })) { +// CLAY_TEXT(CLAY_STRING("Clay Debug Tools"), infoTextConfig); +// CLAY(CLAY_LAYOUT({ .sizing = { CLAY_SIZING_GROW(CLAY__DEFAULT_STRUCT), CLAY__DEFAULT_STRUCT } })) {} +// // 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_TEXT(CLAY_STRING("x"), CLAY_TEXT_CONFIG({ .textColor = CLAY__DEBUGVIEW_COLOR_4, .fontSize = 16 })); +// } +// } +// CLAY(CLAY_LAYOUT({ .sizing = {CLAY_SIZING_GROW(CLAY__DEFAULT_STRUCT), CLAY_SIZING_FIXED(1)} }), CLAY_RECTANGLE({ .color = CLAY__DEBUGVIEW_COLOR_3 })) {} +// CLAY(Clay__AttachId(scrollId), CLAY_LAYOUT({ .sizing = {CLAY_SIZING_GROW(CLAY__DEFAULT_STRUCT), CLAY_SIZING_GROW(CLAY__DEFAULT_STRUCT)} }), CLAY_SCROLL({ .horizontal = true, .vertical = true })) { +// CLAY(CLAY_LAYOUT({ .sizing = {CLAY_SIZING_GROW(CLAY__DEFAULT_STRUCT), CLAY_SIZING_GROW(CLAY__DEFAULT_STRUCT)}, .layoutDirection = CLAY_TOP_TO_BOTTOM }), CLAY_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(CLAY__DEFAULT_STRUCT), CLAY_SIZING_GROW(CLAY__DEFAULT_STRUCT)} }), CLAY_FLOATING({ .pointerCaptureMode = CLAY_POINTER_CAPTURE_MODE_PASSTHROUGH })) { +// CLAY(CLAY_LAYOUT({ .sizing = {CLAY_SIZING_GROW(CLAY__DEFAULT_STRUCT), CLAY_SIZING_GROW(CLAY__DEFAULT_STRUCT)}, .padding = {.x = 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 })) {} +// 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) { +// rowColor = CLAY__DEBUGVIEW_COLOR_SELECTED_ROW; +// } +// if (i == highlightedRow) { +// rowColor.r *= 1.25f; +// rowColor.g *= 1.25f; +// rowColor.b *= 1.25f; +// } +// CLAY(CLAY_LAYOUT({ .sizing = {CLAY_SIZING_GROW(CLAY__DEFAULT_STRUCT), CLAY_SIZING_FIXED(CLAY__DEBUGVIEW_ROW_HEIGHT)}, .layoutDirection = CLAY_TOP_TO_BOTTOM }), CLAY_RECTANGLE({ .color = rowColor })) {} +// } +// } +// } +// CLAY(CLAY_LAYOUT({ .sizing = {.width = CLAY_SIZING_GROW(CLAY__DEFAULT_STRUCT), .height = CLAY_SIZING_FIXED(1)} }), CLAY_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(CLAY__DEFAULT_STRUCT), 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(CLAY__DEFAULT_STRUCT), CLAY_SIZING_FIXED(CLAY__DEBUGVIEW_ROW_HEIGHT + 8)}, .padding = {CLAY__DEBUGVIEW_OUTER_PADDING, 0}, .childAlignment = {.y = CLAY_ALIGN_Y_CENTER} })) { +// CLAY_TEXT(CLAY_STRING("Layout Config"), infoTextConfig); +// CLAY(CLAY_LAYOUT({ .sizing = { CLAY_SIZING_GROW(CLAY__DEFAULT_STRUCT), CLAY__DEFAULT_STRUCT } })) {} +// if (selectedItem->elementId.stringId.length != 0) { +// CLAY_TEXT(selectedItem->elementId.stringId, infoTitleConfig); +// if (selectedItem->elementId.offset != 0) { +// CLAY_TEXT(CLAY_STRING(" ("), infoTitleConfig); +// CLAY_TEXT(Clay__IntToString(selectedItem->elementId.offset), infoTitleConfig); +// CLAY_TEXT(CLAY_STRING(")"), infoTitleConfig); +// } +// } +// } +// // Clay_LayoutConfig debug info +// CLAY(CLAY_LAYOUT({ .padding = {CLAY__DEBUGVIEW_OUTER_PADDING, 8}, .childGap = 8, .layoutDirection = CLAY_TOP_TO_BOTTOM })) { +// // .boundingBox +// CLAY_TEXT(CLAY_STRING("Bounding Box"), infoTitleConfig); +// CLAY(CLAY_LAYOUT(CLAY__DEFAULT_STRUCT)) { +// CLAY_TEXT(CLAY_STRING("{ x: "), infoTextConfig); +// CLAY_TEXT(Clay__IntToString(selectedItem->boundingBox.x), infoTextConfig); +// CLAY_TEXT(CLAY_STRING(", y: "), infoTextConfig); +// CLAY_TEXT(Clay__IntToString(selectedItem->boundingBox.y), infoTextConfig); +// CLAY_TEXT(CLAY_STRING(", width: "), infoTextConfig); +// CLAY_TEXT(Clay__IntToString(selectedItem->boundingBox.width), infoTextConfig); +// CLAY_TEXT(CLAY_STRING(", height: "), infoTextConfig); +// CLAY_TEXT(Clay__IntToString(selectedItem->boundingBox.height), infoTextConfig); +// CLAY_TEXT(CLAY_STRING(" }"), infoTextConfig); +// } +// // .layoutDirection +// CLAY_TEXT(CLAY_STRING("Layout Direction"), infoTitleConfig); +// Clay_LayoutConfig *layoutConfig = selectedItem->layoutElement->layoutConfig; +// 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_TEXT(CLAY_STRING("width: "), infoTextConfig); +// Clay__RenderDebugLayoutSizing(layoutConfig->sizing.width, infoTextConfig); +// } +// CLAY(CLAY_LAYOUT(CLAY__DEFAULT_STRUCT)) { +// 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_TEXT(CLAY_STRING("{ x: "), infoTextConfig); +// CLAY_TEXT(Clay__IntToString(layoutConfig->padding.x), infoTextConfig); +// CLAY_TEXT(CLAY_STRING(", y: "), infoTextConfig); +// CLAY_TEXT(Clay__IntToString(layoutConfig->padding.y), infoTextConfig); +// CLAY_TEXT(CLAY_STRING(" }"), infoTextConfig); +// } +// // .childGap +// CLAY_TEXT(CLAY_STRING("Child Gap"), infoTitleConfig); +// CLAY_TEXT(Clay__IntToString(layoutConfig->childGap), infoTextConfig); +// // .childAlignment +// CLAY_TEXT(CLAY_STRING("Child Alignment"), infoTitleConfig); +// CLAY(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) { +// alignX = CLAY_STRING("CENTER"); +// } else if (layoutConfig->childAlignment.x == CLAY_ALIGN_X_RIGHT) { +// alignX = CLAY_STRING("RIGHT"); +// } +// CLAY_TEXT(alignX, infoTextConfig); +// CLAY_TEXT(CLAY_STRING(", y: "), infoTextConfig); +// Clay_String alignY = CLAY_STRING("TOP"); +// if (layoutConfig->childAlignment.y == CLAY_ALIGN_Y_CENTER) { +// alignY = CLAY_STRING("CENTER"); +// } else if (layoutConfig->childAlignment.y == CLAY_ALIGN_Y_BOTTOM) { +// alignY = CLAY_STRING("BOTTOM"); +// } +// CLAY_TEXT(alignY, infoTextConfig); +// CLAY_TEXT(CLAY_STRING(" }"), infoTextConfig); +// } +// } +// for (int32_t elementConfigIndex = 0; elementConfigIndex < selectedItem->layoutElement->elementConfigs.length; ++elementConfigIndex) { +// 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_RECTANGLE: { +// Clay_RectangleElementConfig *rectangleConfig = elementConfig->config.rectangleElementConfig; +// CLAY(CLAY_LAYOUT({ .padding = {CLAY__DEBUGVIEW_OUTER_PADDING, 8}, .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 = {CLAY__DEBUGVIEW_OUTER_PADDING, 8}, .childGap = 8, .layoutDirection = CLAY_TOP_TO_BOTTOM })) { +// // .fontSize +// CLAY_TEXT(CLAY_STRING("Font Size"), infoTitleConfig); +// CLAY_TEXT(Clay__IntToString(textConfig->fontSize), infoTextConfig); +// // .fontId +// CLAY_TEXT(CLAY_STRING("Font ID"), infoTitleConfig); +// CLAY_TEXT(Clay__IntToString(textConfig->fontId), infoTextConfig); +// // .lineHeight +// CLAY_TEXT(CLAY_STRING("Line Height"), infoTitleConfig); +// CLAY_TEXT(textConfig->lineHeight == 0 ? CLAY_STRING("auto") : Clay__IntToString(textConfig->lineHeight), infoTextConfig); +// // .letterSpacing +// CLAY_TEXT(CLAY_STRING("Letter Spacing"), infoTitleConfig); +// CLAY_TEXT(Clay__IntToString(textConfig->letterSpacing), infoTextConfig); +// // .lineSpacing +// CLAY_TEXT(CLAY_STRING("Wrap Mode"), infoTitleConfig); +// Clay_String wrapMode = CLAY_STRING("WORDS"); +// if (textConfig->wrapMode == CLAY_TEXT_WRAP_NONE) { +// wrapMode = CLAY_STRING("NONE"); +// } else if (textConfig->wrapMode == CLAY_TEXT_WRAP_NEWLINES) { +// wrapMode = CLAY_STRING("NEWLINES"); +// } +// CLAY_TEXT(wrapMode, infoTextConfig); +// // .textColor +// CLAY_TEXT(CLAY_STRING("Text Color"), infoTitleConfig); +// Clay__RenderDebugViewColor(textConfig->textColor, infoTextConfig); +// } +// break; +// } +// case CLAY__ELEMENT_CONFIG_TYPE_IMAGE: { +// Clay_ImageElementConfig *imageConfig = elementConfig->config.imageElementConfig; +// CLAY(CLAY_ID("Clay__DebugViewElementInfoImageBody"), CLAY_LAYOUT({ .padding = {CLAY__DEBUGVIEW_OUTER_PADDING, 8}, .childGap = 8, .layoutDirection = CLAY_TOP_TO_BOTTOM })) { +// // .sourceDimensions +// CLAY_TEXT(CLAY_STRING("Source Dimensions"), infoTitleConfig); +// CLAY(CLAY_ID("Clay__DebugViewElementInfoImageDimensions")) { +// CLAY_TEXT(CLAY_STRING("{ width: "), infoTextConfig); +// CLAY_TEXT(Clay__IntToString(imageConfig->sourceDimensions.width), infoTextConfig); +// CLAY_TEXT(CLAY_STRING(", height: "), infoTextConfig); +// CLAY_TEXT(Clay__IntToString(imageConfig->sourceDimensions.height), infoTextConfig); +// CLAY_TEXT(CLAY_STRING(" }"), infoTextConfig); +// } +// // Image Preview +// CLAY_TEXT(CLAY_STRING("Preview"), infoTitleConfig); +// CLAY(CLAY_LAYOUT({ .sizing = { CLAY_SIZING_GROW({ .max = imageConfig->sourceDimensions.width }), CLAY__DEFAULT_STRUCT }}), Clay__AttachElementConfig(CLAY__INIT(Clay_ElementConfigUnion) { .imageElementConfig = imageConfig }, CLAY__ELEMENT_CONFIG_TYPE_IMAGE)) {} +// } +// break; +// } +// case CLAY__ELEMENT_CONFIG_TYPE_SCROLL_CONTAINER: { +// Clay_ScrollElementConfig *scrollConfig = elementConfig->config.scrollElementConfig; +// CLAY(CLAY_LAYOUT({ .padding = {CLAY__DEBUGVIEW_OUTER_PADDING, 8}, .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); +// // .horizontal +// CLAY_TEXT(CLAY_STRING("Horizontal"), infoTitleConfig); +// CLAY_TEXT(scrollConfig->horizontal ? CLAY_STRING("true") : CLAY_STRING("false") , infoTextConfig); +// } +// break; +// } +// case CLAY__ELEMENT_CONFIG_TYPE_FLOATING_CONTAINER: { +// Clay_FloatingElementConfig *floatingConfig = elementConfig->config.floatingElementConfig; +// CLAY(CLAY_LAYOUT({ .padding = {CLAY__DEBUGVIEW_OUTER_PADDING, 8}, .childGap = 8, .layoutDirection = CLAY_TOP_TO_BOTTOM })) { +// // .offset +// CLAY_TEXT(CLAY_STRING("Offset"), infoTitleConfig); +// CLAY(CLAY_LAYOUT(CLAY__DEFAULT_STRUCT)) { +// CLAY_TEXT(CLAY_STRING("{ x: "), infoTextConfig); +// CLAY_TEXT(Clay__IntToString(floatingConfig->offset.x), infoTextConfig); +// CLAY_TEXT(CLAY_STRING(", y: "), infoTextConfig); +// CLAY_TEXT(Clay__IntToString(floatingConfig->offset.y), infoTextConfig); +// CLAY_TEXT(CLAY_STRING(" }"), infoTextConfig); +// } +// // .expand +// CLAY_TEXT(CLAY_STRING("Expand"), infoTitleConfig); +// CLAY(CLAY_LAYOUT(CLAY__DEFAULT_STRUCT)) { +// CLAY_TEXT(CLAY_STRING("{ width: "), infoTextConfig); +// CLAY_TEXT(Clay__IntToString(floatingConfig->expand.width), infoTextConfig); +// CLAY_TEXT(CLAY_STRING(", height: "), infoTextConfig); +// CLAY_TEXT(Clay__IntToString(floatingConfig->expand.height), infoTextConfig); +// CLAY_TEXT(CLAY_STRING(" }"), infoTextConfig); +// } +// // .zIndex +// CLAY_TEXT(CLAY_STRING("z-index"), infoTitleConfig); +// CLAY_TEXT(Clay__IntToString(floatingConfig->zIndex), infoTextConfig); +// // .parentId +// CLAY_TEXT(CLAY_STRING("Parent"), infoTitleConfig); +// Clay_LayoutElementHashMapItem *hashItem = Clay__GetHashMapItem(floatingConfig->parentId); +// CLAY_TEXT(hashItem->elementId.stringId, infoTextConfig); +// } +// break; +// } +// case CLAY__ELEMENT_CONFIG_TYPE_BORDER_CONTAINER: { +// Clay_BorderElementConfig *borderConfig = elementConfig->config.borderElementConfig; +// CLAY(CLAY_ID("Clay__DebugViewElementInfoBorderBody"), CLAY_LAYOUT({ .padding = {CLAY__DEBUGVIEW_OUTER_PADDING, 8}, .childGap = 8, .layoutDirection = CLAY_TOP_TO_BOTTOM })) { +// // .left +// CLAY_TEXT(CLAY_STRING("Left Border"), infoTitleConfig); +// Clay__RenderDebugViewBorder(1, borderConfig->left, infoTextConfig); +// // .right +// CLAY_TEXT(CLAY_STRING("Right Border"), infoTitleConfig); +// Clay__RenderDebugViewBorder(2, borderConfig->right, infoTextConfig); +// // .top +// CLAY_TEXT(CLAY_STRING("Top Border"), infoTitleConfig); +// Clay__RenderDebugViewBorder(3, borderConfig->top, infoTextConfig); +// // .bottom +// CLAY_TEXT(CLAY_STRING("Bottom Border"), infoTitleConfig); +// Clay__RenderDebugViewBorder(4, borderConfig->bottom, infoTextConfig); +// // .betweenChildren +// CLAY_TEXT(CLAY_STRING("Border Between Children"), infoTitleConfig); +// Clay__RenderDebugViewBorder(5, borderConfig->betweenChildren, infoTextConfig); +// // .cornerRadius +// CLAY_TEXT(CLAY_STRING("Corner Radius"), infoTitleConfig); +// Clay__RenderDebugViewCornerRadius(borderConfig->cornerRadius, infoTextConfig); +// } +// break; +// } +// case CLAY__ELEMENT_CONFIG_TYPE_CUSTOM: +// default: break; +// } +// } +// } +// } else { +// CLAY(CLAY_ID("Clay__DebugViewWarningsScrollPane"), CLAY_LAYOUT({ .sizing = {CLAY_SIZING_GROW(CLAY__DEFAULT_STRUCT), 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_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, 0}, .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(CLAY__DEFAULT_STRUCT), .height = CLAY_SIZING_FIXED(1)} }), CLAY_RECTANGLE({ .color = {200, 200, 200, 255} })) {} +// int32_t previousWarningsLength = (int)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, 0}, .childGap = 8, .childAlignment = {.y = CLAY_ALIGN_Y_CENTER} })) { +// CLAY_TEXT(warning.baseMessage, warningConfig); +// if (warning.dynamicMessage.length > 0) { +// CLAY_TEXT(warning.dynamicMessage, warningConfig); +// } +// } +// } +// } +// } +// } +//} +//#pragma endregion uint32_t Clay__debugViewWidth = 400; Clay_Color Clay__debugViewHighlightColor = { 168, 66, 28, 100 }; @@ -3622,8 +3662,8 @@ bool Clay__Array_AddCapacityCheck(int32_t length, int32_t capacity) CLAY_WASM_EXPORT("Clay_MinMemorySize") uint32_t Clay_MinMemorySize(void) { Clay_Context fakeContext = { - .maxElementCount = 8192, - .maxMeasureTextCacheWordCount = 16384, + .maxElementCount = Clay__defaultMaxElementCount, + .maxMeasureTextCacheWordCount = Clay__defaultMaxMeasureTextWordCacheCount, .internalArena = { .capacity = SIZE_MAX, .memory = (char*)&fakeContext, @@ -3735,14 +3775,18 @@ void Clay_SetPointerState(Clay_Vector2 position, bool isPointerDown) { CLAY_WASM_EXPORT("Clay_Initialize") Clay_Context* Clay_Initialize(Clay_Arena arena, Clay_Dimensions layoutDimensions, Clay_ErrorHandler errorHandler) { - Clay_Context* context = Clay__Context_Allocate_Arena(&arena); + Clay_Context *context = Clay__Context_Allocate_Arena(&arena); if (context == NULL) return NULL; // DEFAULTS - context->maxElementCount = 8192; - context->maxMeasureTextCacheWordCount = context->maxElementCount * 2; - context->errorHandler = CLAY__INIT(Clay_ErrorHandler) { Clay__ErrorHandlerFunctionDefault }; + Clay_Context *oldContext = Clay_GetCurrentContext(); + *context = CLAY__INIT(Clay_Context) { + .maxElementCount = oldContext ? oldContext->maxElementCount : Clay__defaultMaxElementCount, + .maxMeasureTextCacheWordCount = oldContext ? oldContext->maxMeasureTextCacheWordCount : Clay__defaultMaxElementCount * 2, + .errorHandler = errorHandler.errorHandlerFunction ? errorHandler : CLAY__INIT(Clay_ErrorHandler) { Clay__ErrorHandlerFunctionDefault }, + .layoutDimensions = layoutDimensions, + .internalArena = arena, + }; Clay_SetCurrentContext(context); - context->internalArena = arena; Clay__InitializePersistentMemory(context); Clay__InitializeEphemeralMemory(context); for (int32_t i = 0; i < context->layoutElementsHashMap.capacity; ++i) { @@ -3753,9 +3797,6 @@ Clay_Context* Clay_Initialize(Clay_Arena arena, Clay_Dimensions layoutDimensions } context->measureTextHashMapInternal.length = 1; // Reserve the 0 value to mean "no next element" context->layoutDimensions = layoutDimensions; - if (errorHandler.errorHandlerFunction) { - context->errorHandler = errorHandler; - } return context; } @@ -3897,10 +3938,10 @@ void Clay_BeginLayout(void) { context->booleanWarnings.maxElementsExceeded = false; context->booleanWarnings.maxTextMeasureCacheExceeded = false; context->booleanWarnings.maxRenderCommandsExceeded = false; - Clay__OpenElement((Clay_ElementDeclaration){}); - CLAY_ID("Clay__RootContainer"); - CLAY_LAYOUT({ .sizing = {CLAY_SIZING_FIXED((rootDimensions.width)), CLAY_SIZING_FIXED(rootDimensions.height)} }); - Clay__ElementPostConfiguration(); + Clay__OpenElement((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 }); } @@ -4028,7 +4069,11 @@ int32_t Clay_GetMaxElementCount(void) { CLAY_WASM_EXPORT("Clay_SetMaxElementCount") void Clay_SetMaxElementCount(int32_t maxElementCount) { Clay_Context* context = Clay_GetCurrentContext(); - context->maxElementCount = maxElementCount; + if (context) { + context->maxElementCount = maxElementCount; + } else { + Clay__defaultMaxElementCount = maxElementCount; // TODO: Fix this + } } CLAY_WASM_EXPORT("Clay_GetMaxMeasureTextCacheWordCount") @@ -4039,7 +4084,12 @@ int32_t Clay_GetMaxMeasureTextCacheWordCount(void) { CLAY_WASM_EXPORT("Clay_SetMaxMeasureTextCacheWordCount") void Clay_SetMaxMeasureTextCacheWordCount(int32_t maxMeasureTextCacheWordCount) { - Clay__currentContext->maxMeasureTextCacheWordCount = maxMeasureTextCacheWordCount; + Clay_Context* context = Clay_GetCurrentContext(); + if (context) { + Clay__currentContext->maxMeasureTextCacheWordCount = maxMeasureTextCacheWordCount; + } else { + Clay__defaultMaxMeasureTextWordCacheCount = maxMeasureTextCacheWordCount; // TODO: Fix this + } } #endif // CLAY_IMPLEMENTATION diff --git a/examples/multi-context-raylib-sidebar-scrolling-container/main.c b/examples/multi-context-raylib-sidebar-scrolling-container/main.c index 251add1..6ae9260 100644 --- a/examples/multi-context-raylib-sidebar-scrolling-container/main.c +++ b/examples/multi-context-raylib-sidebar-scrolling-container/main.c @@ -22,7 +22,7 @@ void HandleHeaderButtonInteraction(Clay_ElementId elementId, Clay_PointerData po // Examples of re-usable "Components" void RenderHeaderButton(Clay_String text) { CLAY({ - .layoutConfig = {.padding = {16, 8}}, + .layout = {.padding = {16, 8}}, .rectangle = {.color = Clay_Hovered() ? COLOR_BLUE : COLOR_ORANGE} }) { // Clay_OnHover(HandleHeaderButtonInteraction, 1)) { @@ -30,48 +30,51 @@ void RenderHeaderButton(Clay_String text) { } } -Clay_LayoutConfig dropdownTextItemLayout = (Clay_LayoutConfig) { .padding = {8, 4} }; -Clay_RectangleElementConfig dropdownRectangleConfig = (Clay_RectangleElementConfig) { .color = {180, 180, 180, 255} }; Clay_TextElementConfig dropdownTextElementConfig = (Clay_TextElementConfig) { .fontSize = 24, .textColor = {255,255,255,255} }; +Clay_ElementDeclaration dropdownItem = { + .layout = { .padding = {8, 4} }, + .rectangle = { .color = {180, 180, 180, 255} }, +}; + void RenderDropdownTextItem(int index) { - CLAY({ Clay_GetElementIdWithIndex(CLAY_STRING("ScrollContainerItem"), index), .layoutConfig = dropdownTextItemLayout, .rectangle = dropdownRectangleConfig }) { + CLAY_REUSE(&dropdownItem) { CLAY_TEXT(CLAY_STRING("I'm a text field in a scroll container."), &dropdownTextElementConfig); } } Clay_RenderCommandArray CreateLayout() { Clay_BeginLayout(); - CLAY({ .id = Clay_GetElementId(CLAY_STRING("OuterContainer")), .layoutConfig = { .sizing = { .width = CLAY_SIZING_GROW(), .height = CLAY_SIZING_GROW() }, .padding = { 16, 16 }, .childGap = 16 }, .rectangle = { .color = {200, 200, 200, 255} } }) { - CLAY({ .id = Clay_GetElementId(CLAY_STRING("SideBar")), .layoutConfig = { .layoutDirection = CLAY_TOP_TO_BOTTOM, .sizing = { .width = CLAY_SIZING_FIXED(300), .height = CLAY_SIZING_GROW() }, .padding = {16, 16}, .childGap = 16 }, .rectangle = { .color = {150, 150, 255, 255} }}) { - CLAY({ .id = Clay_GetElementId(CLAY_STRING("ProfilePictureOuter")), .layoutConfig = { .sizing = { .width = CLAY_SIZING_GROW() }, .padding = { 8, 8 }, .childGap = 8, .childAlignment = { .y = CLAY_ALIGN_Y_CENTER } }, .rectangle = { .color = {130, 130, 255, 255} }}) { - CLAY({ .id = Clay_GetElementId(CLAY_STRING("ProfilePicture")), .layoutConfig = { .sizing = { .width = CLAY_SIZING_FIXED(60), .height = CLAY_SIZING_FIXED(60) } }, .image = { .imageData = &profilePicture, .sourceDimensions = {60, 60} }}) {} + CLAY({ .id = CLAY_ID("OuterContainer"), .layout = { .sizing = { .width = CLAY_SIZING_GROW(), .height = CLAY_SIZING_GROW() }, .padding = { 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() }, .padding = {16, 16}, .childGap = 16 }, .rectangle = { .color = {150, 150, 255, 255} }}) { + CLAY({ .id = CLAY_ID("ProfilePictureOuter"), .layout = { .sizing = { .width = CLAY_SIZING_GROW() }, .padding = { 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({ .id = Clay_GetElementId(CLAY_STRING("SidebarBlob1")), .layoutConfig = { .sizing = { .width = CLAY_SIZING_GROW(), .height = CLAY_SIZING_FIXED(50) }}, .rectangle = { .color = {110, 110, 255, 255} }}) {} - CLAY({ .id = Clay_GetElementId(CLAY_STRING("SidebarBlob2")), .layoutConfig = { .sizing = { .width = CLAY_SIZING_GROW(), .height = CLAY_SIZING_FIXED(50) }}, .rectangle = { .color = {110, 110, 255, 255} }}) {} - CLAY({ .id = Clay_GetElementId(CLAY_STRING("SidebarBlob3")), .layoutConfig = { .sizing = { .width = CLAY_SIZING_GROW(), .height = CLAY_SIZING_FIXED(50) }}, .rectangle = { .color = {110, 110, 255, 255} }}) {} - CLAY({ .id = Clay_GetElementId(CLAY_STRING("SidebarBlob4")), .layoutConfig = { .sizing = { .width = CLAY_SIZING_GROW(), .height = CLAY_SIZING_FIXED(50) }}, .rectangle = { .color = {110, 110, 255, 255} }}) {} + CLAY({ .id = CLAY_ID("SidebarBlob1"), .layout = { .sizing = { .width = CLAY_SIZING_GROW(), .height = CLAY_SIZING_FIXED(50) }}, .rectangle = { .color = {110, 110, 255, 255} }}) {} + CLAY({ .id = CLAY_ID("SidebarBlob2"), .layout = { .sizing = { .width = CLAY_SIZING_GROW(), .height = CLAY_SIZING_FIXED(50) }}, .rectangle = { .color = {110, 110, 255, 255} }}) {} + CLAY({ .id = CLAY_ID("SidebarBlob3"), .layout = { .sizing = { .width = CLAY_SIZING_GROW(), .height = CLAY_SIZING_FIXED(50) }}, .rectangle = { .color = {110, 110, 255, 255} }}) {} + CLAY({ .id = CLAY_ID("SidebarBlob4"), .layout = { .sizing = { .width = CLAY_SIZING_GROW(), .height = CLAY_SIZING_FIXED(50) }}, .rectangle = { .color = {110, 110, 255, 255} }}) {} } - CLAY({ .id = Clay_GetElementId(CLAY_STRING("RightPanel")), .layoutConfig = { .layoutDirection = CLAY_TOP_TO_BOTTOM, .sizing = { .width = CLAY_SIZING_GROW(), .height = CLAY_SIZING_GROW() }, .childGap = 16 }}) { - CLAY({ .id = Clay_GetElementId(CLAY_STRING("HeaderBar")), .layoutConfig = { .sizing = { .width = CLAY_SIZING_GROW() }, .childAlignment = { .x = CLAY_ALIGN_X_RIGHT }, .padding = {8, 8}, .childGap = 8 }, .rectangle = { .color = {180, 180, 180, 255} }}) { + CLAY({ .id = CLAY_ID("RightPanel"), .layout = { .layoutDirection = CLAY_TOP_TO_BOTTOM, .sizing = { .width = CLAY_SIZING_GROW(), .height = CLAY_SIZING_GROW() }, .childGap = 16 }}) { + CLAY({ .id = CLAY_ID("HeaderBar"), .layout = { .sizing = { .width = CLAY_SIZING_GROW() }, .childAlignment = { .x = CLAY_ALIGN_X_RIGHT }, .padding = {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({ - .id = Clay_GetElementId(CLAY_STRING("MainContent")), + .id = CLAY_ID("MainContent"), .scroll = { .vertical = true }, - .layoutConfig = { .layoutDirection = CLAY_TOP_TO_BOTTOM, .padding = {16, 16}, .childGap = 16, .sizing = { CLAY_SIZING_GROW() } }, + .layout = { .layoutDirection = CLAY_TOP_TO_BOTTOM, .padding = {16, 16}, .childGap = 16, .sizing = { CLAY_SIZING_GROW() } }, .rectangle = { .color = {200, 200, 255, 255} } }){ CLAY({ - .id = Clay_GetElementId(CLAY_STRING("FloatingContainer")), - .layoutConfig = { .sizing = { .width = CLAY_SIZING_FIXED(300), .height = CLAY_SIZING_FIXED(300) }, .padding = { 16, 16 }}, + .id = CLAY_ID("FloatingContainer"), + .layout = { .sizing = { .width = CLAY_SIZING_FIXED(300), .height = CLAY_SIZING_FIXED(300) }, .padding = { 16, 16 }}, .floating = { .zIndex = 1, .attachment = { CLAY_ATTACH_POINT_CENTER_TOP, CLAY_ATTACH_POINT_CENTER_TOP }, .offset = {0, -16} }, .border = CLAY_BORDER_OUTSIDE({ .color = {80, 80, 80, 255}, .width = 2 }), - .rectangle = { .color = {140,80, 200, 200 } } + .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} })); } @@ -79,10 +82,10 @@ Clay_RenderCommandArray CreateLayout() { CLAY_TEXT(CLAY_STRING("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt."), CLAY_TEXT_CONFIG({ .fontId = FONT_ID_BODY_24, .fontSize = 24, .textColor = {0,0,0,255} })); - CLAY({ .id = Clay_GetElementId(CLAY_STRING("Photos2")), .layoutConfig = { .childGap = 16, .padding = { 16, 16 }}, .rectangle = { .color = {180, 180, 220, 255} }}) { - CLAY({ .id = Clay_GetElementId(CLAY_STRING("Picture4")), .layoutConfig = { .sizing = { .width = CLAY_SIZING_FIXED(120), .height = CLAY_SIZING_FIXED(120) }}, .image = { .imageData = &profilePicture, .sourceDimensions = {120, 120} }}) {} - CLAY({ .id = Clay_GetElementId(CLAY_STRING("Picture5")), .layoutConfig = { .sizing = { .width = CLAY_SIZING_FIXED(120), .height = CLAY_SIZING_FIXED(120) }}, .image = { .imageData = &profilePicture, .sourceDimensions = {120, 120} }}) {} - CLAY({ .id = Clay_GetElementId(CLAY_STRING("Picture6")), .layoutConfig = { .sizing = { .width = CLAY_SIZING_FIXED(120), .height = CLAY_SIZING_FIXED(120) }}, .image = { .imageData = &profilePicture, .sourceDimensions = {120, 120} }}) {} + CLAY({ .id = CLAY_ID("Photos2"), .layout = { .childGap = 16, .padding = { 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."), @@ -91,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({ .id = Clay_GetElementId(CLAY_STRING("Photos")), .layoutConfig = { .sizing = { .width = CLAY_SIZING_GROW() }, .childAlignment = { .x = CLAY_ALIGN_X_CENTER, .y = CLAY_ALIGN_Y_CENTER }, .childGap = 16, .padding = {16, 16} }, .rectangle = { .color = {180, 180, 220, 255} }}) { - CLAY({ .id = Clay_GetElementId(CLAY_STRING("Picture2")), .layoutConfig = { .sizing = { .width = CLAY_SIZING_FIXED(120), .height = CLAY_SIZING_FIXED(120) }}, .image = { .imageData = &profilePicture, .sourceDimensions = {120, 120} }}) {} - CLAY({ .id = Clay_GetElementId(CLAY_STRING("Picture1")), .layoutConfig = { .childAlignment = { .x = CLAY_ALIGN_X_CENTER }, .layoutDirection = CLAY_TOP_TO_BOTTOM, .padding = {8, 8} }, .rectangle = { .color = {170, 170, 220, 255} }}) { - CLAY({ .id = Clay_GetElementId(CLAY_STRING("ProfilePicture2")), .layoutConfig = { .sizing = { .width = CLAY_SIZING_FIXED(60), .height = CLAY_SIZING_FIXED(60) }}, .image = { .imageData = &profilePicture, .sourceDimensions = {60, 60} }}) {} + CLAY({ .id = CLAY_ID("Photos"), .layout = { .sizing = { .width = CLAY_SIZING_GROW() }, .childAlignment = { .x = CLAY_ALIGN_X_CENTER, .y = CLAY_ALIGN_Y_CENTER }, .childGap = 16, .padding = {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} }, .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({ .id = Clay_GetElementId(CLAY_STRING("Picture3")), .layoutConfig = { .sizing = { .width = CLAY_SIZING_FIXED(120), .height = CLAY_SIZING_FIXED(120) }}, .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."), @@ -105,32 +108,32 @@ Clay_RenderCommandArray CreateLayout() { } } - CLAY({ .id = Clay_GetElementId(CLAY_STRING("Blob4Floating2")), .floating = { .zIndex = 1, .parentId = Clay_GetElementId(CLAY_STRING("SidebarBlob4")).id }}) { - CLAY({ .id = Clay_GetElementId(CLAY_STRING("ScrollContainer")), .layoutConfig = { .sizing = { .height = CLAY_SIZING_FIXED(200) }, .childGap = 2 }, .scroll = { .vertical = true }}) { - CLAY({ .id = Clay_GetElementId(CLAY_STRING("FloatingContainer2")), .floating = { .zIndex = 1 }}) { - CLAY({ .id = Clay_GetElementId(CLAY_STRING("FloatingContainerInner")), .layoutConfig = { .sizing = { .width = CLAY_SIZING_FIXED(300), .height = CLAY_SIZING_FIXED(300) }, .padding = {16, 16} }, .rectangle = { .color = {140,80, 200, 200} }}) { + CLAY({ .id = CLAY_ID("Blob4Floating2"), .floating = { .zIndex = 1, .parentId = CLAY_ID("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} }, .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({ .id = Clay_GetElementId(CLAY_STRING("ScrollContainerInner")), .layoutConfig = { .layoutDirection = CLAY_TOP_TO_BOTTOM }, .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); } } } } - Clay_ScrollContainerData scrollData = Clay_GetScrollContainerData(Clay_GetElementId(CLAY_STRING("MainContent"))); + Clay_ScrollContainerData scrollData = Clay_GetScrollContainerData(CLAY_ID("MainContent")); if (scrollData.found) { - CLAY({ .id = Clay_GetElementId(CLAY_STRING("ScrollBar")), + 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, + .parentId = CLAY_ID("MainContent").id, .attachment = {.element = CLAY_ATTACH_POINT_RIGHT_TOP, .parent = CLAY_ATTACH_POINT_RIGHT_TOP} } }) { - CLAY({ .id = Clay_GetElementId(CLAY_STRING("ScrollBarButton")), - .layoutConfig = { .sizing = {CLAY_SIZING_FIXED(12), CLAY_SIZING_FIXED((scrollData.scrollContainerDimensions.height / scrollData.contentDimensions.height) * scrollData.scrollContainerDimensions.height) }}, + CLAY({ .id = CLAY_ID("ScrollBarButton"), + .layout = { .sizing = {CLAY_SIZING_FIXED(12), CLAY_SIZING_FIXED((scrollData.scrollContainerDimensions.height / scrollData.contentDimensions.height) * scrollData.scrollContainerDimensions.height) }}, .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} } }) {} } diff --git a/examples/raylib-multi-context/CMakeLists.txt b/examples/raylib-multi-context/CMakeLists.txt new file mode 100644 index 0000000..d5611cd --- /dev/null +++ b/examples/raylib-multi-context/CMakeLists.txt @@ -0,0 +1,35 @@ +cmake_minimum_required(VERSION 3.27) +project(clay_examples_raylib_multi_context C) +set(CMAKE_C_STANDARD 99) + +# Adding Raylib +include(FetchContent) +set(FETCHCONTENT_QUIET FALSE) +set(BUILD_EXAMPLES OFF CACHE BOOL "" FORCE) # don't build the supplied examples +set(BUILD_GAMES OFF CACHE BOOL "" FORCE) # don't build the supplied example games + +FetchContent_Declare( + raylib + GIT_REPOSITORY "https://github.com/raysan5/raylib.git" + GIT_TAG "master" + GIT_PROGRESS TRUE + GIT_SHALLOW TRUE +) + +FetchContent_MakeAvailable(raylib) + +add_executable(clay_examples_raylib_multi_context main.c) + +target_compile_options(clay_examples_raylib_multi_context PUBLIC) +target_include_directories(clay_examples_raylib_multi_context PUBLIC .) + +target_link_libraries(clay_examples_raylib_multi_context PUBLIC raylib) + +set(CMAKE_C_FLAGS_DEBUG "-Wall -Werror -Wno-error=missing-braces -DCLAY_DEBUG") +set(CMAKE_C_FLAGS_RELEASE "-O3") + +add_custom_command( + TARGET clay_examples_raylib_multi_context POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_directory + ${CMAKE_CURRENT_SOURCE_DIR}/resources + ${CMAKE_CURRENT_BINARY_DIR}/resources) diff --git a/examples/raylib-multi-context/main.c b/examples/raylib-multi-context/main.c new file mode 100644 index 0000000..6ce7c1b --- /dev/null +++ b/examples/raylib-multi-context/main.c @@ -0,0 +1,267 @@ +#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, 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 = { 16, 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 = {}; + +Clay_RenderCommandArray CreateLayout(Clay_Context* context, float yOffset, int32_t* documentIndex) { + Clay_SetCurrentContext(context); + Clay_SetDebugModeEnabled(true); + // Run once per frame + Clay_SetLayoutDimensions((Clay_Dimensions) { + .width = GetScreenWidth(), + .height = GetScreenHeight() / 2 + }); + + Vector2 mousePosition = GetMousePosition(); + mousePosition.y -= yOffset; + Vector2 scrollDelta = GetMouseWheelMoveV(); + Clay_SetPointerState( + (Clay_Vector2) { mousePosition.x, mousePosition.y }, + IsMouseButtonDown(0) + ); + Clay_UpdateScrollContainers( + true, + (Clay_Vector2) { scrollDelta.x, scrollDelta.y }, + GetFrameTime() + ); + + Clay_Sizing layoutExpand = { + .width = CLAY_SIZING_GROW(), + .height = CLAY_SIZING_GROW() + }; + + 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 = { 16, 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 = { 16, 16 }, + .childGap = 8, + .sizing = { + .width = CLAY_SIZING_FIXED(250), + .height = CLAY_SIZING_GROW() + } + }) + ) { + for (int i = 0; i < documents.length; i++) { + Document document = documents.documents[i]; + Clay_LayoutConfig sidebarButtonLayout = { + .sizing = { .width = CLAY_SIZING_GROW() }, + .padding = { 16, 16 } + }; + + if (i == *documentIndex) { + 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 { + 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 = 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 = { 16, 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; +} + + +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.") }, + { .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(); + + Clay_Arena clayMemoryTop = Clay_CreateArenaWithCapacityAndMemory(clayRequiredMemory, malloc(clayRequiredMemory)); + Clay_Context *clayContextTop = Clay_Initialize(clayMemoryTop, (Clay_Dimensions) { + .width = GetScreenWidth(), + .height = GetScreenHeight() / 2 + }, (Clay_ErrorHandler) { HandleClayErrors }); // This final argument is new since the video was published + + 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 + + Clay_SetMeasureTextFunction(Raylib_MeasureText); + Raylib_fonts[FONT_ID_BODY_16] = (Raylib_Font) { + .font = LoadFontEx("resources/Roboto-Regular.ttf", 48, 0, 400), + .fontId = FONT_ID_BODY_16 + }; + 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); + BeginDrawing(); + ClearBackground(BLACK); + Clay_Raylib_Render(renderCommandsTop); + Clay_Raylib_Render(renderCommandsBottom); + EndDrawing(); + } +} diff --git a/examples/raylib-multi-context/resources/Roboto-Regular.ttf b/examples/raylib-multi-context/resources/Roboto-Regular.ttf new file mode 100644 index 0000000..ddf4bfa Binary files /dev/null and b/examples/raylib-multi-context/resources/Roboto-Regular.ttf differ diff --git a/examples/raylib-multi-context/resources/RobotoMono-Medium.ttf b/examples/raylib-multi-context/resources/RobotoMono-Medium.ttf new file mode 100644 index 0000000..f6c149a Binary files /dev/null and b/examples/raylib-multi-context/resources/RobotoMono-Medium.ttf differ diff --git a/examples/raylib-multi-context/resources/profile-picture.png b/examples/raylib-multi-context/resources/profile-picture.png new file mode 100644 index 0000000..8c4ea3e Binary files /dev/null and b/examples/raylib-multi-context/resources/profile-picture.png differ diff --git a/examples/raylib-sidebar-scrolling-container/main.c b/examples/raylib-sidebar-scrolling-container/main.c index 9418cc3..25e523c 100644 --- a/examples/raylib-sidebar-scrolling-container/main.c +++ b/examples/raylib-sidebar-scrolling-container/main.c @@ -10,8 +10,8 @@ const uint32_t FONT_ID_BODY_16 = 1; Texture2D profilePicture; #define RAYLIB_VECTOR2_TO_CLAY_VECTOR2(vector) (Clay_Vector2) { .x = vector.x, .y = vector.y } -Clay_String profileText = CLAY_STRING("Profile Page one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen"); -Clay_TextElementConfig headerTextConfig = (Clay_TextElementConfig) { .fontId = 1, .fontSize = 16, .textColor = {0,0,0,255} }; +Clay_String profileText = {.length = 101, .chars = "Profile Page one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen" }; +Clay_TextElementConfig headerTextConfig = { .fontId = 1, .fontSize = 16, .textColor = {0,0,0,255} }; void HandleHeaderButtonInteraction(Clay_ElementId elementId, Clay_PointerData pointerData, intptr_t userData) { if (pointerData.state == CLAY_POINTER_DATA_PRESSED_THIS_FRAME) { @@ -28,9 +28,9 @@ void RenderHeaderButton(Clay_String text) { } } -Clay_LayoutConfig dropdownTextItemLayout = (Clay_LayoutConfig) { .padding = {8, 4} }; -Clay_RectangleElementConfig dropdownRectangleConfig = (Clay_RectangleElementConfig) { .color = {180, 180, 180, 255} }; -Clay_TextElementConfig dropdownTextElementConfig = (Clay_TextElementConfig) { .fontSize = 24, .textColor = {255,255,255,255} }; +Clay_LayoutConfig dropdownTextItemLayout = { .padding = {8, 4} }; +Clay_RectangleElementConfig dropdownRectangleConfig = { .color = {180, 180, 180, 255} }; +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)) { @@ -142,7 +142,7 @@ typedef struct bool mouseDown; } ScrollbarData; -ScrollbarData scrollbarData = (ScrollbarData) {}; +ScrollbarData scrollbarData = {}; bool debugEnabled = false;