From 5e677cafb56e1b8c6999edc53f34c142fb9e995e Mon Sep 17 00:00:00 2001 From: Nic Barker Date: Tue, 27 Aug 2024 10:16:55 +1200 Subject: [PATCH] Add scrollbar to official website and improve culling (#2) --- clay.h | 7 ++- examples/clay-official-website/index.html | 54 +++++++++++----------- examples/clay-official-website/main.c | 52 ++++++++++++++++++++- renderers/raylib/clay_renderer_raylib.c | 8 +++- renderers/web/html/clay-html-renderer.html | 27 +++++------ 5 files changed, 103 insertions(+), 45 deletions(-) diff --git a/clay.h b/clay.h index 377e8fb..8a40bef 100644 --- a/clay.h +++ b/clay.h @@ -1900,7 +1900,7 @@ void Clay__CalculateFinalLayout(int screenWidth, int screenHeight) { hashMapItem->boundingBox = renderCommand.boundingBox; } - // Don't bother to generate render commands for rectangles entirely outside the screen - this won't stop their children from being rendered if they overflow + // Culling - Don't bother to generate render commands for rectangles entirely outside the screen - this won't stop their children from being rendered if they overflow bool offscreen = currentElementBoundingBox.x > (float)screenWidth || currentElementBoundingBox.y > (float)screenHeight || currentElementBoundingBox.x + currentElementBoundingBox.width < 0 || currentElementBoundingBox.y + currentElementBoundingBox.height < 0; bool shouldRender = !offscreen; switch (renderCommand.commandType) { @@ -1976,6 +1976,11 @@ void Clay__CalculateFinalLayout(int screenWidth, int screenHeight) { // Borders between elements are expressed as additional rectangle render commands } else if (currentElement->elementType == CLAY__LAYOUT_ELEMENT_TYPE_BORDER_CONTAINER) { Clay_Rectangle currentElementBoundingBox = (Clay_Rectangle) { currentElementTreeNode->position.x, currentElementTreeNode->position.y, currentElement->dimensions.width, currentElement->dimensions.height }; + bool offscreen = currentElementBoundingBox.x > (float)screenWidth || currentElementBoundingBox.y > (float)screenHeight || currentElementBoundingBox.x + currentElementBoundingBox.width < 0 || currentElementBoundingBox.y + currentElementBoundingBox.height < 0; + if (offscreen) { + dfsBuffer.length--; + continue; + } Clay_BorderContainerElementConfig *borderConfig = currentElement->elementConfig.borderElementConfig; Clay_RenderCommandArray_Add(&Clay__renderCommands, (Clay_RenderCommand) { diff --git a/examples/clay-official-website/index.html b/examples/clay-official-website/index.html index d430675..227d72a 100644 --- a/examples/clay-official-website/index.html +++ b/examples/clay-official-website/index.html @@ -254,6 +254,11 @@ document.addEventListener("mousedown", (event) => { window.mouseDown = true; + window.mouseDownThisFrame = true; + }); + + document.addEventListener("mouseup", (event) => { + window.mouseDown = false; }); const importObject = { @@ -315,6 +320,9 @@ } element = document.createElement(elementType); element.id = renderCommand.id.value; + if (renderCommand.commandType.value === CLAY_RENDER_COMMAND_TYPE_SCISSOR_START) { + element.style.overflow = 'hidden'; + } elementCache[renderCommand.id.value] = { exists: true, element: element, @@ -324,7 +332,6 @@ }; } - let dirty = false; let elementData = elementCache[renderCommand.id.value]; element = elementData.element; if (Array.prototype.indexOf.call(parentElement.element.children, element) !== parentElement.nextElementIndex) { @@ -337,12 +344,8 @@ elementData.exists = true; // Don't get me started. Cheaper to compare the render command memory than to update HTML elements - if (renderCommand.commandType.value !== CLAY_RENDER_COMMAND_TYPE_SCISSOR_START && renderCommand.commandType.value !== CLAY_RENDER_COMMAND_TYPE_SCISSOR_END) { - dirty = MemoryIsDifferent(elementData.previousMemoryCommand, entireRenderCommandMemory, renderCommandSize); - parentElement.nextElementIndex++; - } else { - dirty = true; - } + let dirty = MemoryIsDifferent(elementData.previousMemoryCommand, entireRenderCommandMemory, renderCommandSize); + parentElement.nextElementIndex++; elementData.previousMemoryCommand = entireRenderCommandMemory; let offsetX = scissorStack.length > 0 ? scissorStack[scissorStack.length - 1].nextAllocation.x : 0; @@ -361,7 +364,7 @@ let config = readStructAtAddress(renderCommand.config.value, rectangleConfigDefinition); let configMemory = new Uint8Array(memoryDataView.buffer.slice(renderCommand.config.value, renderCommand.config.value + config.__size)); let linkContents = config.link.length.value > 0 ? textDecoder.decode(new Uint8Array(memoryDataView.buffer.slice(config.link.chars.value, config.link.chars.value + config.link.length.value))) : 0; - if (linkContents.length > 0 && (window.mouseDown || window.touchDown) && instance.exports.Clay_PointerOver(renderCommand.id.value)) { + if (linkContents.length > 0 && (window.mouseDownThisFrame || window.touchDown) && instance.exports.Clay_PointerOver(renderCommand.id.value)) { window.location.href = linkContents; } if (!dirty && !MemoryIsDifferent(configMemory, elementData.previousMemoryConfig, config.__size)) { @@ -377,7 +380,7 @@ } elementData.previousMemoryConfig = configMemory; let color = config.color; - element.style.backgroundColor = `rgba(${color.r.value}, ${color.g.value}, ${color.b.value}, ${color.a.value})`; + element.style.backgroundColor = `rgba(${color.r.value}, ${color.g.value}, ${color.b.value}, ${color.a.value / 255})`; if (config.cornerRadius.topLeft.value > 0) { element.style.borderTopLeftRadius = config.cornerRadius.topLeft.value + 'px'; } @@ -401,19 +404,19 @@ elementData.previousMemoryConfig = configMemory; if (config.left.width.value > 0) { let color = config.left.color; - element.style.borderLeft = `${config.left.width.value}px solid rgba(${color.r.value}, ${color.g.value}, ${color.b.value}, ${color.a.value})` + element.style.borderLeft = `${config.left.width.value}px solid rgba(${color.r.value}, ${color.g.value}, ${color.b.value}, ${color.a.value / 255})` } if (config.right.width.value > 0) { let color = config.right.color; - element.style.borderRight = `${config.right.width.value}px solid rgba(${color.r.value}, ${color.g.value}, ${color.b.value}, ${color.a.value})` + element.style.borderRight = `${config.right.width.value}px solid rgba(${color.r.value}, ${color.g.value}, ${color.b.value}, ${color.a.value / 255})` } if (config.top.width.value > 0) { let color = config.top.color; - element.style.borderTop = `${config.top.width.value}px solid rgba(${color.r.value}, ${color.g.value}, ${color.b.value}, ${color.a.value})` + element.style.borderTop = `${config.top.width.value}px solid rgba(${color.r.value}, ${color.g.value}, ${color.b.value}, ${color.a.value / 255})` } if (config.bottom.width.value > 0) { let color = config.bottom.color; - element.style.borderBottom = `${config.bottom.width.value}px solid rgba(${color.r.value}, ${color.g.value}, ${color.b.value}, ${color.a.value})` + element.style.borderBottom = `${config.bottom.width.value}px solid rgba(${color.r.value}, ${color.g.value}, ${color.b.value}, ${color.a.value / 255})` } if (config.cornerRadius.topLeft.value > 0) { element.style.borderTopLeftRadius = config.cornerRadius.topLeft.value + 'px'; @@ -452,7 +455,6 @@ } case (CLAY_RENDER_COMMAND_TYPE_SCISSOR_START): { scissorStack.push({ nextAllocation: { x: renderCommand.boundingBox.x.value, y: renderCommand.boundingBox.y.value }, element, nextElementIndex: 0 }); - element.style.overflow = 'hidden'; break; } case (CLAY_RENDER_COMMAND_TYPE_SCISSOR_END): { @@ -506,7 +508,7 @@ let config = readStructAtAddress(renderCommand.config.value, rectangleConfigDefinition); let color = config.color; ctx.beginPath(); - window.canvasContext.fillStyle = `rgba(${color.r.value}, ${color.g.value}, ${color.b.value}, ${color.a.value})`; + window.canvasContext.fillStyle = `rgba(${color.r.value}, ${color.g.value}, ${color.b.value}, ${color.a.value / 255})`; window.canvasContext.roundRect( boundingBox.x.value * scale, // x boundingBox.y.value * scale, // y @@ -517,7 +519,7 @@ ctx.closePath(); // Handle link clicks let linkContents = config.link.length.value > 0 ? textDecoder.decode(new Uint8Array(memoryDataView.buffer.slice(config.link.chars.value, config.link.chars.value + config.link.length.value))) : 0; - if (linkContents.length > 0 && (window.mouseDown || window.touchDown) && instance.exports.Clay_PointerOver(renderCommand.id.value)) { + if (linkContents.length > 0 && (window.mouseDownThisFrame || window.touchDown) && instance.exports.Clay_PointerOver(renderCommand.id.value)) { window.location.href = linkContents; } break; @@ -533,7 +535,7 @@ ctx.moveTo((boundingBox.x.value + halfLineWidth) * scale, (boundingBox.y.value + config.cornerRadius.topLeft.value + halfLineWidth) * scale); let color = config.top.color; ctx.lineWidth = lineWidth * scale; - ctx.strokeStyle = `rgba(${color.r.value}, ${color.g.value}, ${color.b.value}, ${color.a.value})`; + ctx.strokeStyle = `rgba(${color.r.value}, ${color.g.value}, ${color.b.value}, ${color.a.value / 255})`; ctx.arcTo((boundingBox.x.value + halfLineWidth) * scale, (boundingBox.y.value + halfLineWidth) * scale, (boundingBox.x.value + config.cornerRadius.topLeft.value + halfLineWidth) * scale, (boundingBox.y.value + halfLineWidth) * scale, config.cornerRadius.topLeft.value * scale); ctx.stroke(); } @@ -543,7 +545,7 @@ let halfLineWidth = lineWidth / 2; let color = config.top.color; ctx.lineWidth = lineWidth * scale; - ctx.strokeStyle = `rgba(${color.r.value}, ${color.g.value}, ${color.b.value}, ${color.a.value})`; + ctx.strokeStyle = `rgba(${color.r.value}, ${color.g.value}, ${color.b.value}, ${color.a.value / 255})`; ctx.moveTo((boundingBox.x.value + config.cornerRadius.topLeft.value + halfLineWidth) * scale, (boundingBox.y.value + halfLineWidth) * scale); ctx.lineTo((boundingBox.x.value + boundingBox.width.value - config.cornerRadius.topRight.value - halfLineWidth) * scale, (boundingBox.y.value + halfLineWidth) * scale); ctx.stroke(); @@ -555,7 +557,7 @@ ctx.moveTo((boundingBox.x.value + boundingBox.width.value - config.cornerRadius.topRight.value - halfLineWidth) * scale, (boundingBox.y.value + halfLineWidth) * scale); let color = config.top.color; ctx.lineWidth = lineWidth * scale; - ctx.strokeStyle = `rgba(${color.r.value}, ${color.g.value}, ${color.b.value}, ${color.a.value})`; + ctx.strokeStyle = `rgba(${color.r.value}, ${color.g.value}, ${color.b.value}, ${color.a.value / 255})`; ctx.arcTo((boundingBox.x.value + boundingBox.width.value - halfLineWidth) * scale, (boundingBox.y.value + halfLineWidth) * scale, (boundingBox.x.value + boundingBox.width.value - halfLineWidth) * scale, (boundingBox.y.value + config.cornerRadius.topRight.value + halfLineWidth) * scale, config.cornerRadius.topRight.value * scale); ctx.stroke(); } @@ -565,7 +567,7 @@ let lineWidth = config.right.width.value; let halfLineWidth = lineWidth / 2; ctx.lineWidth = lineWidth * scale; - ctx.strokeStyle = `rgba(${color.r.value}, ${color.g.value}, ${color.b.value}, ${color.a.value})`; + ctx.strokeStyle = `rgba(${color.r.value}, ${color.g.value}, ${color.b.value}, ${color.a.value / 255})`; ctx.moveTo((boundingBox.x.value + boundingBox.width.value - halfLineWidth) * scale, (boundingBox.y.value + config.cornerRadius.topRight.value + halfLineWidth) * scale); ctx.lineTo((boundingBox.x.value + boundingBox.width.value - halfLineWidth) * scale, (boundingBox.y.value + boundingBox.height.value - config.cornerRadius.topRight.value - halfLineWidth) * scale); ctx.stroke(); @@ -577,7 +579,7 @@ let halfLineWidth = lineWidth / 2; ctx.moveTo((boundingBox.x.value + boundingBox.width.value - halfLineWidth) * scale, (boundingBox.y.value + boundingBox.height.value - config.cornerRadius.bottomRight.value - halfLineWidth) * scale); ctx.lineWidth = lineWidth * scale; - ctx.strokeStyle = `rgba(${color.r.value}, ${color.g.value}, ${color.b.value}, ${color.a.value})`; + ctx.strokeStyle = `rgba(${color.r.value}, ${color.g.value}, ${color.b.value}, ${color.a.value / 255})`; ctx.arcTo((boundingBox.x.value + boundingBox.width.value - halfLineWidth) * scale, (boundingBox.y.value + boundingBox.height.value - halfLineWidth) * scale, (boundingBox.x.value + boundingBox.width.value - config.cornerRadius.bottomRight.value - halfLineWidth) * scale, (boundingBox.y.value + boundingBox.height.value - halfLineWidth) * scale, config.cornerRadius.bottomRight.value * scale); ctx.stroke(); } @@ -587,7 +589,7 @@ let lineWidth = config.bottom.width.value; let halfLineWidth = lineWidth / 2; ctx.lineWidth = lineWidth * scale; - ctx.strokeStyle = `rgba(${color.r.value}, ${color.g.value}, ${color.b.value}, ${color.a.value})`; + ctx.strokeStyle = `rgba(${color.r.value}, ${color.g.value}, ${color.b.value}, ${color.a.value / 255})`; ctx.moveTo((boundingBox.x.value + config.cornerRadius.bottomLeft.value + halfLineWidth) * scale, (boundingBox.y.value + boundingBox.height.value - halfLineWidth) * scale); ctx.lineTo((boundingBox.x.value + boundingBox.width.value - config.cornerRadius.bottomRight.value - halfLineWidth) * scale, (boundingBox.y.value + boundingBox.height.value - halfLineWidth) * scale); ctx.stroke(); @@ -599,7 +601,7 @@ let halfLineWidth = lineWidth / 2; ctx.moveTo((boundingBox.x.value + config.cornerRadius.bottomLeft.value + halfLineWidth) * scale, (boundingBox.y.value + boundingBox.height.value - halfLineWidth) * scale); ctx.lineWidth = lineWidth * scale; - ctx.strokeStyle = `rgba(${color.r.value}, ${color.g.value}, ${color.b.value}, ${color.a.value})`; + ctx.strokeStyle = `rgba(${color.r.value}, ${color.g.value}, ${color.b.value}, ${color.a.value / 255})`; ctx.arcTo((boundingBox.x.value + halfLineWidth) * scale, (boundingBox.y.value + boundingBox.height.value - halfLineWidth) * scale, (boundingBox.x.value + halfLineWidth) * scale, (boundingBox.y.value + boundingBox.height.value - config.cornerRadius.bottomLeft.value - halfLineWidth) * scale, config.cornerRadius.bottomLeft.value * scale); ctx.stroke(); } @@ -609,7 +611,7 @@ let lineWidth = config.left.width.value; let halfLineWidth = lineWidth / 2; ctx.lineWidth = lineWidth * scale; - ctx.strokeStyle = `rgba(${color.r.value}, ${color.g.value}, ${color.b.value}, ${color.a.value})`; + ctx.strokeStyle = `rgba(${color.r.value}, ${color.g.value}, ${color.b.value}, ${color.a.value / 255})`; ctx.moveTo((boundingBox.x.value + halfLineWidth) * scale, (boundingBox.y.value + boundingBox.height.value - config.cornerRadius.bottomLeft.value - halfLineWidth) * scale); ctx.lineTo((boundingBox.x.value + halfLineWidth) * scale, (boundingBox.y.value + config.cornerRadius.bottomRight.value + halfLineWidth) * scale); ctx.stroke(); @@ -625,7 +627,7 @@ ctx.font = `${fontSize}px ${fontsById[config.fontId.value]}`; let color = config.textColor; ctx.textBaseline = 'middle'; - ctx.fillStyle = `rgba(${color.r.value}, ${color.g.value}, ${color.b.value}, ${color.a.value})`; + ctx.fillStyle = `rgba(${color.r.value}, ${color.g.value}, ${color.b.value}, ${color.a.value / 255})`; ctx.fillText(textDecoder.decode(stringContents), boundingBox.x.value * scale, (boundingBox.y.value + boundingBox.height.value / 2 + 1) * scale); break; } @@ -685,7 +687,7 @@ } window.previousActiveRendererIndex = activeRendererIndex; requestAnimationFrame(renderLoop); - window.mouseDown = false; + window.mouseDownThisFrame = false; } init(); diff --git a/examples/clay-official-website/main.c b/examples/clay-official-website/main.c index fef2900..3cc15c4 100644 --- a/examples/clay-official-website/main.c +++ b/examples/clay-official-website/main.c @@ -274,6 +274,16 @@ void RendererPageMobile() { }); } +typedef struct +{ + Clay_Vector2 clickOrigin; + Clay_Vector2 positionOrigin; + bool mouseDown; +} ScrollbarData; + +ScrollbarData scrollbarData = (ScrollbarData) {}; +float animationLerpValue = -1.0f; + Clay_RenderCommandArray CreateLayout(float lerpValue) { bool mobileScreen = windowWidth < 750; Clay_BeginLayout((int)windowWidth, (int)windowHeight); @@ -322,11 +332,23 @@ Clay_RenderCommandArray CreateLayout(float lerpValue) { }); }); }); + + if (!mobileScreen) { + Clay_ScrollContainerData scrollData = Clay_GetScrollContainerData(CLAY_ID("OuterScrollContainer")); + Clay_Color scrollbarColor = (Clay_Color){225, 138, 50, 120}; + if (scrollbarData.mouseDown) { + scrollbarColor = (Clay_Color){225, 138, 50, 200}; + } else if (Clay_PointerOver(CLAY_ID("ScrollBar"))) { + scrollbarColor = (Clay_Color){225, 138, 50, 160}; + } + float scrollHeight = scrollData.scrollContainerDimensions.height - 12; + CLAY_FLOATING_CONTAINER(CLAY_ID("ScrollBar"), &CLAY_LAYOUT_DEFAULT, CLAY_FLOATING_CONFIG(.offset = { .x = -6, .y = -(scrollData.scrollPosition->y / scrollData.contentDimensions.height) * scrollHeight + 6}, .zIndex = 1, .parentId = CLAY_ID("OuterScrollContainer"), .attachment = {.element = CLAY_ATTACH_POINT_RIGHT_TOP, .parent = CLAY_ATTACH_POINT_RIGHT_TOP}), { + CLAY_RECTANGLE(CLAY_ID("ScrollBarButton"), CLAY_LAYOUT(.sizing = {CLAY_SIZING_FIXED(10), CLAY_SIZING_FIXED((scrollHeight / scrollData.contentDimensions.height) * scrollHeight)}), CLAY_RECTANGLE_CONFIG(.cornerRadius = CLAY_CORNER_RADIUS(5), .color = scrollbarColor), {}); + }); + } return Clay_EndLayout((int)windowWidth, (int)windowHeight); } -float animationLerpValue = -1.0f; - CLAY_WASM_EXPORT("UpdateDrawFrame") Clay_RenderCommandArray UpdateDrawFrame(float width, float height, float mouseWheelX, float mouseWheelY, float mousePositionX, float mousePositionY, bool isTouchDown, bool isMouseDown, float deltaTime) { windowWidth = width; windowHeight = height; @@ -347,6 +369,32 @@ CLAY_WASM_EXPORT("UpdateDrawFrame") Clay_RenderCommandArray UpdateDrawFrame(floa //---------------------------------------------------------------------------------- // Handle scroll containers Clay_SetPointerPosition((Clay_Vector2) {mousePositionX, mousePositionY}); + + if (!isMouseDown) { + scrollbarData.mouseDown = false; + } + + if (isMouseDown && !scrollbarData.mouseDown && Clay_PointerOver(CLAY_ID("ScrollBar"))) { + Clay_ScrollContainerData scrollContainerData = Clay_GetScrollContainerData(CLAY_ID("OuterScrollContainer")); + scrollbarData.clickOrigin = (Clay_Vector2) { mousePositionX, mousePositionY }; + scrollbarData.positionOrigin = *scrollContainerData.scrollPosition; + scrollbarData.mouseDown = true; + } else if (scrollbarData.mouseDown) { + Clay_ScrollContainerData scrollContainerData = Clay_GetScrollContainerData(CLAY_ID("OuterScrollContainer")); + if (scrollContainerData.contentDimensions.height > 0) { + Clay_Vector2 ratio = (Clay_Vector2) { + scrollContainerData.contentDimensions.width / scrollContainerData.scrollContainerDimensions.width, + scrollContainerData.contentDimensions.height / scrollContainerData.scrollContainerDimensions.height, + }; + if (scrollContainerData.config.vertical) { + scrollContainerData.scrollPosition->y = scrollbarData.positionOrigin.y + (scrollbarData.clickOrigin.y - mousePositionY) * ratio.y; + } + if (scrollContainerData.config.horizontal) { + scrollContainerData.scrollPosition->x = scrollbarData.positionOrigin.x + (scrollbarData.clickOrigin.x - mousePositionX) * ratio.x; + } + } + } + Clay_UpdateScrollContainers(isTouchDown, (Clay_Vector2) {mouseWheelX, mouseWheelY}, deltaTime); return CreateLayout(animationLerpValue < 0 ? (animationLerpValue + 1) : (1 - animationLerpValue)); //---------------------------------------------------------------------------------- diff --git a/renderers/raylib/clay_renderer_raylib.c b/renderers/raylib/clay_renderer_raylib.c index 8681660..e4851f4 100644 --- a/renderers/raylib/clay_renderer_raylib.c +++ b/renderers/raylib/clay_renderer_raylib.c @@ -166,7 +166,13 @@ void Clay_Raylib_Render(Clay_RenderCommandArray renderCommands) break; } case CLAY_RENDER_COMMAND_TYPE_RECTANGLE: { - DrawRectangle((int)roundf(boundingBox.x), (int)roundf(boundingBox.y), (int)roundf(boundingBox.width), (int)roundf(boundingBox.height), CLAY_COLOR_TO_RAYLIB_COLOR(renderCommand->config.rectangleElementConfig->color)); + Clay_RectangleElementConfig *config = renderCommand->config.rectangleElementConfig; + if (config->cornerRadius.topLeft > 0) { + float radius = (config->cornerRadius.topLeft * 2) / (boundingBox.width > boundingBox.height) ? boundingBox.height : boundingBox.width; + DrawRectangleRounded((Rectangle) { boundingBox.x, boundingBox.y, boundingBox.width, boundingBox.height }, radius, 8, CLAY_COLOR_TO_RAYLIB_COLOR(config->color)); + } else { + DrawRectangle(boundingBox.x, boundingBox.y, boundingBox.width, boundingBox.height, CLAY_COLOR_TO_RAYLIB_COLOR(config->color)); + } break; } case CLAY_RENDER_COMMAND_TYPE_BORDER: { diff --git a/renderers/web/html/clay-html-renderer.html b/renderers/web/html/clay-html-renderer.html index 7d23dd8..ab7bdf6 100644 --- a/renderers/web/html/clay-html-renderer.html +++ b/renderers/web/html/clay-html-renderer.html @@ -338,6 +338,9 @@ } element = document.createElement(elementType); element.id = renderCommand.id.value; + if (renderCommand.commandType.value === CLAY_RENDER_COMMAND_TYPE_SCISSOR_START) { + element.style.overflow = 'hidden'; + } elementCache[renderCommand.id.value] = { exists: true, element: element, @@ -347,7 +350,6 @@ }; } - let dirty = false; let elementData = elementCache[renderCommand.id.value]; element = elementData.element; if (Array.prototype.indexOf.call(parentElement.element.children, element) !== parentElement.nextElementIndex) { @@ -360,12 +362,8 @@ elementData.exists = true; // Don't get me started. Cheaper to compare the render command memory than to update HTML elements - if (renderCommand.commandType.value !== CLAY_RENDER_COMMAND_TYPE_SCISSOR_START && renderCommand.commandType.value !== CLAY_RENDER_COMMAND_TYPE_SCISSOR_END) { - dirty = MemoryIsDifferent(elementData.previousMemoryCommand, entireRenderCommandMemory, renderCommandSize); - parentElement.nextElementIndex++; - } else { - dirty = true; - } + let dirty = MemoryIsDifferent(elementData.previousMemoryCommand, entireRenderCommandMemory, renderCommandSize); + parentElement.nextElementIndex++; elementData.previousMemoryCommand = entireRenderCommandMemory; let offsetX = scissorStack.length > 0 ? scissorStack[scissorStack.length - 1].nextAllocation.x : 0; @@ -376,7 +374,7 @@ element.style.height = Math.round(renderCommand.boundingBox.height.value) + 'px'; } - switch (renderCommand.commandType.value) { + switch(renderCommand.commandType.value) { case (CLAY_RENDER_COMMAND_TYPE_NONE): { break; } @@ -384,7 +382,7 @@ let config = readStructAtAddress(renderCommand.config.value, rectangleConfigDefinition); let configMemory = new Uint8Array(memoryDataView.buffer.slice(renderCommand.config.value, renderCommand.config.value + config.__size)); let linkContents = config.link.length.value > 0 ? textDecoder.decode(new Uint8Array(memoryDataView.buffer.slice(config.link.chars.value, config.link.chars.value + config.link.length.value))) : 0; - if (linkContents.length > 0 && (window.mouseDown || window.touchDown) && instance.exports.Clay_PointerOver(renderCommand.id.value)) { + if (linkContents.length > 0 && (window.mouseDownThisFrame || window.touchDown) && instance.exports.Clay_PointerOver(renderCommand.id.value)) { window.location.href = linkContents; } if (!dirty && !MemoryIsDifferent(configMemory, elementData.previousMemoryConfig, config.__size)) { @@ -400,7 +398,7 @@ } elementData.previousMemoryConfig = configMemory; let color = config.color; - element.style.backgroundColor = `rgba(${color.r.value}, ${color.g.value}, ${color.b.value}, ${color.a.value})`; + element.style.backgroundColor = `rgba(${color.r.value}, ${color.g.value}, ${color.b.value}, ${color.a.value / 255})`; if (config.cornerRadius.topLeft.value > 0) { element.style.borderTopLeftRadius = config.cornerRadius.topLeft.value + 'px'; } @@ -424,19 +422,19 @@ elementData.previousMemoryConfig = configMemory; if (config.left.width.value > 0) { let color = config.left.color; - element.style.borderLeft = `${config.left.width.value}px solid rgba(${color.r.value}, ${color.g.value}, ${color.b.value}, ${color.a.value})` + element.style.borderLeft = `${config.left.width.value}px solid rgba(${color.r.value}, ${color.g.value}, ${color.b.value}, ${color.a.value / 255})` } if (config.right.width.value > 0) { let color = config.right.color; - element.style.borderRight = `${config.right.width.value}px solid rgba(${color.r.value}, ${color.g.value}, ${color.b.value}, ${color.a.value})` + element.style.borderRight = `${config.right.width.value}px solid rgba(${color.r.value}, ${color.g.value}, ${color.b.value}, ${color.a.value / 255})` } if (config.top.width.value > 0) { let color = config.top.color; - element.style.borderTop = `${config.top.width.value}px solid rgba(${color.r.value}, ${color.g.value}, ${color.b.value}, ${color.a.value})` + element.style.borderTop = `${config.top.width.value}px solid rgba(${color.r.value}, ${color.g.value}, ${color.b.value}, ${color.a.value / 255})` } if (config.bottom.width.value > 0) { let color = config.bottom.color; - element.style.borderBottom = `${config.bottom.width.value}px solid rgba(${color.r.value}, ${color.g.value}, ${color.b.value}, ${color.a.value})` + element.style.borderBottom = `${config.bottom.width.value}px solid rgba(${color.r.value}, ${color.g.value}, ${color.b.value}, ${color.a.value / 255})` } if (config.cornerRadius.topLeft.value > 0) { element.style.borderTopLeftRadius = config.cornerRadius.topLeft.value + 'px'; @@ -475,7 +473,6 @@ } case (CLAY_RENDER_COMMAND_TYPE_SCISSOR_START): { scissorStack.push({ nextAllocation: { x: renderCommand.boundingBox.x.value, y: renderCommand.boundingBox.y.value }, element, nextElementIndex: 0 }); - element.style.overflow = 'hidden'; break; } case (CLAY_RENDER_COMMAND_TYPE_SCISSOR_END): {