From eeb019656828350daeebfa98f9aa186b51cbc6e5 Mon Sep 17 00:00:00 2001 From: Nic Barker Date: Mon, 30 Mar 2026 10:46:55 +1100 Subject: [PATCH] Improve pointer handling and tidy up internal implementation' --- clay.h | 29 ++++---- examples/raylib-transitions/main.c | 105 ++++++++++++++--------------- 2 files changed, 67 insertions(+), 67 deletions(-) diff --git a/clay.h b/clay.h index f05bc37..9cf82f3 100644 --- a/clay.h +++ b/clay.h @@ -469,8 +469,6 @@ typedef CLAY_PACKED_ENUM { CLAY_ATTACH_TO_ELEMENT_WITH_ID, // Attaches this floating element to the root of the layout, which combined with the .offset field provides functionality similar to "absolute positioning". CLAY_ATTACH_TO_ROOT, - // Attaches this floating element to the root of the layout, which combined with the .offset field provides functionality similar to "absolute positioning". - CLAY_ATTACH_TO_INLINE, } Clay_FloatingAttachToElement; // Controls whether or not a floating element is clipped to the same clipping rectangle as the element it's attached to. @@ -1217,6 +1215,9 @@ typedef struct Clay_LayoutElement { uint32_t id; uint16_t floatingChildrenCount; bool isTextElement; + // True if the element is currently in an exit transition, and is "synthetic" + // i.e. data was retained from previous frames + bool exiting; } Clay_LayoutElement; CLAY__ARRAY_DEFINE(Clay_LayoutElement, Clay_LayoutElementArray) @@ -2333,7 +2334,7 @@ void Clay__SizeContainersAlongAxis(bool xAxis, float deltaTime, Clay__int32_tArr } // Note: setting isFirstChild = false is skipped here - if (childElement->config.floating.attachTo == CLAY_ATTACH_TO_INLINE) { + if (childElement->exiting) { continue; } @@ -3060,7 +3061,7 @@ void Clay__CalculateFinalLayout(float deltaTime, bool useStoredBoundingBoxes) { if (layoutConfig->layoutDirection == CLAY_LEFT_TO_RIGHT) { for (int32_t i = 0; i < currentElement->children.length; ++i) { Clay_LayoutElement *childElement = Clay_LayoutElementArray_Get(&context->layoutElements, currentElement->children.elements[i]); - if (childElement->config.floating.attachTo == CLAY_ATTACH_TO_INLINE) continue; + if (childElement->exiting) continue; contentSizeCurrent.width += childElement->dimensions.width; contentSizeCurrent.height = CLAY__MAX(contentSizeCurrent.height, childElement->dimensions.height); } @@ -3076,7 +3077,7 @@ void Clay__CalculateFinalLayout(float deltaTime, bool useStoredBoundingBoxes) { } else if (layoutConfig->layoutDirection == CLAY_TOP_TO_BOTTOM) { for (int32_t i = 0; i < currentElement->children.length; ++i) { Clay_LayoutElement *childElement = Clay_LayoutElementArray_Get(&context->layoutElements, currentElement->children.elements[i]); - if (childElement->config.floating.attachTo == CLAY_ATTACH_TO_INLINE) continue; + if (childElement->exiting) continue; contentSizeCurrent.width = CLAY__MAX(contentSizeCurrent.width, childElement->dimensions.width); contentSizeCurrent.height += childElement->dimensions.height; } @@ -3134,7 +3135,7 @@ void Clay__CalculateFinalLayout(float deltaTime, bool useStoredBoundingBoxes) { context->treeNodeVisited.internalArray[newNodeIndex] = false; // Update parent offsets - if (childElement->config.floating.attachTo != CLAY_ATTACH_TO_INLINE) { + if (!childElement->exiting) { if (layoutConfig->layoutDirection == CLAY_LEFT_TO_RIGHT) { currentElementTreeNode->nextChildOffset.x += childElement->dimensions.width + (float)layoutConfig->childGap; } else { @@ -4344,9 +4345,9 @@ Clay_RenderCommandArray Clay_EndLayout(float deltaTime) { if (parentHashMapItem->generation <= context->generation) { data->elementThisFrame->config.floating.attachTo = CLAY_ATTACH_TO_ROOT; data->elementThisFrame->config.floating.offset = CLAY__INIT(Clay_Vector2) { hashMapItem->boundingBox.x, hashMapItem->boundingBox.y }; - } else { - data->elementThisFrame->config.floating.attachTo = CLAY_ATTACH_TO_INLINE; + data->siblingIndex = 0; } + data->elementThisFrame->exiting = true; data->elementThisFrame->config.layout.sizing.width = CLAY_SIZING_FIXED(data->elementThisFrame->dimensions.width); data->elementThisFrame->config.layout.sizing.height = CLAY_SIZING_FIXED(data->elementThisFrame->dimensions.height); data->state = CLAY_TRANSITION_STATE_EXITING; @@ -4517,12 +4518,11 @@ Clay_RenderCommandArray Clay_EndLayout(float deltaTime) { } } - if (activeProperties != 0) { - if (transitionData->state == CLAY_TRANSITION_STATE_IDLE || transitionData->state == CLAY_TRANSITION_STATE_TRANSITIONING) { - transitionData->elapsedTime = 0; - transitionData->initialState = transitionData->currentState; - transitionData->state = CLAY_TRANSITION_STATE_TRANSITIONING; - } + if (activeProperties != 0 && transitionData->state != CLAY_TRANSITION_STATE_EXITING) { + transitionData->elapsedTime = 0; + transitionData->initialState = transitionData->currentState; + transitionData->state = CLAY_TRANSITION_STATE_TRANSITIONING; + transitionData->activeProperties = activeProperties; } if (transitionData->state == CLAY_TRANSITION_STATE_IDLE) { @@ -4548,6 +4548,7 @@ Clay_RenderCommandArray Clay_EndLayout(float deltaTime) { if (transitionData->state == CLAY_TRANSITION_STATE_ENTERING || transitionData->state == CLAY_TRANSITION_STATE_TRANSITIONING) {transitionData->state = CLAY_TRANSITION_STATE_IDLE; transitionData->elapsedTime = 0; transitionData->reparented = false; + transitionData->activeProperties = CLAY_TRANSITION_PROPERTY_NONE; } else if (transitionData->state == CLAY_TRANSITION_STATE_EXITING) { Clay__TransitionDataInternalArray_RemoveSwapback(&context->transitionDatas, i); } diff --git a/examples/raylib-transitions/main.c b/examples/raylib-transitions/main.c index ad5f8e4..66f84b6 100644 --- a/examples/raylib-transitions/main.c +++ b/examples/raylib-transitions/main.c @@ -71,58 +71,57 @@ typedef struct { Arena frameArena = {}; bool Clay_EaseOut(Clay_TransitionCallbackArguments arguments) { - float ratio = arguments.elapsedTime / arguments.duration; - if (ratio < 1) { - float lerpAmount = (1 - powf(1 - ratio, 3.0f)); - if (arguments.properties & CLAY_TRANSITION_PROPERTY_X) { - arguments.current->boundingBox.x = Lerp(arguments.initial.boundingBox.x, arguments.target.boundingBox.x, lerpAmount); - } - if (arguments.properties & CLAY_TRANSITION_PROPERTY_Y) { - arguments.current->boundingBox.y = Lerp(arguments.initial.boundingBox.y, arguments.target.boundingBox.y, lerpAmount); - } - if (arguments.properties & CLAY_TRANSITION_PROPERTY_WIDTH) { - arguments.current->boundingBox.width = Lerp(arguments.initial.boundingBox.width, arguments.target.boundingBox.width, lerpAmount); - } - if (arguments.properties & CLAY_TRANSITION_PROPERTY_HEIGHT) { - arguments.current->boundingBox.height = Lerp(arguments.initial.boundingBox.height, arguments.target.boundingBox.height, lerpAmount); - } - if (arguments.properties & CLAY_TRANSITION_PROPERTY_BACKGROUND_COLOR) { - arguments.current->backgroundColor = CLAY__INIT(Clay_Color) { - .r = Lerp(arguments.initial.backgroundColor.r, arguments.target.backgroundColor.r, lerpAmount), - .g = Lerp(arguments.initial.backgroundColor.g, arguments.target.backgroundColor.g, lerpAmount), - .b = Lerp(arguments.initial.backgroundColor.b, arguments.target.backgroundColor.b, lerpAmount), - .a = Lerp(arguments.initial.backgroundColor.a, arguments.target.backgroundColor.a, lerpAmount), - }; - } - if (arguments.properties & CLAY_TRANSITION_PROPERTY_OVERLAY_COLOR) { - arguments.current->overlayColor = CLAY__INIT(Clay_Color) { - .r = Lerp(arguments.initial.overlayColor.r, arguments.target.overlayColor.r, lerpAmount), - .g = Lerp(arguments.initial.overlayColor.g, arguments.target.overlayColor.g, lerpAmount), - .b = Lerp(arguments.initial.overlayColor.b, arguments.target.overlayColor.b, lerpAmount), - .a = Lerp(arguments.initial.overlayColor.a, arguments.target.overlayColor.a, lerpAmount), - }; - } - if (arguments.properties & CLAY_TRANSITION_PROPERTY_BORDER_COLOR) { - arguments.current->borderColor = CLAY__INIT(Clay_Color) { - .r = Lerp(arguments.initial.borderColor.r, arguments.target.borderColor.r, lerpAmount), - .g = Lerp(arguments.initial.borderColor.g, arguments.target.borderColor.g, lerpAmount), - .b = Lerp(arguments.initial.borderColor.b, arguments.target.borderColor.b, lerpAmount), - .a = Lerp(arguments.initial.borderColor.a, arguments.target.borderColor.a, lerpAmount), - }; - } - if (arguments.properties & CLAY_TRANSITION_PROPERTY_BORDER_WIDTH) { - arguments.current->borderWidth = CLAY__INIT(Clay_BorderWidth) { - .left = Lerp(arguments.initial.borderWidth.left, arguments.target.borderWidth.left, lerpAmount), - .right = Lerp(arguments.initial.borderWidth.right, arguments.target.borderWidth.right, lerpAmount), - .top = Lerp(arguments.initial.borderWidth.top, arguments.target.borderWidth.top, lerpAmount), - .bottom = Lerp(arguments.initial.borderWidth.bottom, arguments.target.borderWidth.bottom, lerpAmount), - .betweenChildren = Lerp(arguments.initial.borderWidth.betweenChildren, arguments.target.borderWidth.betweenChildren, lerpAmount), - }; - } - return false; - } else { - return true; + float ratio = 1; + if (arguments.duration > 0) { + ratio = arguments.elapsedTime / arguments.duration; } + float lerpAmount = (1 - powf(1 - CLAY__MIN(ratio, 1.f), 3.0f)); + if (arguments.properties & CLAY_TRANSITION_PROPERTY_X) { + arguments.current->boundingBox.x = Lerp(arguments.initial.boundingBox.x, arguments.target.boundingBox.x, lerpAmount); + } + if (arguments.properties & CLAY_TRANSITION_PROPERTY_Y) { + arguments.current->boundingBox.y = Lerp(arguments.initial.boundingBox.y, arguments.target.boundingBox.y, lerpAmount); + } + if (arguments.properties & CLAY_TRANSITION_PROPERTY_WIDTH) { + arguments.current->boundingBox.width = Lerp(arguments.initial.boundingBox.width, arguments.target.boundingBox.width, lerpAmount); + } + if (arguments.properties & CLAY_TRANSITION_PROPERTY_HEIGHT) { + arguments.current->boundingBox.height = Lerp(arguments.initial.boundingBox.height, arguments.target.boundingBox.height, lerpAmount); + } + if (arguments.properties & CLAY_TRANSITION_PROPERTY_BACKGROUND_COLOR) { + arguments.current->backgroundColor = CLAY__INIT(Clay_Color) { + .r = Lerp(arguments.initial.backgroundColor.r, arguments.target.backgroundColor.r, lerpAmount), + .g = Lerp(arguments.initial.backgroundColor.g, arguments.target.backgroundColor.g, lerpAmount), + .b = Lerp(arguments.initial.backgroundColor.b, arguments.target.backgroundColor.b, lerpAmount), + .a = Lerp(arguments.initial.backgroundColor.a, arguments.target.backgroundColor.a, lerpAmount), + }; + } + if (arguments.properties & CLAY_TRANSITION_PROPERTY_OVERLAY_COLOR) { + arguments.current->overlayColor = CLAY__INIT(Clay_Color) { + .r = Lerp(arguments.initial.overlayColor.r, arguments.target.overlayColor.r, lerpAmount), + .g = Lerp(arguments.initial.overlayColor.g, arguments.target.overlayColor.g, lerpAmount), + .b = Lerp(arguments.initial.overlayColor.b, arguments.target.overlayColor.b, lerpAmount), + .a = Lerp(arguments.initial.overlayColor.a, arguments.target.overlayColor.a, lerpAmount), + }; + } + if (arguments.properties & CLAY_TRANSITION_PROPERTY_BORDER_COLOR) { + arguments.current->borderColor = CLAY__INIT(Clay_Color) { + .r = Lerp(arguments.initial.borderColor.r, arguments.target.borderColor.r, lerpAmount), + .g = Lerp(arguments.initial.borderColor.g, arguments.target.borderColor.g, lerpAmount), + .b = Lerp(arguments.initial.borderColor.b, arguments.target.borderColor.b, lerpAmount), + .a = Lerp(arguments.initial.borderColor.a, arguments.target.borderColor.a, lerpAmount), + }; + } + if (arguments.properties & CLAY_TRANSITION_PROPERTY_BORDER_WIDTH) { + arguments.current->borderWidth = CLAY__INIT(Clay_BorderWidth) { + .left = Lerp(arguments.initial.borderWidth.left, arguments.target.borderWidth.left, lerpAmount), + .right = Lerp(arguments.initial.borderWidth.right, arguments.target.borderWidth.right, lerpAmount), + .top = Lerp(arguments.initial.borderWidth.top, arguments.target.borderWidth.top, lerpAmount), + .bottom = Lerp(arguments.initial.borderWidth.bottom, arguments.target.borderWidth.bottom, lerpAmount), + .betweenChildren = Lerp(arguments.initial.borderWidth.betweenChildren, arguments.target.borderWidth.betweenChildren, lerpAmount), + }; + } + return ratio >= 1; } Clay_TransitionData EnterExitSlideUp(Clay_TransitionData initialState, Clay_TransitionProperty properties) { @@ -273,12 +272,12 @@ Clay_RenderCommandArray CreateLayout(void) { .layout.sizing = {CLAY_SIZING_GROW(), CLAY_SIZING_GROW() }, .layout.childAlignment = { CLAY_ALIGN_X_CENTER, CLAY_ALIGN_Y_CENTER }, .backgroundColor = boxColor, - .overlayColor = Clay_Hovered() ? (Clay_Color) { 80, 80, 80, 80 } : (Clay_Color) { 255, 255, 255, 0 }, + .overlayColor = Clay_Hovered() ? (Clay_Color) { 140, 140, 140, 80 } : (Clay_Color) { 255, 255, 255, 0 }, .cornerRadius = {12, 12, 12, 12}, .border = { darker, CLAY_BORDER_OUTSIDE(3) }, .transition = { .handler = Clay_EaseOut, - .duration = 0.5f, + .duration = Clay_Hovered() && Clay_GetPointerState().state != CLAY_POINTER_DATA_PRESSED_THIS_FRAME ? 0.f : 0.5f, .properties = CLAY_TRANSITION_PROPERTY_WIDTH | CLAY_TRANSITION_PROPERTY_POSITION | CLAY_TRANSITION_PROPERTY_OVERLAY_COLOR | CLAY_TRANSITION_PROPERTY_BACKGROUND_COLOR, .enter = { .setInitialState = EnterExitSlideUp }, .exit = { .setFinalState = EnterExitSlideUp },