[Core] Replace .scroll config with .clip

This commit is contained in:
Nic Barker 2025-04-10 12:02:18 +12:00
parent eb46688b82
commit b90598e193
2 changed files with 89 additions and 70 deletions

155
clay.h
View File

@ -492,11 +492,12 @@ CLAY__WRAPPER_STRUCT(Clay_CustomElementConfig);
// Controls the axis on which an element switches to "scrolling", which clips the contents and allows scrolling in that direction.
typedef struct {
bool horizontal; // Clip overflowing elements on the X axis and allow scrolling left and right.
bool vertical; // Clip overflowing elements on the YU axis and allow scrolling up and down.
} Clay_ScrollElementConfig;
bool horizontal; // Clip overflowing elements on the X axis.
bool vertical; // Clip overflowing elements on the Y axis.
Clay_Vector2 childOffset; // Offsets the x,y positions of all child elements. Used primarily for scrolling containers.
} Clay_ClipElementConfig;
CLAY__WRAPPER_STRUCT(Clay_ScrollElementConfig);
CLAY__WRAPPER_STRUCT(Clay_ClipElementConfig);
// Border -----------------------------
@ -578,7 +579,7 @@ typedef struct {
typedef struct {
bool horizontal;
bool vertical;
} Clay_ScrollRenderData;
} Clay_ClipRenderData;
// Render command data when commandType == CLAY_RENDER_COMMAND_TYPE_BORDER
typedef struct {
@ -604,8 +605,8 @@ typedef union {
Clay_CustomRenderData custom;
// Render command data when commandType == CLAY_RENDER_COMMAND_TYPE_BORDER
Clay_BorderRenderData border;
// Render command data when commandType == CLAY_RENDER_COMMAND_TYPE_SCROLL
Clay_ScrollRenderData scroll;
// Render command data when commandType == CLAY_RENDER_COMMAND_TYPE_SCISSOR_START|END
Clay_ClipRenderData clip;
} Clay_RenderData;
// Miscellaneous Structs & Enums ---------------------------------
@ -619,8 +620,8 @@ typedef struct {
Clay_Dimensions scrollContainerDimensions;
// The outer dimensions of the inner scroll container content, including the padding of the parent scroll container.
Clay_Dimensions contentDimensions;
// The config that was originally passed to the scroll element.
Clay_ScrollElementConfig config;
// The config that was originally passed to the clip element.
Clay_ClipElementConfig config;
// Indicates whether an actual scroll container matched the provided ID or if the default struct was returned.
bool found;
} Clay_ScrollContainerData;
@ -730,8 +731,8 @@ typedef struct {
Clay_FloatingElementConfig floating;
// Used to create CUSTOM render commands, usually to render element types not supported by Clay.
Clay_CustomElementConfig custom;
// Controls whether an element should clip its contents and allow scrolling rather than expanding to contain them.
Clay_ScrollElementConfig scroll;
// Controls whether an element should clip its contents, as well as providing child x,y offset configuration for scrolling.
Clay_ClipElementConfig clip;
// Controls settings related to element borders, and will generate BORDER render commands.
Clay_BorderElementConfig border;
// A pointer that will be transparently passed through to resulting render commands.
@ -816,6 +817,9 @@ CLAY_DLL_EXPORT void Clay_SetCurrentContext(Clay_Context* context);
// - scrollDelta is the amount to scroll this frame on each axis in pixels.
// - deltaTime is the time in seconds since the last "frame" (scroll update)
CLAY_DLL_EXPORT void Clay_UpdateScrollContainers(bool enableDragScrolling, Clay_Vector2 scrollDelta, float deltaTime);
// Returns the internally stored scroll offset for the currently open element.
// Generally intended for use with clip elements to create scrolling containers.
CLAY_DLL_EXPORT Clay_Vector2 Clay_GetScrollOffset();
// Updates the layout dimensions in response to the window or outer container being resized.
CLAY_DLL_EXPORT void Clay_SetLayoutDimensions(Clay_Dimensions dimensions);
// Called before starting any layout declarations.
@ -1035,7 +1039,7 @@ CLAY__ARRAY_DEFINE(Clay_TextElementConfig, Clay__TextElementConfigArray)
CLAY__ARRAY_DEFINE(Clay_ImageElementConfig, Clay__ImageElementConfigArray)
CLAY__ARRAY_DEFINE(Clay_FloatingElementConfig, Clay__FloatingElementConfigArray)
CLAY__ARRAY_DEFINE(Clay_CustomElementConfig, Clay__CustomElementConfigArray)
CLAY__ARRAY_DEFINE(Clay_ScrollElementConfig, Clay__ScrollElementConfigArray)
CLAY__ARRAY_DEFINE(Clay_ClipElementConfig, Clay__ClipElementConfigArray)
CLAY__ARRAY_DEFINE(Clay_BorderElementConfig, Clay__BorderElementConfigArray)
CLAY__ARRAY_DEFINE(Clay_String, Clay__StringArray)
CLAY__ARRAY_DEFINE(Clay_SharedElementConfig, Clay__SharedElementConfigArray)
@ -1045,7 +1049,7 @@ typedef CLAY_PACKED_ENUM {
CLAY__ELEMENT_CONFIG_TYPE_NONE,
CLAY__ELEMENT_CONFIG_TYPE_BORDER,
CLAY__ELEMENT_CONFIG_TYPE_FLOATING,
CLAY__ELEMENT_CONFIG_TYPE_SCROLL,
CLAY__ELEMENT_CONFIG_TYPE_CLIP,
CLAY__ELEMENT_CONFIG_TYPE_IMAGE,
CLAY__ELEMENT_CONFIG_TYPE_TEXT,
CLAY__ELEMENT_CONFIG_TYPE_CUSTOM,
@ -1057,7 +1061,7 @@ typedef union {
Clay_ImageElementConfig *imageElementConfig;
Clay_FloatingElementConfig *floatingElementConfig;
Clay_CustomElementConfig *customElementConfig;
Clay_ScrollElementConfig *scrollElementConfig;
Clay_ClipElementConfig *clipElementConfig;
Clay_BorderElementConfig *borderElementConfig;
Clay_SharedElementConfig *sharedElementConfig;
} Clay_ElementConfigUnion;
@ -1219,7 +1223,7 @@ struct Clay_Context {
Clay__TextElementConfigArray textElementConfigs;
Clay__ImageElementConfigArray imageElementConfigs;
Clay__FloatingElementConfigArray floatingElementConfigs;
Clay__ScrollElementConfigArray scrollElementConfigs;
Clay__ClipElementConfigArray clipElementConfigs;
Clay__CustomElementConfigArray customElementConfigs;
Clay__BorderElementConfigArray borderElementConfigs;
Clay__SharedElementConfigArray sharedElementConfigs;
@ -1287,7 +1291,7 @@ Clay_TextElementConfig * Clay__StoreTextElementConfig(Clay_TextElementConfig con
Clay_ImageElementConfig * Clay__StoreImageElementConfig(Clay_ImageElementConfig config) { return Clay_GetCurrentContext()->booleanWarnings.maxElementsExceeded ? &Clay_ImageElementConfig_DEFAULT : Clay__ImageElementConfigArray_Add(&Clay_GetCurrentContext()->imageElementConfigs, config); }
Clay_FloatingElementConfig * Clay__StoreFloatingElementConfig(Clay_FloatingElementConfig config) { return Clay_GetCurrentContext()->booleanWarnings.maxElementsExceeded ? &Clay_FloatingElementConfig_DEFAULT : Clay__FloatingElementConfigArray_Add(&Clay_GetCurrentContext()->floatingElementConfigs, config); }
Clay_CustomElementConfig * Clay__StoreCustomElementConfig(Clay_CustomElementConfig config) { return Clay_GetCurrentContext()->booleanWarnings.maxElementsExceeded ? &Clay_CustomElementConfig_DEFAULT : Clay__CustomElementConfigArray_Add(&Clay_GetCurrentContext()->customElementConfigs, config); }
Clay_ScrollElementConfig * Clay__StoreScrollElementConfig(Clay_ScrollElementConfig config) { return Clay_GetCurrentContext()->booleanWarnings.maxElementsExceeded ? &Clay_ScrollElementConfig_DEFAULT : Clay__ScrollElementConfigArray_Add(&Clay_GetCurrentContext()->scrollElementConfigs, config); }
Clay_ClipElementConfig * Clay__StoreClipElementConfig(Clay_ClipElementConfig config) { return Clay_GetCurrentContext()->booleanWarnings.maxElementsExceeded ? &Clay_ClipElementConfig_DEFAULT : Clay__ClipElementConfigArray_Add(&Clay_GetCurrentContext()->clipElementConfigs, config); }
Clay_BorderElementConfig * Clay__StoreBorderElementConfig(Clay_BorderElementConfig config) { return Clay_GetCurrentContext()->booleanWarnings.maxElementsExceeded ? &Clay_BorderElementConfig_DEFAULT : Clay__BorderElementConfigArray_Add(&Clay_GetCurrentContext()->borderElementConfigs, config); }
Clay_SharedElementConfig * Clay__StoreSharedElementConfig(Clay_SharedElementConfig config) { return Clay_GetCurrentContext()->booleanWarnings.maxElementsExceeded ? &Clay_SharedElementConfig_DEFAULT : Clay__SharedElementConfigArray_Add(&Clay_GetCurrentContext()->sharedElementConfigs, config); }
@ -1759,9 +1763,9 @@ void Clay__CloseElement(void) {
bool elementHasScrollVertical = false;
for (int32_t i = 0; i < openLayoutElement->elementConfigs.length; i++) {
Clay_ElementConfig *config = Clay__ElementConfigArraySlice_Get(&openLayoutElement->elementConfigs, i);
if (config->type == CLAY__ELEMENT_CONFIG_TYPE_SCROLL) {
elementHasScrollHorizontal = config->config.scrollElementConfig->horizontal;
elementHasScrollVertical = config->config.scrollElementConfig->vertical;
if (config->type == CLAY__ELEMENT_CONFIG_TYPE_CLIP) {
elementHasScrollHorizontal = config->config.clipElementConfig->horizontal;
elementHasScrollVertical = config->config.clipElementConfig->vertical;
context->openClipElementStack.length--;
break;
} else if (config->type == CLAY__ELEMENT_CONFIG_TYPE_FLOATING) {
@ -2072,8 +2076,8 @@ void Clay__ConfigureOpenElementPtr(const Clay_ElementDeclaration *declaration) {
openLayoutElementId = Clay__GenerateIdForAnonymousElement(openLayoutElement);
}
if (declaration->scroll.horizontal | declaration->scroll.vertical) {
Clay__AttachElementConfig(CLAY__INIT(Clay_ElementConfigUnion) { .scrollElementConfig = Clay__StoreScrollElementConfig(declaration->scroll) }, CLAY__ELEMENT_CONFIG_TYPE_SCROLL);
if (declaration->clip.horizontal | declaration->clip.vertical) {
Clay__AttachElementConfig(CLAY__INIT(Clay_ElementConfigUnion) { .clipElementConfig = Clay__StoreClipElementConfig(declaration->clip) }, CLAY__ELEMENT_CONFIG_TYPE_CLIP);
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;
@ -2116,7 +2120,7 @@ void Clay__InitializeEphemeralMemory(Clay_Context* context) {
context->textElementConfigs = Clay__TextElementConfigArray_Allocate_Arena(maxElementCount, arena);
context->imageElementConfigs = Clay__ImageElementConfigArray_Allocate_Arena(maxElementCount, arena);
context->floatingElementConfigs = Clay__FloatingElementConfigArray_Allocate_Arena(maxElementCount, arena);
context->scrollElementConfigs = Clay__ScrollElementConfigArray_Allocate_Arena(maxElementCount, arena);
context->clipElementConfigs = Clay__ClipElementConfigArray_Allocate_Arena(maxElementCount, arena);
context->customElementConfigs = Clay__CustomElementConfigArray_Allocate_Arena(maxElementCount, arena);
context->borderElementConfigs = Clay__BorderElementConfigArray_Allocate_Arena(maxElementCount, arena);
context->sharedElementConfigs = Clay__SharedElementConfigArray_Allocate_Arena(maxElementCount, arena);
@ -2255,8 +2259,8 @@ void Clay__SizeContainersAlongAxis(bool xAxis) {
float sizeToDistribute = parentSize - parentPadding - innerContentSize;
// The content is too large, compress the children as much as possible
if (sizeToDistribute < 0) {
// If the parent can scroll in the axis direction in this direction, don't compress children, just leave them alone
Clay_ScrollElementConfig *scrollElementConfig = Clay__FindElementConfigWithType(parent, CLAY__ELEMENT_CONFIG_TYPE_SCROLL).scrollElementConfig;
// If the parent clips content in this axis direction, don't compress children, just leave them alone
Clay_ClipElementConfig *scrollElementConfig = Clay__FindElementConfigWithType(parent, CLAY__ELEMENT_CONFIG_TYPE_CLIP).clipElementConfig;
if (scrollElementConfig) {
if (((xAxis && scrollElementConfig->horizontal) || (!xAxis && scrollElementConfig->vertical))) {
continue;
@ -2357,9 +2361,9 @@ void Clay__SizeContainersAlongAxis(bool xAxis) {
float maxSize = parentSize - parentPadding;
// If we're laying out the children of a scroll panel, grow containers expand to the size of the inner content, not the outer container
if (Clay__ElementHasConfig(parent, CLAY__ELEMENT_CONFIG_TYPE_SCROLL)) {
Clay_ScrollElementConfig *scrollElementConfig = Clay__FindElementConfigWithType(parent, CLAY__ELEMENT_CONFIG_TYPE_SCROLL).scrollElementConfig;
if (((xAxis && scrollElementConfig->horizontal) || (!xAxis && scrollElementConfig->vertical))) {
if (Clay__ElementHasConfig(parent, CLAY__ELEMENT_CONFIG_TYPE_CLIP)) {
Clay_ClipElementConfig *clipElementConfig = Clay__FindElementConfigWithType(parent, CLAY__ELEMENT_CONFIG_TYPE_CLIP).clipElementConfig;
if (((xAxis && clipElementConfig->horizontal) || (!xAxis && clipElementConfig->vertical))) {
maxSize = CLAY__MAX(maxSize, innerContentSize);
}
}
@ -2632,20 +2636,14 @@ void Clay__CalculateFinalLayout(void) {
if (clipHashMapItem) {
// Floating elements that are attached to scrolling contents won't be correctly positioned if external scroll handling is enabled, fix here
if (context->externalScrollHandlingEnabled) {
Clay_ScrollElementConfig *scrollConfig = Clay__FindElementConfigWithType(clipHashMapItem->layoutElement, CLAY__ELEMENT_CONFIG_TYPE_SCROLL).scrollElementConfig;
for (int32_t i = 0; i < context->scrollContainerDatas.length; i++) {
Clay__ScrollContainerDataInternal *mapping = Clay__ScrollContainerDataInternalArray_Get(&context->scrollContainerDatas, i);
if (mapping->layoutElement == clipHashMapItem->layoutElement) {
root->pointerOffset = mapping->scrollPosition;
if (scrollConfig->horizontal) {
rootPosition.x += mapping->scrollPosition.x;
}
if (scrollConfig->vertical) {
rootPosition.y += mapping->scrollPosition.y;
}
break;
}
Clay_ClipElementConfig *clipConfig = Clay__FindElementConfigWithType(clipHashMapItem->layoutElement, CLAY__ELEMENT_CONFIG_TYPE_CLIP).clipElementConfig;
if (clipConfig->horizontal) {
rootPosition.x += clipConfig->childOffset.x;
}
if (clipConfig->vertical) {
rootPosition.y += clipConfig->childOffset.y;
}
break;
}
Clay__AddRenderCommand(CLAY__INIT(Clay_RenderCommand) {
.boundingBox = clipHashMapItem->boundingBox,
@ -2681,8 +2679,8 @@ void Clay__CalculateFinalLayout(void) {
Clay__ScrollContainerDataInternal *scrollContainerData = CLAY__NULL;
// Apply scroll offsets to container
if (Clay__ElementHasConfig(currentElement, CLAY__ELEMENT_CONFIG_TYPE_SCROLL)) {
Clay_ScrollElementConfig *scrollConfig = Clay__FindElementConfigWithType(currentElement, CLAY__ELEMENT_CONFIG_TYPE_SCROLL).scrollElementConfig;
if (Clay__ElementHasConfig(currentElement, CLAY__ELEMENT_CONFIG_TYPE_CLIP)) {
Clay_ClipElementConfig *clipConfig = Clay__FindElementConfigWithType(currentElement, CLAY__ELEMENT_CONFIG_TYPE_CLIP).clipElementConfig;
// This linear scan could theoretically be slow under very strange conditions, but I can't imagine a real UI with more than a few 10's of scroll containers
for (int32_t i = 0; i < context->scrollContainerDatas.length; i++) {
@ -2690,10 +2688,10 @@ void Clay__CalculateFinalLayout(void) {
if (mapping->layoutElement == currentElement) {
scrollContainerData = mapping;
mapping->boundingBox = currentElementBoundingBox;
if (scrollConfig->horizontal) {
if (clipConfig->horizontal) {
scrollOffset.x = mapping->scrollPosition.x;
}
if (scrollConfig->vertical) {
if (clipConfig->vertical) {
scrollOffset.y = mapping->scrollPosition.y;
}
if (context->externalScrollHandlingEnabled) {
@ -2726,7 +2724,7 @@ void Clay__CalculateFinalLayout(void) {
int32_t next = sortedConfigIndexes[i + 1];
Clay__ElementConfigType currentType = Clay__ElementConfigArraySlice_Get(&currentElement->elementConfigs, current)->type;
Clay__ElementConfigType nextType = Clay__ElementConfigArraySlice_Get(&currentElement->elementConfigs, next)->type;
if (nextType == CLAY__ELEMENT_CONFIG_TYPE_SCROLL || currentType == CLAY__ELEMENT_CONFIG_TYPE_BORDER) {
if (nextType == CLAY__ELEMENT_CONFIG_TYPE_CLIP || currentType == CLAY__ELEMENT_CONFIG_TYPE_BORDER) {
sortedConfigIndexes[i] = next;
sortedConfigIndexes[i + 1] = current;
}
@ -2762,12 +2760,12 @@ void Clay__CalculateFinalLayout(void) {
shouldRender = false;
break;
}
case CLAY__ELEMENT_CONFIG_TYPE_SCROLL: {
case CLAY__ELEMENT_CONFIG_TYPE_CLIP: {
renderCommand.commandType = CLAY_RENDER_COMMAND_TYPE_SCISSOR_START;
renderCommand.renderData = CLAY__INIT(Clay_RenderData) {
.scroll = {
.horizontal = elementConfig->config.scrollElementConfig->horizontal,
.vertical = elementConfig->config.scrollElementConfig->vertical,
.clip = {
.horizontal = elementConfig->config.clipElementConfig->horizontal,
.vertical = elementConfig->config.clipElementConfig->vertical,
}
};
break;
@ -2910,15 +2908,15 @@ void Clay__CalculateFinalLayout(void) {
}
else {
// DFS is returning upwards backwards
bool closeScrollElement = false;
Clay_ScrollElementConfig *scrollConfig = Clay__FindElementConfigWithType(currentElement, CLAY__ELEMENT_CONFIG_TYPE_SCROLL).scrollElementConfig;
if (scrollConfig) {
closeScrollElement = true;
bool closeClipElement = false;
Clay_ClipElementConfig *clipConfig = Clay__FindElementConfigWithType(currentElement, CLAY__ELEMENT_CONFIG_TYPE_CLIP).clipElementConfig;
if (clipConfig) {
closeClipElement = true;
for (int32_t i = 0; i < context->scrollContainerDatas.length; i++) {
Clay__ScrollContainerDataInternal *mapping = Clay__ScrollContainerDataInternalArray_Get(&context->scrollContainerDatas, i);
if (mapping->layoutElement == currentElement) {
if (scrollConfig->horizontal) { scrollOffset.x = mapping->scrollPosition.x; }
if (scrollConfig->vertical) { scrollOffset.y = mapping->scrollPosition.y; }
if (clipConfig->horizontal) { scrollOffset.x = mapping->scrollPosition.x; }
if (clipConfig->vertical) { scrollOffset.y = mapping->scrollPosition.y; }
if (context->externalScrollHandlingEnabled) {
scrollOffset = CLAY__INIT(Clay_Vector2) CLAY__DEFAULT_STRUCT;
}
@ -2987,7 +2985,7 @@ void Clay__CalculateFinalLayout(void) {
}
}
// This exists because the scissor needs to end _after_ borders between elements
if (closeScrollElement) {
if (closeClipElement) {
Clay__AddRenderCommand(CLAY__INIT(Clay_RenderCommand) {
.id = Clay__HashNumber(currentElement->id, rootElement->childrenOrTextContent.children.length + 11).id,
.commandType = CLAY_RENDER_COMMAND_TYPE_SCISSOR_END,
@ -3075,7 +3073,7 @@ Clay__DebugElementConfigTypeLabelConfig Clay__DebugGetElementConfigTypeLabel(Cla
case CLAY__ELEMENT_CONFIG_TYPE_TEXT: return CLAY__INIT(Clay__DebugElementConfigTypeLabelConfig) { CLAY_STRING("Text"), {105,210,231,255} };
case CLAY__ELEMENT_CONFIG_TYPE_IMAGE: return CLAY__INIT(Clay__DebugElementConfigTypeLabelConfig) { CLAY_STRING("Image"), {121,189,154,255} };
case CLAY__ELEMENT_CONFIG_TYPE_FLOATING: return CLAY__INIT(Clay__DebugElementConfigTypeLabelConfig) { CLAY_STRING("Floating"), {250,105,0,255} };
case CLAY__ELEMENT_CONFIG_TYPE_SCROLL: return CLAY__INIT(Clay__DebugElementConfigTypeLabelConfig) {CLAY_STRING("Scroll"), {242, 196, 90, 255} };
case CLAY__ELEMENT_CONFIG_TYPE_CLIP: return CLAY__INIT(Clay__DebugElementConfigTypeLabelConfig) {CLAY_STRING("Scroll"), {242, 196, 90, 255} };
case CLAY__ELEMENT_CONFIG_TYPE_BORDER: return CLAY__INIT(Clay__DebugElementConfigTypeLabelConfig) {CLAY_STRING("Border"), {108, 91, 123, 255} };
case CLAY__ELEMENT_CONFIG_TYPE_CUSTOM: return CLAY__INIT(Clay__DebugElementConfigTypeLabelConfig) { CLAY_STRING("Custom"), {11,72,107,255} };
default: break;
@ -3382,7 +3380,7 @@ void Clay__RenderDebugView(void) {
}
}
CLAY({ .layout = { .sizing = {CLAY_SIZING_GROW(0), CLAY_SIZING_FIXED(1)} }, .backgroundColor = CLAY__DEBUGVIEW_COLOR_3 } ) {}
CLAY({ .id = scrollId, .layout = { .sizing = {CLAY_SIZING_GROW(0), CLAY_SIZING_GROW(0)} }, .scroll = { .horizontal = true, .vertical = true } }) {
CLAY({ .id = scrollId, .layout = { .sizing = {CLAY_SIZING_GROW(0), CLAY_SIZING_GROW(0)} }, .clip = { .horizontal = true, .vertical = true, .childOffset = Clay_GetScrollOffset() } }) {
CLAY({ .layout = { .sizing = {CLAY_SIZING_GROW(0), CLAY_SIZING_GROW(0)}, .layoutDirection = CLAY_TOP_TO_BOTTOM }, .backgroundColor = ((initialElementsLength + initialRootsLength) & 1) == 0 ? CLAY__DEBUGVIEW_COLOR_2 : CLAY__DEBUGVIEW_COLOR_1 }) {
Clay_ElementId panelContentsId = Clay__HashString(CLAY_STRING("Clay__DebugViewPaneOuter"), 0, 0);
// Element list
@ -3413,7 +3411,7 @@ void Clay__RenderDebugView(void) {
CLAY({
.layout = { .sizing = {CLAY_SIZING_GROW(0), CLAY_SIZING_FIXED(300)}, .layoutDirection = CLAY_TOP_TO_BOTTOM },
.backgroundColor = CLAY__DEBUGVIEW_COLOR_2 ,
.scroll = { .vertical = true },
.clip = { .vertical = true, .childOffset = Clay_GetScrollOffset() },
.border = { .color = CLAY__DEBUGVIEW_COLOR_3, .width = { .betweenChildren = 1 } }
}) {
CLAY({ .layout = { .sizing = {CLAY_SIZING_GROW(0), CLAY_SIZING_FIXED(CLAY__DEBUGVIEW_ROW_HEIGHT + 8)}, .padding = {CLAY__DEBUGVIEW_OUTER_PADDING, CLAY__DEBUGVIEW_OUTER_PADDING, 0, 0 }, .childAlignment = {.y = CLAY_ALIGN_Y_CENTER} } }) {
@ -3569,15 +3567,15 @@ void Clay__RenderDebugView(void) {
}
break;
}
case CLAY__ELEMENT_CONFIG_TYPE_SCROLL: {
Clay_ScrollElementConfig *scrollConfig = elementConfig->config.scrollElementConfig;
case CLAY__ELEMENT_CONFIG_TYPE_CLIP: {
Clay_ClipElementConfig *clipConfig = elementConfig->config.clipElementConfig;
CLAY({ .layout = { .padding = attributeConfigPadding, .childGap = 8, .layoutDirection = CLAY_TOP_TO_BOTTOM } }) {
// .vertical
CLAY_TEXT(CLAY_STRING("Vertical"), infoTitleConfig);
CLAY_TEXT(scrollConfig->vertical ? CLAY_STRING("true") : CLAY_STRING("false") , infoTextConfig);
CLAY_TEXT(clipConfig->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);
CLAY_TEXT(clipConfig->horizontal ? CLAY_STRING("true") : CLAY_STRING("false") , infoTextConfig);
}
break;
}
@ -3639,7 +3637,7 @@ void Clay__RenderDebugView(void) {
}
}
} else {
CLAY({ .id = CLAY_ID("Clay__DebugViewWarningsScrollPane"), .layout = { .sizing = {CLAY_SIZING_GROW(0), CLAY_SIZING_FIXED(300)}, .childGap = 6, .layoutDirection = CLAY_TOP_TO_BOTTOM }, .backgroundColor = CLAY__DEBUGVIEW_COLOR_2, .scroll = { .horizontal = true, .vertical = true } }) {
CLAY({ .id = CLAY_ID("Clay__DebugViewWarningsScrollPane"), .layout = { .sizing = {CLAY_SIZING_GROW(0), CLAY_SIZING_FIXED(300)}, .childGap = 6, .layoutDirection = CLAY_TOP_TO_BOTTOM }, .backgroundColor = CLAY__DEBUGVIEW_COLOR_2, .clip = { .horizontal = true, .vertical = true, .childOffset = Clay_GetScrollOffset() } }) {
Clay_TextElementConfig *warningConfig = CLAY_TEXT_CONFIG({ .textColor = CLAY__DEBUGVIEW_COLOR_4, .fontSize = 16, .wrapMode = CLAY_TEXT_WRAP_NONE });
CLAY({ .id = CLAY_ID("Clay__DebugViewWarningItemHeader"), .layout = { .sizing = {.height = CLAY_SIZING_FIXED(CLAY__DEBUGVIEW_ROW_HEIGHT)}, .padding = {CLAY__DEBUGVIEW_OUTER_PADDING, CLAY__DEBUGVIEW_OUTER_PADDING, 0, 0 }, .childGap = 8, .childAlignment = {.y = CLAY_ALIGN_Y_CENTER} } }) {
CLAY_TEXT(CLAY_STRING("Warnings"), warningConfig);
@ -3896,6 +3894,27 @@ void Clay_SetCurrentContext(Clay_Context* context) {
Clay__currentContext = context;
}
CLAY_WASM_EXPORT("Clay_GetScrollOffset")
Clay_Vector2 Clay_GetScrollOffset() {
Clay_Context* context = Clay_GetCurrentContext();
if (context->booleanWarnings.maxElementsExceeded) {
return CLAY__INIT(Clay_Vector2){};
}
Clay_LayoutElement *openLayoutElement = Clay__GetOpenLayoutElement();
// If the element has no id attached at this point, we need to generate one
if (openLayoutElement->id == 0) {
Clay__GenerateIdForAnonymousElement(openLayoutElement);
}
Clay_ClipElementConfig *clipConfig = Clay__FindElementConfigWithType(openLayoutElement, CLAY__ELEMENT_CONFIG_TYPE_CLIP).clipElementConfig;
for (int32_t i = 0; i < context->scrollContainerDatas.length; i++) {
Clay__ScrollContainerDataInternal *mapping = Clay__ScrollContainerDataInternalArray_Get(&context->scrollContainerDatas, i);
if (mapping->layoutElement == openLayoutElement) {
return mapping->scrollPosition;
}
}
return CLAY__INIT(Clay_Vector2){};
}
CLAY_WASM_EXPORT("Clay_UpdateScrollContainers")
void Clay_UpdateScrollContainers(bool enableDragScrolling, Clay_Vector2 scrollDelta, float deltaTime) {
Clay_Context* context = Clay_GetCurrentContext();
@ -3960,9 +3979,9 @@ void Clay_UpdateScrollContainers(bool enableDragScrolling, Clay_Vector2 scrollDe
if (highestPriorityElementIndex > -1 && highestPriorityScrollData) {
Clay_LayoutElement *scrollElement = highestPriorityScrollData->layoutElement;
Clay_ScrollElementConfig *scrollConfig = Clay__FindElementConfigWithType(scrollElement, CLAY__ELEMENT_CONFIG_TYPE_SCROLL).scrollElementConfig;
bool canScrollVertically = scrollConfig->vertical && highestPriorityScrollData->contentSize.height > scrollElement->dimensions.height;
bool canScrollHorizontally = scrollConfig->horizontal && highestPriorityScrollData->contentSize.width > scrollElement->dimensions.width;
Clay_ClipElementConfig *clipConfig = Clay__FindElementConfigWithType(scrollElement, CLAY__ELEMENT_CONFIG_TYPE_CLIP).clipElementConfig;
bool canScrollVertically = clipConfig->vertical && highestPriorityScrollData->contentSize.height > scrollElement->dimensions.height;
bool canScrollHorizontally = clipConfig->horizontal && highestPriorityScrollData->contentSize.width > scrollElement->dimensions.width;
// Handle wheel scroll
if (canScrollVertically) {
highestPriorityScrollData->scrollPosition.y = highestPriorityScrollData->scrollPosition.y + scrollDelta.y * 10;
@ -4122,7 +4141,7 @@ Clay_ScrollContainerData Clay_GetScrollContainerData(Clay_ElementId id) {
.scrollPosition = &scrollContainerData->scrollPosition,
.scrollContainerDimensions = { scrollContainerData->boundingBox.width, scrollContainerData->boundingBox.height },
.contentDimensions = scrollContainerData->contentSize,
.config = *Clay__FindElementConfigWithType(scrollContainerData->layoutElement, CLAY__ELEMENT_CONFIG_TYPE_SCROLL).scrollElementConfig,
.config = *Clay__FindElementConfigWithType(scrollContainerData->layoutElement, CLAY__ELEMENT_CONFIG_TYPE_CLIP).clipElementConfig,
.found = true
};
}

View File

@ -65,7 +65,7 @@ Clay_RenderCommandArray CreateLayout(void) {
CLAY({.id = CLAY_ID("MainContent"),
.layout = { .layoutDirection = CLAY_TOP_TO_BOTTOM, .padding = {16, 16, 16, 16}, .childGap = 16, .sizing = { .width = CLAY_SIZING_GROW(0) } },
.backgroundColor = {200, 200, 255, 255},
.scroll = { .vertical = true },
.clip = { .vertical = true, .childOffset = Clay_GetScrollOffset() },
})
{
CLAY({ .id = CLAY_ID("FloatingContainer"),
@ -107,7 +107,7 @@ Clay_RenderCommandArray CreateLayout(void) {
}
CLAY({ .id = CLAY_ID("Blob4Floating2"), .floating = { .attachTo = CLAY_ATTACH_TO_ELEMENT_WITH_ID, .zIndex = 1, .parentId = Clay_GetElementId(CLAY_STRING("SidebarBlob4")).id } }) {
CLAY({ .id = CLAY_ID("ScrollContainer"), .layout = { .sizing = { .height = CLAY_SIZING_FIXED(200) }, .childGap = 2 }, .scroll = { .vertical = true } }) {
CLAY({ .id = CLAY_ID("ScrollContainer"), .layout = { .sizing = { .height = CLAY_SIZING_FIXED(200) }, .childGap = 2 }, .clip = { .vertical = true, .childOffset = Clay_GetScrollOffset() } }) {
CLAY({ .id = CLAY_ID("FloatingContainer2"), .floating = { .attachTo = CLAY_ATTACH_TO_PARENT, .zIndex = 1 } }) {
CLAY({ .id = CLAY_ID("FloatingContainerInner"), .layout = { .sizing = { .width = CLAY_SIZING_FIXED(300), .height = CLAY_SIZING_FIXED(300) }, .padding = {16, 16, 16, 16} }, .backgroundColor = {140,80, 200, 200} }) {
CLAY_TEXT(CLAY_STRING("I'm an inline floating container."), CLAY_TEXT_CONFIG({ .fontSize = 24, .textColor = {255,255,255,255} }));