Compare commits

..

1 Commits

Author SHA1 Message Date
Harrison Lambeth
0ea0643a36
Merge b97bf246c8 into dcd6feda86 2025-02-08 16:24:11 +08:00
11 changed files with 319 additions and 432 deletions

View File

@ -1 +0,0 @@
https://github.com/Orcolom/clay-cs

Binary file not shown.

Binary file not shown.

Binary file not shown.

53
clay.h
View File

@ -21,11 +21,6 @@
#include <arm_neon.h>
#endif
#ifdef __JETBRAINS_IDE__
// Help jetbrains IDEs like CLion and Rider with intellisense & debugging
#define CLAY_IMPLEMENTATION
#endif
// -----------------------------------------
// HEADER DECLARATIONS ---------------------
// -----------------------------------------
@ -429,11 +424,6 @@ typedef struct {
void* customData;
} Clay_CustomRenderData;
typedef struct {
bool horizontal;
bool vertical;
} Clay_ScrollRenderData;
typedef struct {
Clay_Color color;
Clay_CornerRadius cornerRadius;
@ -446,7 +436,6 @@ typedef union {
Clay_ImageRenderData image;
Clay_CustomRenderData custom;
Clay_BorderRenderData border;
Clay_ScrollRenderData scroll;
} Clay_RenderData;
// Miscellaneous Structs & Enums ---------------------------------
@ -1288,14 +1277,13 @@ Clay_LayoutElementHashMapItem *Clay__GetHashMapItem(uint32_t id) {
return &Clay_LayoutElementHashMapItem_DEFAULT;
}
Clay_ElementId Clay__GenerateIdForAnonymousElement(Clay_LayoutElement *openLayoutElement) {
void Clay__GenerateIdForAnonymousElement(Clay_LayoutElement *openLayoutElement) {
Clay_Context* context = Clay_GetCurrentContext();
Clay_LayoutElement *parentElement = Clay_LayoutElementArray_Get(&context->layoutElements, Clay__int32_tArray_GetValue(&context->openLayoutElementStack, context->openLayoutElementStack.length - 2));
Clay_ElementId elementId = Clay__HashNumber(parentElement->childrenOrTextContent.children.length, parentElement->id);
openLayoutElement->id = elementId.id;
Clay__AddHashMapItem(elementId, openLayoutElement, 0);
Clay__StringArray_Add(&context->layoutElementIdStrings, elementId.stringId);
return elementId;
}
bool Clay__ElementHasConfig(Clay_LayoutElement *layoutElement, Clay__ElementConfigType type) {
@ -1530,8 +1518,11 @@ void Clay__ConfigureOpenElement(const Clay_ElementDeclaration declaration) {
.errorText = CLAY_STRING("An element was configured with CLAY_SIZING_PERCENT, but the provided percentage value was over 1.0. Clay expects a value between 0 and 1, i.e. 20% is 0.2."),
.userData = context->errorHandler.userData });
}
Clay_ElementId openLayoutElementId = declaration.id;
if (declaration.id.id != 0) {
Clay__AttachId(declaration.id);
} else if (openLayoutElement->id == 0) {
Clay__GenerateIdForAnonymousElement(openLayoutElement);
}
openLayoutElement->elementConfigs.internalArray = &context->elementConfigs.internalArray[context->elementConfigs.length];
Clay_SharedElementConfig *sharedConfig = NULL;
@ -1584,9 +1575,6 @@ void Clay__ConfigureOpenElement(const Clay_ElementDeclaration declaration) {
} else if (declaration.floating.attachTo == CLAY_ATTACH_TO_ROOT) {
floatingConfig.parentId = Clay__HashString(CLAY_STRING("Clay__RootContainer"), 0, 0).id;
}
if (!openLayoutElementId.id) {
openLayoutElementId = Clay__HashString(CLAY_STRING("Clay__FloatingContainer"), context->layoutElementTreeRoots.length, 0);
}
Clay__LayoutElementTreeRootArray_Add(&context->layoutElementTreeRoots, CLAY__INIT(Clay__LayoutElementTreeRoot) {
.layoutElementIndex = Clay__int32_tArray_GetValue(&context->openLayoutElementStack, context->openLayoutElementStack.length - 1),
.parentId = floatingConfig.parentId,
@ -1599,13 +1587,6 @@ void Clay__ConfigureOpenElement(const Clay_ElementDeclaration declaration) {
if (declaration.custom.customData) {
Clay__AttachElementConfig(CLAY__INIT(Clay_ElementConfigUnion) { .customElementConfig = Clay__StoreCustomElementConfig(declaration.custom) }, CLAY__ELEMENT_CONFIG_TYPE_CUSTOM);
}
if (openLayoutElementId.id != 0) {
Clay__AttachId(openLayoutElementId);
} else if (openLayoutElement->id == 0) {
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);
Clay__int32_tArray_Add(&context->openClipElementStack, (int)openLayoutElement->id);
@ -2278,12 +2259,6 @@ void Clay__CalculateFinalLayout(void) {
}
case CLAY__ELEMENT_CONFIG_TYPE_SCROLL: {
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,
}
};
break;
}
case CLAY__ELEMENT_CONFIG_TYPE_IMAGE: {
@ -3130,11 +3105,11 @@ void Clay__RenderDebugView(void) {
CLAY({{0}}) {
CLAY_TEXT(CLAY_STRING("{ left: "), infoTextConfig);
CLAY_TEXT(Clay__IntToString(borderConfig->width.left), infoTextConfig);
CLAY_TEXT(CLAY_STRING(", right: "), infoTextConfig);
CLAY_TEXT(CLAY_STRING("{ right: "), infoTextConfig);
CLAY_TEXT(Clay__IntToString(borderConfig->width.right), infoTextConfig);
CLAY_TEXT(CLAY_STRING(", top: "), infoTextConfig);
CLAY_TEXT(CLAY_STRING("{ top: "), infoTextConfig);
CLAY_TEXT(Clay__IntToString(borderConfig->width.top), infoTextConfig);
CLAY_TEXT(CLAY_STRING(", bottom: "), infoTextConfig);
CLAY_TEXT(CLAY_STRING("{ bottom: "), infoTextConfig);
CLAY_TEXT(Clay__IntToString(borderConfig->width.bottom), infoTextConfig);
CLAY_TEXT(CLAY_STRING(" }"), infoTextConfig);
}
@ -3597,19 +3572,13 @@ CLAY_WASM_EXPORT("Clay_EndLayout")
Clay_RenderCommandArray Clay_EndLayout(void) {
Clay_Context* context = Clay_GetCurrentContext();
Clay__CloseElement();
bool elementsExceededBeforeDebugView = context->booleanWarnings.maxElementsExceeded;
if (context->debugModeEnabled && !elementsExceededBeforeDebugView) {
if (context->debugModeEnabled) {
context->warningsEnabled = false;
Clay__RenderDebugView();
context->warningsEnabled = true;
}
if (context->booleanWarnings.maxElementsExceeded) {
Clay_String message;
if (!elementsExceededBeforeDebugView) {
message = CLAY_STRING("Clay Error: Layout elements exceeded Clay__maxElementCount after adding the debug-view to the layout.");
} else {
message = CLAY_STRING("Clay Error: Layout elements exceeded Clay__maxElementCount");
}
Clay_String message = CLAY_STRING("Clay Error: Layout elements exceeded Clay__maxElementCount");
Clay__AddRenderCommand(CLAY__INIT(Clay_RenderCommand ) {
.boundingBox = { context->layoutDimensions.width / 2 - 59 * 4, context->layoutDimensions.height / 2, 0, 0 },
.renderData = { .text = { .stringContents = CLAY__INIT(Clay_StringSlice) { .length = message.length, .chars = message.chars, .baseChars = message.chars }, .textColor = {255, 0, 0, 255}, .fontSize = 16 } },

View File

@ -86,10 +86,6 @@
];
let elementCache = {};
let imageCache = {};
let dimensionsDefinition = { type: 'struct', members: [
{name: 'width', type: 'float'},
{name: 'height', type: 'float'},
]};
let colorDefinition = { type: 'struct', members: [
{name: 'r', type: 'float' },
{name: 'g', type: 'float' },
@ -105,12 +101,9 @@
{name: 'chars', type: 'uint32_t' },
{name: 'baseChars', type: 'uint32_t' },
]};
let borderWidthDefinition = { type: 'struct', members: [
{name: 'left', type: 'uint16_t'},
{name: 'right', type: 'uint16_t'},
{name: 'top', type: 'uint16_t'},
{name: 'bottom', type: 'uint16_t'},
{name: 'betweenChildren', type: 'uint16_t'},
let borderDefinition = { type: 'struct', members: [
{name: 'width', type: 'uint32_t'},
{name: 'color', ...colorDefinition},
]};
let cornerRadiusDefinition = { type: 'struct', members: [
{name: 'topLeft', type: 'float'},
@ -118,53 +111,44 @@
{name: 'bottomLeft', type: 'float'},
{name: 'bottomRight', type: 'float'},
]};
let rectangleConfigDefinition = { name: 'rectangle', type: 'struct', members: [
{ name: 'color', ...colorDefinition },
{ name: 'link', ...stringDefinition },
{ name: 'cursorPointer', type: 'uint8_t' },
]};
let borderConfigDefinition = { name: 'text', type: 'struct', members: [
{ name: 'left', ...borderDefinition },
{ name: 'right', ...borderDefinition },
{ name: 'top', ...borderDefinition },
{ name: 'bottom', ...borderDefinition },
{ name: 'betweenChildren', ...borderDefinition },
]};
let textConfigDefinition = { name: 'text', type: 'struct', members: [
{ name: 'textColor', ...colorDefinition },
{ name: 'fontId', type: 'uint16_t' },
{ name: 'fontSize', type: 'uint16_t' },
{ name: 'letterSpacing', type: 'uint16_t' },
{ name: 'lineSpacing', type: 'uint16_t' },
{ name: 'wrapMode', type: 'uint8_t' },
{ name: 'disablePointerEvents', type: 'uint8_t' },
{ name: '_padding', type: 'uint16_t' },
{ name: 'wrapMode', type: 'uint32_t' },
{ name: 'disablePointerEvents', type: 'uint8_t' }
]};
let textRenderDataDefinition = { type: 'struct', members: [
{ name: 'stringContents', ...stringSliceDefinition },
{ name: 'textColor', ...colorDefinition },
{ name: 'fontId', type: 'uint16_t' },
{ name: 'fontSize', type: 'uint16_t' },
{ name: 'letterSpacing', type: 'uint16_t' },
{ name: 'lineHeight', type: 'uint16_t' },
]};
let rectangleRenderDataDefinition = { type: 'struct', members: [
{ name: 'backgroundColor', ...colorDefinition },
{ name: 'cornerRadius', ...cornerRadiusDefinition },
]};
let imageRenderDataDefinition = { type: 'struct', members: [
{ name: 'backgroundColor', ...colorDefinition },
{ name: 'cornerRadius', ...cornerRadiusDefinition },
{ name: 'sourceDimensions', ...dimensionsDefinition },
{ name: 'imageData', type: 'uint32_t' },
]};
let customRenderDataDefinition = { type: 'struct', members: [
{ name: 'backgroundColor', ...colorDefinition },
{ name: 'cornerRadius', ...cornerRadiusDefinition },
{ name: 'customData', type: 'uint32_t' },
]};
let borderRenderDataDefinition = { type: 'struct', members: [
{ name: 'color', ...colorDefinition },
{ name: 'cornerRadius', ...cornerRadiusDefinition },
{ name: 'width', ...borderWidthDefinition },
{ name: 'padding', type: 'uint16_t'}
]};
let scrollRenderDataDefinition = { type: 'struct', members: [
let scrollConfigDefinition = { name: 'text', type: 'struct', members: [
{ name: 'horizontal', type: 'bool' },
{ name: 'vertical', type: 'bool' },
]};
let customHTMLDataDefinition = { type: 'struct', members: [
{ name: 'link', ...stringDefinition },
{ name: 'cursorPointer', type: 'uint8_t' },
{ name: 'disablePointerEvents', type: 'uint8_t' },
let imageConfigDefinition = { name: 'image', type: 'struct', members: [
{ name: 'imageData', type: 'uint32_t' },
{ name: 'sourceDimensions', type: 'struct', members: [
{ name: 'width', type: 'float' },
{ name: 'height', type: 'float' },
]},
{ name: 'sourceURL', ...stringDefinition }
]};
let customConfigDefinition = { name: 'custom', type: 'struct', members: [
{ name: 'customData', type: 'uint32_t' },
]}
let sharedConfigDefinition = { name: 'shared', type: 'struct', members: [
{ name: 'cornerRadius', ...cornerRadiusDefinition },
]};
let renderCommandDefinition = {
name: 'CLay_RenderCommand',
@ -176,19 +160,14 @@
{ name: 'width', type: 'float' },
{ name: 'height', type: 'float' },
]},
{ name: 'renderData', type: 'union', members: [
{ name: 'rectangle', ...rectangleRenderDataDefinition },
{ name: 'text', ...textRenderDataDefinition },
{ name: 'image', ...imageRenderDataDefinition },
{ name: 'custom', ...customRenderDataDefinition },
{ name: 'border', ...borderRenderDataDefinition },
{ name: 'scroll', ...scrollRenderDataDefinition },
{ name: 'config', type: 'uint32_t'},
{ name: 'textOrSharedConfig', type: 'union', members: [
{ name: 'text', ...stringSliceDefinition },
{ name: 'sharedConfig', type: 'uint32_t' }
]},
{ name: 'userData', type: 'uint32_t'},
{ name: 'zIndex', type: 'int32_t' },
{ name: 'id', type: 'uint32_t' },
{ name: 'zIndex', type: 'int16_t' },
{ name: 'commandType', type: 'uint8_t' },
{ name: '_padding', type: 'uint8_t' },
{ name: 'commandType', type: 'uint32_t', },
]
};
@ -211,7 +190,6 @@
case 'uint32_t': return 4;
case 'int32_t': return 4;
case 'uint16_t': return 2;
case 'int16_t': return 2;
case 'uint8_t': return 1;
case 'bool': return 1;
default: {
@ -241,7 +219,6 @@
case 'uint32_t': return { value: memoryDataView.getUint32(address, true), __size: 4 };
case 'int32_t': return { value: memoryDataView.getUint32(address, true), __size: 4 };
case 'uint16_t': return { value: memoryDataView.getUint16(address, true), __size: 2 };
case 'int16_t': return { value: memoryDataView.getInt16(address, true), __size: 2 };
case 'uint8_t': return { value: memoryDataView.getUint8(address, true), __size: 1 };
case 'bool': return { value: memoryDataView.getUint8(address, true), __size: 1 };
default: {
@ -363,7 +340,7 @@
memoryDataView.setFloat32(addressOfOffset, -container.scrollLeft, true);
memoryDataView.setFloat32(addressOfOffset + 4, -container.scrollTop, true);
}
},
}
},
};
const { instance } = await WebAssembly.instantiateStreaming(
@ -371,15 +348,13 @@
);
memoryDataView = new DataView(new Uint8Array(instance.exports.memory.buffer).buffer);
scratchSpaceAddress = instance.exports.__heap_base.value;
let clayScratchSpaceAddress = instance.exports.__heap_base.value + 1024;
heapSpaceAddress = instance.exports.__heap_base.value + 2048;
heapSpaceAddress = instance.exports.__heap_base.value + 1024;
let arenaAddress = scratchSpaceAddress + 8;
window.instance = instance;
createMainArena(arenaAddress, heapSpaceAddress);
memoryDataView.setFloat32(instance.exports.__heap_base.value, window.innerWidth, true);
memoryDataView.setFloat32(instance.exports.__heap_base.value + 4, window.innerHeight, true);
instance.exports.Clay_Initialize(arenaAddress, instance.exports.__heap_base.value);
instance.exports.SetScratchMemory(arenaAddress, clayScratchSpaceAddress);
renderCommandSize = getStructTotalSize(renderCommandDefinition);
renderLoop();
}
@ -393,22 +368,6 @@
return false;
}
function SetElementBackgroundColorAndRadius(element, cornerRadius, backgroundColor) {
element.style.backgroundColor = `rgba(${backgroundColor.r.value}, ${backgroundColor.g.value}, ${backgroundColor.b.value}, ${backgroundColor.a.value / 255})`;
if (cornerRadius.topLeft.value > 0) {
element.style.borderTopLeftRadius = cornerRadius.topLeft.value + 'px';
}
if (cornerRadius.topRight.value > 0) {
element.style.borderTopRightRadius = cornerRadius.topRight.value + 'px';
}
if (cornerRadius.bottomLeft.value > 0) {
element.style.borderBottomLeftRadius = cornerRadius.bottomLeft.value + 'px';
}
if (cornerRadius.bottomRight.value > 0) {
element.style.borderBottomRightRadius = cornerRadius.bottomRight.value + 'px';
}
}
function renderLoopHTML() {
let capacity = memoryDataView.getInt32(scratchSpaceAddress, true);
let length = memoryDataView.getInt32(scratchSpaceAddress + 4, true);
@ -416,7 +375,7 @@
let scissorStack = [{ nextAllocation: { x: 0, y: 0 }, element: htmlRoot, nextElementIndex: 0 }];
let previousId = 0;
for (let i = 0; i < length; i++, arrayOffset += renderCommandSize) {
let entireRenderCommandMemory = new Uint8Array(memoryDataView.buffer.slice(arrayOffset, arrayOffset + renderCommandSize));
let entireRenderCommandMemory = new Uint32Array(memoryDataView.buffer.slice(arrayOffset, arrayOffset + renderCommandSize));
let renderCommand = readStructAtAddress(arrayOffset, renderCommandDefinition);
let parentElement = scissorStack[scissorStack.length - 1];
let element = null;
@ -425,12 +384,13 @@
let elementType = 'div';
switch (renderCommand.commandType.value & 0xff) {
case CLAY_RENDER_COMMAND_TYPE_RECTANGLE: {
// if (readStructAtAddress(renderCommand.renderData.rectangle.value, rectangleRenderDataDefinition).link.length.value > 0) { TODO reimplement links
// elementType = 'a';
// }
if (readStructAtAddress(renderCommand.config.value, rectangleConfigDefinition).link.length.value > 0) {
elementType = 'a';
}
break;
}
case CLAY_RENDER_COMMAND_TYPE_IMAGE: {
console.log('test5');
elementType = 'img'; break;
}
default: break;
@ -483,82 +443,93 @@
break;
}
case (CLAY_RENDER_COMMAND_TYPE_RECTANGLE): {
let config = renderCommand.renderData.rectangle;
let configMemory = JSON.stringify(config);
if (configMemory === elementData.previousMemoryConfig) {
break;
}
SetElementBackgroundColorAndRadius(element, config.cornerRadius, config.backgroundColor);
if (renderCommand.userData.value !== 0) {
let customData = readStructAtAddress(renderCommand.userData.value, customHTMLDataDefinition);
let linkContents = customData.link.length.value > 0 ? textDecoder.decode(new Uint8Array(memoryDataView.buffer.slice(customData.link.chars.value, customData.link.chars.value + customData.link.length.value))) : 0;
let config = readStructAtAddress(renderCommand.config.value, rectangleConfigDefinition);
let sharedConfig = readStructAtAddress( renderCommand.textOrSharedConfig.sharedConfig.value, sharedConfigDefinition);
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;
memoryDataView.setUint32(0, renderCommand.id.value, true);
if (linkContents.length > 0 && (window.mouseDownThisFrame || window.touchDown) && instance.exports.Clay_PointerOver(0)) {
window.location.href = linkContents;
}
if (!dirty && !MemoryIsDifferent(configMemory, elementData.previousMemoryConfig, config.__size)) {
break;
}
if (linkContents.length > 0) {
element.href = linkContents;
}
if (linkContents.length > 0 || customData.cursorPointer.value) {
if (linkContents.length > 0 || config.cursorPointer.value) {
element.style.pointerEvents = 'all';
element.style.cursor = 'pointer';
}
}
elementData.previousMemoryConfig = configMemory;
let color = config.color;
element.style.backgroundColor = `rgba(${color.r.value}, ${color.g.value}, ${color.b.value}, ${color.a.value / 255})`;
if (sharedConfig.cornerRadius.topLeft.value > 0) {
element.style.borderTopLeftRadius = sharedConfig.cornerRadius.topLeft.value + 'px';
}
if (sharedConfig.cornerRadius.topRight.value > 0) {
element.style.borderTopRightRadius = sharedConfig.cornerRadius.topRight.value + 'px';
}
if (sharedConfig.cornerRadius.bottomLeft.value > 0) {
element.style.borderBottomLeftRadius = sharedConfig.cornerRadius.bottomLeft.value + 'px';
}
if (sharedConfig.cornerRadius.bottomRight.value > 0) {
element.style.borderBottomRightRadius = sharedConfig.cornerRadius.bottomRight.value + 'px';
}
break;
}
case (CLAY_RENDER_COMMAND_TYPE_BORDER): {
let config = renderCommand.renderData.border;
let configMemory = JSON.stringify(config);
if (configMemory === elementData.previousMemoryConfig) {
let config = readStructAtAddress(renderCommand.config.value, borderConfigDefinition);
let sharedConfig = readStructAtAddress( renderCommand.textOrSharedConfig.sharedConfig.value, sharedConfigDefinition);
let configMemory = new Uint8Array(memoryDataView.buffer.slice(renderCommand.config.value, renderCommand.config.value + config.__size));
if (!dirty && !MemoryIsDifferent(configMemory, elementData.previousMemoryConfig, config.__size)) {
break;
}
let color = config.color;
elementData.previousMemoryConfig = configMemory;
if (config.width.left.value > 0) {
element.style.borderLeft = `${config.width.left.value}px solid rgba(${color.r.value}, ${color.g.value}, ${color.b.value}, ${color.a.value / 255})`
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 / 255})`
}
if (config.width.right.value > 0) {
element.style.borderRight = `${config.width.right.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 / 255})`
}
if (config.width.top.value > 0) {
element.style.borderTop = `${config.width.top.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 / 255})`
}
if (config.width.bottom.value > 0) {
element.style.borderBottom = `${config.width.bottom.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 / 255})`
}
if (config.cornerRadius.topLeft.value > 0) {
element.style.borderTopLeftRadius = config.cornerRadius.topLeft.value + 'px';
if (sharedConfig.cornerRadius.topLeft.value > 0) {
element.style.borderTopLeftRadius = sharedConfig.cornerRadius.topLeft.value + 'px';
}
if (config.cornerRadius.topRight.value > 0) {
element.style.borderTopRightRadius = config.cornerRadius.topRight.value + 'px';
if (sharedConfig.cornerRadius.topRight.value > 0) {
element.style.borderTopRightRadius = sharedConfig.cornerRadius.topRight.value + 'px';
}
if (config.cornerRadius.bottomLeft.value > 0) {
element.style.borderBottomLeftRadius = config.cornerRadius.bottomLeft.value + 'px';
if (sharedConfig.cornerRadius.bottomLeft.value > 0) {
element.style.borderBottomLeftRadius = sharedConfig.cornerRadius.bottomLeft.value + 'px';
}
if (config.cornerRadius.bottomRight.value > 0) {
element.style.borderBottomRightRadius = config.cornerRadius.bottomRight.value + 'px';
if (sharedConfig.cornerRadius.bottomRight.value > 0) {
element.style.borderBottomRightRadius = sharedConfig.cornerRadius.bottomRight.value + 'px';
}
break;
}
case (CLAY_RENDER_COMMAND_TYPE_TEXT): {
let config = renderCommand.renderData.text;
let customData = readStructAtAddress(renderCommand.userData.value, customHTMLDataDefinition);
let configMemory = JSON.stringify(config);
let stringContents = new Uint8Array(memoryDataView.buffer.slice(config.stringContents.chars.value, config.stringContents.chars.value + config.stringContents.length.value));
if (configMemory !== elementData.previousMemoryConfig) {
let config = readStructAtAddress(renderCommand.config.value, textConfigDefinition);
let configMemory = new Uint8Array(memoryDataView.buffer.slice(renderCommand.config.value, renderCommand.config.value + config.__size));
let textContents = renderCommand.textOrSharedConfig.text;
let stringContents = new Uint8Array(memoryDataView.buffer.slice(textContents.chars.value, textContents.chars.value + textContents.length.value));
if (MemoryIsDifferent(configMemory, elementData.previousMemoryConfig, config.__size)) {
element.className = 'text';
let textColor = config.textColor;
let fontSize = Math.round(config.fontSize.value * GLOBAL_FONT_SCALING_FACTOR);
element.style.color = `rgba(${textColor.r.value}, ${textColor.g.value}, ${textColor.b.value}, ${textColor.a.value})`;
element.style.fontFamily = fontsById[config.fontId.value];
element.style.fontSize = fontSize + 'px';
element.style.pointerEvents = customData.disablePointerEvents.value ? 'none' : 'all';
element.style.pointerEvents = config.disablePointerEvents.value ? 'none' : 'all';
elementData.previousMemoryConfig = configMemory;
}
if (stringContents.length !== elementData.previousMemoryText.length || MemoryIsDifferent(stringContents, elementData.previousMemoryText, stringContents.length)) {
@ -569,11 +540,7 @@
}
case (CLAY_RENDER_COMMAND_TYPE_SCISSOR_START): {
scissorStack.push({ nextAllocation: { x: renderCommand.boundingBox.x.value, y: renderCommand.boundingBox.y.value }, element, nextElementIndex: 0 });
let config = renderCommand.renderData.scroll;
let configMemory = JSON.stringify(config);
if (configMemory === elementData.previousMemoryConfig) {
break;
}
let config = readStructAtAddress(renderCommand.config.value, scrollConfigDefinition);
if (config.horizontal.value) {
element.style.overflowX = 'scroll';
element.style.pointerEvents = 'auto';
@ -582,7 +549,6 @@
element.style.overflowY = 'scroll';
element.style.pointerEvents = 'auto';
}
elementData.previousMemoryConfig = configMemory;
break;
}
case (CLAY_RENDER_COMMAND_TYPE_SCISSOR_END): {
@ -590,9 +556,9 @@
break;
}
case (CLAY_RENDER_COMMAND_TYPE_IMAGE): {
let config = renderCommand.renderData.image;
let imageURL = readStructAtAddress(config.imageData.value, stringDefinition);
let srcContents = new Uint8Array(memoryDataView.buffer.slice(imageURL.chars.value, imageURL.chars.value + imageURL.length.value));
console.log('test1');
let config = readStructAtAddress(renderCommand.config.value, imageConfigDefinition);
let srcContents = new Uint8Array(memoryDataView.buffer.slice(config.sourceURL.chars.value, config.sourceURL.chars.value + config.sourceURL.length.value));
if (srcContents.length !== elementData.previousMemoryText.length || MemoryIsDifferent(srcContents, elementData.previousMemoryText, srcContents.length)) {
element.src = textDecoder.decode(srcContents);
}
@ -600,9 +566,6 @@
break;
}
case (CLAY_RENDER_COMMAND_TYPE_CUSTOM): break;
default: {
console.log("Error: unhandled render command");
}
}
}
@ -639,8 +602,8 @@
break;
}
case (CLAY_RENDER_COMMAND_TYPE_RECTANGLE): {
let config = renderCommand.renderData.rectangle;
let color = config.backgroundColor;
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 / 255})`;
window.canvasContext.roundRect(
@ -652,35 +615,33 @@
ctx.fill();
ctx.closePath();
// Handle link clicks
if (renderCommand.userData.value !== 0) {
let customData = readStructAtAddress(renderCommand.userData.value, customHTMLDataDefinition);
let linkContents = customData.link.length.value > 0 ? textDecoder.decode(new Uint8Array(memoryDataView.buffer.slice(customData.link.chars.value, customData.link.chars.value + customData.link.length.value))) : 0;
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;
memoryDataView.setUint32(0, renderCommand.id.value, true);
if (linkContents.length > 0 && (window.mouseDownThisFrame || window.touchDown) && instance.exports.Clay_PointerOver(0)) {
window.location.href = linkContents;
}
}
break;
}
case (CLAY_RENDER_COMMAND_TYPE_BORDER): {
let config = renderCommand.renderData.border;
let color = config.color;
let config = readStructAtAddress(renderCommand.config.value, borderConfigDefinition);
ctx.beginPath();
ctx.moveTo(boundingBox.x.value * scale, boundingBox.y.value * scale);
// Top Left Corner
if (config.cornerRadius.topLeft.value > 0) {
let lineWidth = config.width.top.value;
let lineWidth = config.top.width.value;
let halfLineWidth = lineWidth / 2;
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 / 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();
}
// Top border
if (config.width.top.value > 0) {
let lineWidth = config.width.top.value;
if (config.top.width.value > 0) {
let lineWidth = config.top.width.value;
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 / 255})`;
ctx.moveTo((boundingBox.x.value + config.cornerRadius.topLeft.value + halfLineWidth) * scale, (boundingBox.y.value + halfLineWidth) * scale);
@ -689,17 +650,19 @@
}
// Top Right Corner
if (config.cornerRadius.topRight.value > 0) {
let lineWidth = config.width.top.value;
let lineWidth = config.top.width.value;
let halfLineWidth = lineWidth / 2;
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 / 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();
}
// Right border
if (config.width.right.value > 0) {
let lineWidth = config.width.right.value;
if (config.right.width.value > 0) {
let color = config.right.color;
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 / 255})`;
@ -709,7 +672,8 @@
}
// Bottom Right Corner
if (config.cornerRadius.bottomRight.value > 0) {
let lineWidth = config.width.top.value;
let color = config.top.color;
let lineWidth = config.top.width.value;
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;
@ -718,8 +682,9 @@
ctx.stroke();
}
// Bottom Border
if (config.width.bottom.value > 0) {
let lineWidth = config.width.bottom.value;
if (config.bottom.width.value > 0) {
let color = config.bottom.color;
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 / 255})`;
@ -729,7 +694,8 @@
}
// Bottom Left Corner
if (config.cornerRadius.bottomLeft.value > 0) {
let lineWidth = config.width.bottom.value;
let color = config.bottom.color;
let lineWidth = config.bottom.width.value;
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;
@ -738,8 +704,9 @@
ctx.stroke();
}
// Left Border
if (config.width.left.value > 0) {
let lineWidth = config.width.left.value;
if (config.left.width.value > 0) {
let color = config.left.color;
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 / 255})`;
@ -751,8 +718,8 @@
break;
}
case (CLAY_RENDER_COMMAND_TYPE_TEXT): {
let config = renderCommand.renderData.text;
let textContents = config.stringContents;
let config = readStructAtAddress(renderCommand.config.value, textConfigDefinition);
let textContents = renderCommand.text;
let stringContents = new Uint8Array(memoryDataView.buffer.slice(textContents.chars.value, textContents.chars.value + textContents.length.value));
let fontSize = config.fontSize.value * GLOBAL_FONT_SCALING_FACTOR * scale;
ctx.font = `${fontSize}px ${fontsById[config.fontId.value]}`;
@ -775,9 +742,8 @@
break;
}
case (CLAY_RENDER_COMMAND_TYPE_IMAGE): {
let config = renderCommand.renderData.image;
let imageURL = readStructAtAddress(config.imageData.value, stringDefinition);
let src = textDecoder.decode(new Uint8Array(memoryDataView.buffer.slice(imageURL.chars.value, imageURL.chars.value + imageURL.length.value)));
let config = readStructAtAddress(renderCommand.config.value, imageConfigDefinition);
let src = textDecoder.decode(new Uint8Array(memoryDataView.buffer.slice(config.sourceURL.chars.value, config.sourceURL.chars.value + config.sourceURL.length.value)));
if (!imageCache[src]) {
imageCache[src] = {
image: new Image(),

View File

@ -86,10 +86,6 @@
];
let elementCache = {};
let imageCache = {};
let dimensionsDefinition = { type: 'struct', members: [
{name: 'width', type: 'float'},
{name: 'height', type: 'float'},
]};
let colorDefinition = { type: 'struct', members: [
{name: 'r', type: 'float' },
{name: 'g', type: 'float' },
@ -105,12 +101,9 @@
{name: 'chars', type: 'uint32_t' },
{name: 'baseChars', type: 'uint32_t' },
]};
let borderWidthDefinition = { type: 'struct', members: [
{name: 'left', type: 'uint16_t'},
{name: 'right', type: 'uint16_t'},
{name: 'top', type: 'uint16_t'},
{name: 'bottom', type: 'uint16_t'},
{name: 'betweenChildren', type: 'uint16_t'},
let borderDefinition = { type: 'struct', members: [
{name: 'width', type: 'uint32_t'},
{name: 'color', ...colorDefinition},
]};
let cornerRadiusDefinition = { type: 'struct', members: [
{name: 'topLeft', type: 'float'},
@ -118,53 +111,44 @@
{name: 'bottomLeft', type: 'float'},
{name: 'bottomRight', type: 'float'},
]};
let rectangleConfigDefinition = { name: 'rectangle', type: 'struct', members: [
{ name: 'color', ...colorDefinition },
{ name: 'link', ...stringDefinition },
{ name: 'cursorPointer', type: 'uint8_t' },
]};
let borderConfigDefinition = { name: 'text', type: 'struct', members: [
{ name: 'left', ...borderDefinition },
{ name: 'right', ...borderDefinition },
{ name: 'top', ...borderDefinition },
{ name: 'bottom', ...borderDefinition },
{ name: 'betweenChildren', ...borderDefinition },
]};
let textConfigDefinition = { name: 'text', type: 'struct', members: [
{ name: 'textColor', ...colorDefinition },
{ name: 'fontId', type: 'uint16_t' },
{ name: 'fontSize', type: 'uint16_t' },
{ name: 'letterSpacing', type: 'uint16_t' },
{ name: 'lineSpacing', type: 'uint16_t' },
{ name: 'wrapMode', type: 'uint8_t' },
{ name: 'disablePointerEvents', type: 'uint8_t' },
{ name: '_padding', type: 'uint16_t' },
{ name: 'wrapMode', type: 'uint32_t' },
{ name: 'disablePointerEvents', type: 'uint8_t' }
]};
let textRenderDataDefinition = { type: 'struct', members: [
{ name: 'stringContents', ...stringSliceDefinition },
{ name: 'textColor', ...colorDefinition },
{ name: 'fontId', type: 'uint16_t' },
{ name: 'fontSize', type: 'uint16_t' },
{ name: 'letterSpacing', type: 'uint16_t' },
{ name: 'lineHeight', type: 'uint16_t' },
]};
let rectangleRenderDataDefinition = { type: 'struct', members: [
{ name: 'backgroundColor', ...colorDefinition },
{ name: 'cornerRadius', ...cornerRadiusDefinition },
]};
let imageRenderDataDefinition = { type: 'struct', members: [
{ name: 'backgroundColor', ...colorDefinition },
{ name: 'cornerRadius', ...cornerRadiusDefinition },
{ name: 'sourceDimensions', ...dimensionsDefinition },
{ name: 'imageData', type: 'uint32_t' },
]};
let customRenderDataDefinition = { type: 'struct', members: [
{ name: 'backgroundColor', ...colorDefinition },
{ name: 'cornerRadius', ...cornerRadiusDefinition },
{ name: 'customData', type: 'uint32_t' },
]};
let borderRenderDataDefinition = { type: 'struct', members: [
{ name: 'color', ...colorDefinition },
{ name: 'cornerRadius', ...cornerRadiusDefinition },
{ name: 'width', ...borderWidthDefinition },
{ name: 'padding', type: 'uint16_t'}
]};
let scrollRenderDataDefinition = { type: 'struct', members: [
let scrollConfigDefinition = { name: 'text', type: 'struct', members: [
{ name: 'horizontal', type: 'bool' },
{ name: 'vertical', type: 'bool' },
]};
let customHTMLDataDefinition = { type: 'struct', members: [
{ name: 'link', ...stringDefinition },
{ name: 'cursorPointer', type: 'uint8_t' },
{ name: 'disablePointerEvents', type: 'uint8_t' },
let imageConfigDefinition = { name: 'image', type: 'struct', members: [
{ name: 'imageData', type: 'uint32_t' },
{ name: 'sourceDimensions', type: 'struct', members: [
{ name: 'width', type: 'float' },
{ name: 'height', type: 'float' },
]},
{ name: 'sourceURL', ...stringDefinition }
]};
let customConfigDefinition = { name: 'custom', type: 'struct', members: [
{ name: 'customData', type: 'uint32_t' },
]}
let sharedConfigDefinition = { name: 'shared', type: 'struct', members: [
{ name: 'cornerRadius', ...cornerRadiusDefinition },
]};
let renderCommandDefinition = {
name: 'CLay_RenderCommand',
@ -176,19 +160,14 @@
{ name: 'width', type: 'float' },
{ name: 'height', type: 'float' },
]},
{ name: 'renderData', type: 'union', members: [
{ name: 'rectangle', ...rectangleRenderDataDefinition },
{ name: 'text', ...textRenderDataDefinition },
{ name: 'image', ...imageRenderDataDefinition },
{ name: 'custom', ...customRenderDataDefinition },
{ name: 'border', ...borderRenderDataDefinition },
{ name: 'scroll', ...scrollRenderDataDefinition },
{ name: 'config', type: 'uint32_t'},
{ name: 'textOrSharedConfig', type: 'union', members: [
{ name: 'text', ...stringSliceDefinition },
{ name: 'sharedConfig', type: 'uint32_t' }
]},
{ name: 'userData', type: 'uint32_t'},
{ name: 'zIndex', type: 'int32_t' },
{ name: 'id', type: 'uint32_t' },
{ name: 'zIndex', type: 'int16_t' },
{ name: 'commandType', type: 'uint8_t' },
{ name: '_padding', type: 'uint8_t' },
{ name: 'commandType', type: 'uint32_t', },
]
};
@ -211,7 +190,6 @@
case 'uint32_t': return 4;
case 'int32_t': return 4;
case 'uint16_t': return 2;
case 'int16_t': return 2;
case 'uint8_t': return 1;
case 'bool': return 1;
default: {
@ -241,7 +219,6 @@
case 'uint32_t': return { value: memoryDataView.getUint32(address, true), __size: 4 };
case 'int32_t': return { value: memoryDataView.getUint32(address, true), __size: 4 };
case 'uint16_t': return { value: memoryDataView.getUint16(address, true), __size: 2 };
case 'int16_t': return { value: memoryDataView.getInt16(address, true), __size: 2 };
case 'uint8_t': return { value: memoryDataView.getUint8(address, true), __size: 1 };
case 'bool': return { value: memoryDataView.getUint8(address, true), __size: 1 };
default: {
@ -363,7 +340,7 @@
memoryDataView.setFloat32(addressOfOffset, -container.scrollLeft, true);
memoryDataView.setFloat32(addressOfOffset + 4, -container.scrollTop, true);
}
},
}
},
};
const { instance } = await WebAssembly.instantiateStreaming(
@ -371,15 +348,13 @@
);
memoryDataView = new DataView(new Uint8Array(instance.exports.memory.buffer).buffer);
scratchSpaceAddress = instance.exports.__heap_base.value;
let clayScratchSpaceAddress = instance.exports.__heap_base.value + 1024;
heapSpaceAddress = instance.exports.__heap_base.value + 2048;
heapSpaceAddress = instance.exports.__heap_base.value + 1024;
let arenaAddress = scratchSpaceAddress + 8;
window.instance = instance;
createMainArena(arenaAddress, heapSpaceAddress);
memoryDataView.setFloat32(instance.exports.__heap_base.value, window.innerWidth, true);
memoryDataView.setFloat32(instance.exports.__heap_base.value + 4, window.innerHeight, true);
instance.exports.Clay_Initialize(arenaAddress, instance.exports.__heap_base.value);
instance.exports.SetScratchMemory(arenaAddress, clayScratchSpaceAddress);
renderCommandSize = getStructTotalSize(renderCommandDefinition);
renderLoop();
}
@ -393,22 +368,6 @@
return false;
}
function SetElementBackgroundColorAndRadius(element, cornerRadius, backgroundColor) {
element.style.backgroundColor = `rgba(${backgroundColor.r.value}, ${backgroundColor.g.value}, ${backgroundColor.b.value}, ${backgroundColor.a.value / 255})`;
if (cornerRadius.topLeft.value > 0) {
element.style.borderTopLeftRadius = cornerRadius.topLeft.value + 'px';
}
if (cornerRadius.topRight.value > 0) {
element.style.borderTopRightRadius = cornerRadius.topRight.value + 'px';
}
if (cornerRadius.bottomLeft.value > 0) {
element.style.borderBottomLeftRadius = cornerRadius.bottomLeft.value + 'px';
}
if (cornerRadius.bottomRight.value > 0) {
element.style.borderBottomRightRadius = cornerRadius.bottomRight.value + 'px';
}
}
function renderLoopHTML() {
let capacity = memoryDataView.getInt32(scratchSpaceAddress, true);
let length = memoryDataView.getInt32(scratchSpaceAddress + 4, true);
@ -416,7 +375,7 @@
let scissorStack = [{ nextAllocation: { x: 0, y: 0 }, element: htmlRoot, nextElementIndex: 0 }];
let previousId = 0;
for (let i = 0; i < length; i++, arrayOffset += renderCommandSize) {
let entireRenderCommandMemory = new Uint8Array(memoryDataView.buffer.slice(arrayOffset, arrayOffset + renderCommandSize));
let entireRenderCommandMemory = new Uint32Array(memoryDataView.buffer.slice(arrayOffset, arrayOffset + renderCommandSize));
let renderCommand = readStructAtAddress(arrayOffset, renderCommandDefinition);
let parentElement = scissorStack[scissorStack.length - 1];
let element = null;
@ -425,12 +384,13 @@
let elementType = 'div';
switch (renderCommand.commandType.value & 0xff) {
case CLAY_RENDER_COMMAND_TYPE_RECTANGLE: {
// if (readStructAtAddress(renderCommand.renderData.rectangle.value, rectangleRenderDataDefinition).link.length.value > 0) { TODO reimplement links
// elementType = 'a';
// }
if (readStructAtAddress(renderCommand.config.value, rectangleConfigDefinition).link.length.value > 0) {
elementType = 'a';
}
break;
}
case CLAY_RENDER_COMMAND_TYPE_IMAGE: {
console.log('test5');
elementType = 'img'; break;
}
default: break;
@ -483,82 +443,93 @@
break;
}
case (CLAY_RENDER_COMMAND_TYPE_RECTANGLE): {
let config = renderCommand.renderData.rectangle;
let configMemory = JSON.stringify(config);
if (configMemory === elementData.previousMemoryConfig) {
break;
}
SetElementBackgroundColorAndRadius(element, config.cornerRadius, config.backgroundColor);
if (renderCommand.userData.value !== 0) {
let customData = readStructAtAddress(renderCommand.userData.value, customHTMLDataDefinition);
let linkContents = customData.link.length.value > 0 ? textDecoder.decode(new Uint8Array(memoryDataView.buffer.slice(customData.link.chars.value, customData.link.chars.value + customData.link.length.value))) : 0;
let config = readStructAtAddress(renderCommand.config.value, rectangleConfigDefinition);
let sharedConfig = readStructAtAddress( renderCommand.textOrSharedConfig.sharedConfig.value, sharedConfigDefinition);
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;
memoryDataView.setUint32(0, renderCommand.id.value, true);
if (linkContents.length > 0 && (window.mouseDownThisFrame || window.touchDown) && instance.exports.Clay_PointerOver(0)) {
window.location.href = linkContents;
}
if (!dirty && !MemoryIsDifferent(configMemory, elementData.previousMemoryConfig, config.__size)) {
break;
}
if (linkContents.length > 0) {
element.href = linkContents;
}
if (linkContents.length > 0 || customData.cursorPointer.value) {
if (linkContents.length > 0 || config.cursorPointer.value) {
element.style.pointerEvents = 'all';
element.style.cursor = 'pointer';
}
}
elementData.previousMemoryConfig = configMemory;
let color = config.color;
element.style.backgroundColor = `rgba(${color.r.value}, ${color.g.value}, ${color.b.value}, ${color.a.value / 255})`;
if (sharedConfig.cornerRadius.topLeft.value > 0) {
element.style.borderTopLeftRadius = sharedConfig.cornerRadius.topLeft.value + 'px';
}
if (sharedConfig.cornerRadius.topRight.value > 0) {
element.style.borderTopRightRadius = sharedConfig.cornerRadius.topRight.value + 'px';
}
if (sharedConfig.cornerRadius.bottomLeft.value > 0) {
element.style.borderBottomLeftRadius = sharedConfig.cornerRadius.bottomLeft.value + 'px';
}
if (sharedConfig.cornerRadius.bottomRight.value > 0) {
element.style.borderBottomRightRadius = sharedConfig.cornerRadius.bottomRight.value + 'px';
}
break;
}
case (CLAY_RENDER_COMMAND_TYPE_BORDER): {
let config = renderCommand.renderData.border;
let configMemory = JSON.stringify(config);
if (configMemory === elementData.previousMemoryConfig) {
let config = readStructAtAddress(renderCommand.config.value, borderConfigDefinition);
let sharedConfig = readStructAtAddress( renderCommand.textOrSharedConfig.sharedConfig.value, sharedConfigDefinition);
let configMemory = new Uint8Array(memoryDataView.buffer.slice(renderCommand.config.value, renderCommand.config.value + config.__size));
if (!dirty && !MemoryIsDifferent(configMemory, elementData.previousMemoryConfig, config.__size)) {
break;
}
let color = config.color;
elementData.previousMemoryConfig = configMemory;
if (config.width.left.value > 0) {
element.style.borderLeft = `${config.width.left.value}px solid rgba(${color.r.value}, ${color.g.value}, ${color.b.value}, ${color.a.value / 255})`
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 / 255})`
}
if (config.width.right.value > 0) {
element.style.borderRight = `${config.width.right.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 / 255})`
}
if (config.width.top.value > 0) {
element.style.borderTop = `${config.width.top.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 / 255})`
}
if (config.width.bottom.value > 0) {
element.style.borderBottom = `${config.width.bottom.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 / 255})`
}
if (config.cornerRadius.topLeft.value > 0) {
element.style.borderTopLeftRadius = config.cornerRadius.topLeft.value + 'px';
if (sharedConfig.cornerRadius.topLeft.value > 0) {
element.style.borderTopLeftRadius = sharedConfig.cornerRadius.topLeft.value + 'px';
}
if (config.cornerRadius.topRight.value > 0) {
element.style.borderTopRightRadius = config.cornerRadius.topRight.value + 'px';
if (sharedConfig.cornerRadius.topRight.value > 0) {
element.style.borderTopRightRadius = sharedConfig.cornerRadius.topRight.value + 'px';
}
if (config.cornerRadius.bottomLeft.value > 0) {
element.style.borderBottomLeftRadius = config.cornerRadius.bottomLeft.value + 'px';
if (sharedConfig.cornerRadius.bottomLeft.value > 0) {
element.style.borderBottomLeftRadius = sharedConfig.cornerRadius.bottomLeft.value + 'px';
}
if (config.cornerRadius.bottomRight.value > 0) {
element.style.borderBottomRightRadius = config.cornerRadius.bottomRight.value + 'px';
if (sharedConfig.cornerRadius.bottomRight.value > 0) {
element.style.borderBottomRightRadius = sharedConfig.cornerRadius.bottomRight.value + 'px';
}
break;
}
case (CLAY_RENDER_COMMAND_TYPE_TEXT): {
let config = renderCommand.renderData.text;
let customData = readStructAtAddress(renderCommand.userData.value, customHTMLDataDefinition);
let configMemory = JSON.stringify(config);
let stringContents = new Uint8Array(memoryDataView.buffer.slice(config.stringContents.chars.value, config.stringContents.chars.value + config.stringContents.length.value));
if (configMemory !== elementData.previousMemoryConfig) {
let config = readStructAtAddress(renderCommand.config.value, textConfigDefinition);
let configMemory = new Uint8Array(memoryDataView.buffer.slice(renderCommand.config.value, renderCommand.config.value + config.__size));
let textContents = renderCommand.textOrSharedConfig.text;
let stringContents = new Uint8Array(memoryDataView.buffer.slice(textContents.chars.value, textContents.chars.value + textContents.length.value));
if (MemoryIsDifferent(configMemory, elementData.previousMemoryConfig, config.__size)) {
element.className = 'text';
let textColor = config.textColor;
let fontSize = Math.round(config.fontSize.value * GLOBAL_FONT_SCALING_FACTOR);
element.style.color = `rgba(${textColor.r.value}, ${textColor.g.value}, ${textColor.b.value}, ${textColor.a.value})`;
element.style.fontFamily = fontsById[config.fontId.value];
element.style.fontSize = fontSize + 'px';
element.style.pointerEvents = customData.disablePointerEvents.value ? 'none' : 'all';
element.style.pointerEvents = config.disablePointerEvents.value ? 'none' : 'all';
elementData.previousMemoryConfig = configMemory;
}
if (stringContents.length !== elementData.previousMemoryText.length || MemoryIsDifferent(stringContents, elementData.previousMemoryText, stringContents.length)) {
@ -569,11 +540,7 @@
}
case (CLAY_RENDER_COMMAND_TYPE_SCISSOR_START): {
scissorStack.push({ nextAllocation: { x: renderCommand.boundingBox.x.value, y: renderCommand.boundingBox.y.value }, element, nextElementIndex: 0 });
let config = renderCommand.renderData.scroll;
let configMemory = JSON.stringify(config);
if (configMemory === elementData.previousMemoryConfig) {
break;
}
let config = readStructAtAddress(renderCommand.config.value, scrollConfigDefinition);
if (config.horizontal.value) {
element.style.overflowX = 'scroll';
element.style.pointerEvents = 'auto';
@ -582,7 +549,6 @@
element.style.overflowY = 'scroll';
element.style.pointerEvents = 'auto';
}
elementData.previousMemoryConfig = configMemory;
break;
}
case (CLAY_RENDER_COMMAND_TYPE_SCISSOR_END): {
@ -590,9 +556,9 @@
break;
}
case (CLAY_RENDER_COMMAND_TYPE_IMAGE): {
let config = renderCommand.renderData.image;
let imageURL = readStructAtAddress(config.imageData.value, stringDefinition);
let srcContents = new Uint8Array(memoryDataView.buffer.slice(imageURL.chars.value, imageURL.chars.value + imageURL.length.value));
console.log('test1');
let config = readStructAtAddress(renderCommand.config.value, imageConfigDefinition);
let srcContents = new Uint8Array(memoryDataView.buffer.slice(config.sourceURL.chars.value, config.sourceURL.chars.value + config.sourceURL.length.value));
if (srcContents.length !== elementData.previousMemoryText.length || MemoryIsDifferent(srcContents, elementData.previousMemoryText, srcContents.length)) {
element.src = textDecoder.decode(srcContents);
}
@ -600,9 +566,6 @@
break;
}
case (CLAY_RENDER_COMMAND_TYPE_CUSTOM): break;
default: {
console.log("Error: unhandled render command");
}
}
}
@ -639,8 +602,8 @@
break;
}
case (CLAY_RENDER_COMMAND_TYPE_RECTANGLE): {
let config = renderCommand.renderData.rectangle;
let color = config.backgroundColor;
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 / 255})`;
window.canvasContext.roundRect(
@ -652,35 +615,33 @@
ctx.fill();
ctx.closePath();
// Handle link clicks
if (renderCommand.userData.value !== 0) {
let customData = readStructAtAddress(renderCommand.userData.value, customHTMLDataDefinition);
let linkContents = customData.link.length.value > 0 ? textDecoder.decode(new Uint8Array(memoryDataView.buffer.slice(customData.link.chars.value, customData.link.chars.value + customData.link.length.value))) : 0;
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;
memoryDataView.setUint32(0, renderCommand.id.value, true);
if (linkContents.length > 0 && (window.mouseDownThisFrame || window.touchDown) && instance.exports.Clay_PointerOver(0)) {
window.location.href = linkContents;
}
}
break;
}
case (CLAY_RENDER_COMMAND_TYPE_BORDER): {
let config = renderCommand.renderData.border;
let color = config.color;
let config = readStructAtAddress(renderCommand.config.value, borderConfigDefinition);
ctx.beginPath();
ctx.moveTo(boundingBox.x.value * scale, boundingBox.y.value * scale);
// Top Left Corner
if (config.cornerRadius.topLeft.value > 0) {
let lineWidth = config.width.top.value;
let lineWidth = config.top.width.value;
let halfLineWidth = lineWidth / 2;
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 / 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();
}
// Top border
if (config.width.top.value > 0) {
let lineWidth = config.width.top.value;
if (config.top.width.value > 0) {
let lineWidth = config.top.width.value;
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 / 255})`;
ctx.moveTo((boundingBox.x.value + config.cornerRadius.topLeft.value + halfLineWidth) * scale, (boundingBox.y.value + halfLineWidth) * scale);
@ -689,17 +650,19 @@
}
// Top Right Corner
if (config.cornerRadius.topRight.value > 0) {
let lineWidth = config.width.top.value;
let lineWidth = config.top.width.value;
let halfLineWidth = lineWidth / 2;
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 / 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();
}
// Right border
if (config.width.right.value > 0) {
let lineWidth = config.width.right.value;
if (config.right.width.value > 0) {
let color = config.right.color;
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 / 255})`;
@ -709,7 +672,8 @@
}
// Bottom Right Corner
if (config.cornerRadius.bottomRight.value > 0) {
let lineWidth = config.width.top.value;
let color = config.top.color;
let lineWidth = config.top.width.value;
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;
@ -718,8 +682,9 @@
ctx.stroke();
}
// Bottom Border
if (config.width.bottom.value > 0) {
let lineWidth = config.width.bottom.value;
if (config.bottom.width.value > 0) {
let color = config.bottom.color;
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 / 255})`;
@ -729,7 +694,8 @@
}
// Bottom Left Corner
if (config.cornerRadius.bottomLeft.value > 0) {
let lineWidth = config.width.bottom.value;
let color = config.bottom.color;
let lineWidth = config.bottom.width.value;
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;
@ -738,8 +704,9 @@
ctx.stroke();
}
// Left Border
if (config.width.left.value > 0) {
let lineWidth = config.width.left.value;
if (config.left.width.value > 0) {
let color = config.left.color;
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 / 255})`;
@ -751,8 +718,8 @@
break;
}
case (CLAY_RENDER_COMMAND_TYPE_TEXT): {
let config = renderCommand.renderData.text;
let textContents = config.stringContents;
let config = readStructAtAddress(renderCommand.config.value, textConfigDefinition);
let textContents = renderCommand.text;
let stringContents = new Uint8Array(memoryDataView.buffer.slice(textContents.chars.value, textContents.chars.value + textContents.length.value));
let fontSize = config.fontSize.value * GLOBAL_FONT_SCALING_FACTOR * scale;
ctx.font = `${fontSize}px ${fontsById[config.fontId.value]}`;
@ -775,9 +742,8 @@
break;
}
case (CLAY_RENDER_COMMAND_TYPE_IMAGE): {
let config = renderCommand.renderData.image;
let imageURL = readStructAtAddress(config.imageData.value, stringDefinition);
let src = textDecoder.decode(new Uint8Array(memoryDataView.buffer.slice(imageURL.chars.value, imageURL.chars.value + imageURL.length.value)));
let config = readStructAtAddress(renderCommand.config.value, imageConfigDefinition);
let src = textDecoder.decode(new Uint8Array(memoryDataView.buffer.slice(config.sourceURL.chars.value, config.sourceURL.chars.value + config.sourceURL.length.value)));
if (!imageCache[src]) {
imageCache[src] = {
image: new Image(),

View File

@ -3,7 +3,7 @@
double windowWidth = 1024, windowHeight = 768;
float modelPageOneZRotation = 0;
uint32_t ACTIVE_RENDERER_INDEX = 1;
uint32_t ACTIVE_RENDERER_INDEX = 0;
const uint32_t FONT_ID_BODY_16 = 0;
const uint32_t FONT_ID_TITLE_56 = 1;
@ -52,21 +52,13 @@ typedef struct {
CustomHTMLData* FrameAllocateCustomData(CustomHTMLData data) {
CustomHTMLData *customData = (CustomHTMLData *)(frameArena.memory + frameArena.offset);
*customData = data;
frameArena.offset += sizeof(CustomHTMLData);
return customData;
}
Clay_String* FrameAllocateString(Clay_String string) {
Clay_String *allocated = (Clay_String *)(frameArena.memory + frameArena.offset);
*allocated = string;
frameArena.offset += sizeof(Clay_String);
return allocated;
}
void LandingPageBlob(int index, int fontSize, Clay_Color color, Clay_String text, Clay_String imageURL) {
void LandingPageBlob(int index, int fontSize, Clay_Color color, Clay_String text, char* imageURL) {
CLAY({ .id = CLAY_IDI("HeroBlob", index), .layout = { .sizing = { CLAY_SIZING_GROW(.max = 480) }, .padding = CLAY_PADDING_ALL(16), .childGap = 16, .childAlignment = {.y = CLAY_ALIGN_Y_CENTER} }, .border = { .color = color, .width = { 2, 2, 2, 2 }}, .cornerRadius = CLAY_CORNER_RADIUS(10) }) {
CLAY({ .id = CLAY_IDI("CheckImage", index), .layout = { .sizing = { CLAY_SIZING_FIXED(32) } }, .image = { .sourceDimensions = { 128, 128 }, .imageData = FrameAllocateString(imageURL) } }) {}
CLAY({ .id = CLAY_IDI("CheckImage", index), .layout = { .sizing = { CLAY_SIZING_FIXED(32) } }, .image = { .sourceDimensions = { 128, 128 }, .imageData = imageURL } }) {}
CLAY_TEXT(text, CLAY_TEXT_CONFIG({ .fontSize = fontSize, .fontId = FONT_ID_BODY_24, .textColor = color }));
}
}
@ -80,11 +72,11 @@ void LandingPageDesktop() {
CLAY_TEXT(CLAY_STRING("Clay is laying out this webpage right now!"), CLAY_TEXT_CONFIG({ .fontSize = 36, .fontId = FONT_ID_TITLE_36, .textColor = COLOR_ORANGE }));
}
CLAY({ .id = CLAY_ID("HeroImageOuter"), .layout = { .layoutDirection = CLAY_TOP_TO_BOTTOM, .sizing = { .width = CLAY_SIZING_PERCENT(0.45f) }, .childAlignment = { CLAY_ALIGN_X_CENTER }, .childGap = 16 } }) {
LandingPageBlob(1, 32, COLOR_BLOB_BORDER_5, CLAY_STRING("High performance"), CLAY_STRING("/clay/images/check_5.png"));
LandingPageBlob(2, 32, COLOR_BLOB_BORDER_4, CLAY_STRING("Flexbox-style responsive layout"), CLAY_STRING("/clay/images/check_4.png"));
LandingPageBlob(3, 32, COLOR_BLOB_BORDER_3, CLAY_STRING("Declarative syntax"), CLAY_STRING("/clay/images/check_3.png"));
LandingPageBlob(4, 32, COLOR_BLOB_BORDER_2, CLAY_STRING("Single .h file for C/C++"), CLAY_STRING("/clay/images/check_2.png"));
LandingPageBlob(5, 32, COLOR_BLOB_BORDER_1, CLAY_STRING("Compile to 15kb .wasm"), CLAY_STRING("/clay/images/check_1.png"));
LandingPageBlob(1, 32, COLOR_BLOB_BORDER_5, CLAY_STRING("High performance"), "/clay/images/check_5.png");
LandingPageBlob(2, 32, COLOR_BLOB_BORDER_4, CLAY_STRING("Flexbox-style responsive layout"), "/clay/images/check_4.png");
LandingPageBlob(3, 32, COLOR_BLOB_BORDER_3, CLAY_STRING("Declarative syntax"), "/clay/images/check_3.png");
LandingPageBlob(4, 32, COLOR_BLOB_BORDER_2, CLAY_STRING("Single .h file for C/C++"), "/clay/images/check_2.png");
LandingPageBlob(5, 32, COLOR_BLOB_BORDER_1, CLAY_STRING("Compile to 15kb .wasm"), "/clay/images/check_1.png");
}
}
}
@ -98,11 +90,11 @@ void LandingPageMobile() {
CLAY_TEXT(CLAY_STRING("Clay is laying out this webpage right now!"), CLAY_TEXT_CONFIG({ .fontSize = 32, .fontId = FONT_ID_TITLE_36, .textColor = COLOR_ORANGE }));
}
CLAY({ .id = CLAY_ID("HeroImageOuter"), .layout = { .layoutDirection = CLAY_TOP_TO_BOTTOM, .sizing = { .width = CLAY_SIZING_GROW(0) }, .childAlignment = { CLAY_ALIGN_X_CENTER }, .childGap = 16 } }) {
LandingPageBlob(1, 28, COLOR_BLOB_BORDER_5, CLAY_STRING("High performance"), CLAY_STRING("/clay/images/check_5.png"));
LandingPageBlob(2, 28, COLOR_BLOB_BORDER_4, CLAY_STRING("Flexbox-style responsive layout"), CLAY_STRING("/clay/images/check_4.png"));
LandingPageBlob(3, 28, COLOR_BLOB_BORDER_3, CLAY_STRING("Declarative syntax"), CLAY_STRING("/clay/images/check_3.png"));
LandingPageBlob(4, 28, COLOR_BLOB_BORDER_2, CLAY_STRING("Single .h file for C/C++"), CLAY_STRING("/clay/images/check_2.png"));
LandingPageBlob(5, 28, COLOR_BLOB_BORDER_1, CLAY_STRING("Compile to 15kb .wasm"), CLAY_STRING("/clay/images/check_1.png"));
LandingPageBlob(1, 28, COLOR_BLOB_BORDER_5, CLAY_STRING("High performance"), "/clay/images/check_5.png");
LandingPageBlob(2, 28, COLOR_BLOB_BORDER_4, CLAY_STRING("Flexbox-style responsive layout"), "/clay/images/check_4.png");
LandingPageBlob(3, 28, COLOR_BLOB_BORDER_3, CLAY_STRING("Declarative syntax"), "/clay/images/check_3.png");
LandingPageBlob(4, 28, COLOR_BLOB_BORDER_2, CLAY_STRING("Single .h file for C/C++"), "/clay/images/check_2.png");
LandingPageBlob(5, 28, COLOR_BLOB_BORDER_1, CLAY_STRING("Compile to 15kb .wasm"), "/clay/images/check_1.png");
}
}
}
@ -156,7 +148,7 @@ void DeclarativeSyntaxPageDesktop() {
CLAY_TEXT(CLAY_STRING("Create your own library of re-usable components from UI primitives like text, images and rectangles."), CLAY_TEXT_CONFIG({ .fontSize = 28, .fontId = FONT_ID_BODY_36, .textColor = COLOR_RED }));
}
CLAY({ .id = CLAY_ID("SyntaxPageRightImage"), .layout = { .sizing = { CLAY_SIZING_PERCENT(0.50) }, .childAlignment = {.x = CLAY_ALIGN_X_CENTER} } }) {
CLAY({ .id = CLAY_ID("SyntaxPageRightImageInner"), .layout = { .sizing = { CLAY_SIZING_GROW(.max = 568) } }, .image = { .sourceDimensions = {1136, 1194}, .imageData = FrameAllocateString(CLAY_STRING("/clay/images/declarative.png")) } }) {}
CLAY({ .id = CLAY_ID("SyntaxPageRightImageInner"), .layout = { .sizing = { CLAY_SIZING_GROW(.max = 568) } }, .image = { .sourceDimensions = {1136, 1194}, .imageData = "/clay/images/declarative.png" } }) {}
}
}
}
@ -172,7 +164,7 @@ void DeclarativeSyntaxPageMobile() {
CLAY_TEXT(CLAY_STRING("Create your own library of re-usable components from UI primitives like text, images and rectangles."), CLAY_TEXT_CONFIG({ .fontSize = 28, .fontId = FONT_ID_BODY_36, .textColor = COLOR_RED }));
}
CLAY({ .id = CLAY_ID("SyntaxPageRightImage"), .layout = { .sizing = { CLAY_SIZING_GROW(0) }, .childAlignment = {.x = CLAY_ALIGN_X_CENTER} } }) {
CLAY({ .id = CLAY_ID("SyntaxPageRightImageInner"), .layout = { .sizing = { CLAY_SIZING_GROW(.max = 568) } }, .image = { .sourceDimensions = {1136, 1194}, .imageData = FrameAllocateString(CLAY_STRING("/clay/images/declarative.png")) } }) {}
CLAY({ .id = CLAY_ID("SyntaxPageRightImageInner"), .layout = { .sizing = { CLAY_SIZING_GROW(.max = 568) } }, .image = { .sourceDimensions = {1136, 1194}, .imageData = "/clay/images/declarative.png" } }) {}
}
}
}
@ -245,7 +237,7 @@ void RendererButtonActive(Clay_String text) {
.layout = { .sizing = {CLAY_SIZING_FIXED(300) }, .padding = CLAY_PADDING_ALL(16) },
.backgroundColor = Clay_Hovered() ? COLOR_RED_HOVER : COLOR_RED,
.cornerRadius = CLAY_CORNER_RADIUS(10),
.userData = FrameAllocateCustomData((CustomHTMLData) { .disablePointerEvents = true, .cursorPointer = true })
.custom = { .customData = FrameAllocateCustomData((CustomHTMLData) { .disablePointerEvents = true, .cursorPointer = true })}
}) {
CLAY_TEXT(text, CLAY_TEXT_CONFIG({ .fontSize = 28, .fontId = FONT_ID_BODY_36, .textColor = COLOR_LIGHT }));
}
@ -257,7 +249,7 @@ void RendererButtonInactive(Clay_String text, size_t rendererIndex) {
.border = { .width = {2, 2, 2, 2}, .color = COLOR_RED },
.backgroundColor = Clay_Hovered() ? COLOR_LIGHT_HOVER : COLOR_LIGHT,
.cornerRadius = CLAY_CORNER_RADIUS(10),
.userData = FrameAllocateCustomData((CustomHTMLData) { .disablePointerEvents = true, .cursorPointer = true })
.custom = { .customData = FrameAllocateCustomData((CustomHTMLData) { .disablePointerEvents = true, .cursorPointer = true })}
}) {
Clay_OnHover(HandleRendererButtonInteraction, rendererIndex);
CLAY_TEXT(text, CLAY_TEXT_CONFIG({ .fontSize = 28, .fontId = FONT_ID_BODY_36, .textColor = COLOR_RED }));
@ -323,7 +315,7 @@ void DebuggerPageDesktop() {
CLAY_TEXT(CLAY_STRING("Press the \"d\" key to try it out now!"), CLAY_TEXT_CONFIG({ .fontSize = 32, .fontId = FONT_ID_TITLE_36, .textColor = COLOR_ORANGE }));
}
CLAY({ .id = CLAY_ID("DebuggerRightImageOuter"), .layout = { .sizing = { CLAY_SIZING_PERCENT(0.50) }, .childAlignment = {CLAY_ALIGN_X_CENTER} } }) {
CLAY({ .id = CLAY_ID("DebuggerPageRightImageInner"), .layout = { .sizing = { CLAY_SIZING_GROW(.max = 558) } }, .image = { .sourceDimensions = {1620, 1474}, .imageData = FrameAllocateString(CLAY_STRING("/clay/images/debugger.png")) } }) {}
CLAY({ .id = CLAY_ID("DebuggerPageRightImageInner"), .layout = { .sizing = { CLAY_SIZING_GROW(.max = 558) } }, .image = { .sourceDimensions = {1620, 1474}, .imageData = "/clay/images/debugger.png" } }) {}
}
}
}
@ -345,10 +337,10 @@ Clay_RenderCommandArray CreateLayout(bool mobileScreen, float lerpValue) {
CLAY_TEXT(CLAY_STRING("Clay"), &headerTextConfig);
CLAY({ .id = CLAY_ID("Spacer"), .layout = { .sizing = { .width = CLAY_SIZING_GROW(0) } } }) {}
if (!mobileScreen) {
CLAY({ .id = CLAY_ID("LinkExamplesOuter"), .layout = { .padding = {8, 8} }, .userData = FrameAllocateCustomData((CustomHTMLData) { .link = CLAY_STRING("https://github.com/nicbarker/clay/tree/main/examples") }) }) {
CLAY({ .id = CLAY_ID("LinkExamplesOuter"), .layout = { .padding = {8, 8} }, .custom = { .customData = FrameAllocateCustomData((CustomHTMLData) { .link = CLAY_STRING("https://github.com/nicbarker/clay/tree/main/examples") }) } }) {
CLAY_TEXT(CLAY_STRING("Examples"), CLAY_TEXT_CONFIG({ .fontId = FONT_ID_BODY_24, .fontSize = 24, .textColor = {61, 26, 5, 255} }));
}
CLAY({ .id = CLAY_ID("LinkDocsOuter"), .layout = { .padding = {8, 8} }, .userData = FrameAllocateCustomData((CustomHTMLData) { .link = CLAY_STRING("https://github.com/nicbarker/clay/blob/main/README.md") }) }) {
CLAY({ .id = CLAY_ID("LinkDocsOuter"), .layout = { .padding = {8, 8} }, .custom = { .customData = FrameAllocateCustomData((CustomHTMLData) { .link = CLAY_STRING("https://github.com/nicbarker/clay/blob/main/README.md") }) } }) {
CLAY_TEXT(CLAY_STRING("Docs"), CLAY_TEXT_CONFIG({ .fontId = FONT_ID_BODY_24, .fontSize = 24, .textColor = {61, 26, 5, 255} }));
}
}
@ -357,7 +349,7 @@ Clay_RenderCommandArray CreateLayout(bool mobileScreen, float lerpValue) {
.backgroundColor = Clay_Hovered() ? COLOR_LIGHT_HOVER : COLOR_LIGHT,
.border = { .width = {2, 2, 2, 2}, .color = COLOR_RED },
.cornerRadius = CLAY_CORNER_RADIUS(10),
.userData = FrameAllocateCustomData((CustomHTMLData) { .link = CLAY_STRING("https://github.com/nicbarker/clay/tree/main/examples") }),
.custom = { .customData = FrameAllocateCustomData((CustomHTMLData) { .link = CLAY_STRING("https://github.com/nicbarker/clay/tree/main/examples") }) },
}) {
CLAY_TEXT(CLAY_STRING("Discord"), CLAY_TEXT_CONFIG({ .fontId = FONT_ID_BODY_24, .fontSize = 24, .textColor = {61, 26, 5, 255} }));
}
@ -366,7 +358,7 @@ Clay_RenderCommandArray CreateLayout(bool mobileScreen, float lerpValue) {
.backgroundColor = Clay_Hovered() ? COLOR_LIGHT_HOVER : COLOR_LIGHT,
.border = { .width = {2, 2, 2, 2}, .color = COLOR_RED },
.cornerRadius = CLAY_CORNER_RADIUS(10),
.userData = FrameAllocateCustomData((CustomHTMLData) { .link = CLAY_STRING("https://github.com/nicbarker/clay") }),
.custom = { .customData = FrameAllocateCustomData((CustomHTMLData) { .link = CLAY_STRING("https://github.com/nicbarker/clay") }) },
}) {
CLAY_TEXT(CLAY_STRING("Github"), CLAY_TEXT_CONFIG({ .fontId = FONT_ID_BODY_24, .fontSize = 24, .textColor = {61, 26, 5, 255} }));
}
@ -421,12 +413,7 @@ Clay_RenderCommandArray CreateLayout(bool mobileScreen, float lerpValue) {
bool debugModeEnabled = false;
CLAY_WASM_EXPORT("SetScratchMemory") void SetScratchMemory(void * memory) {
frameArena.memory = memory;
}
CLAY_WASM_EXPORT("UpdateDrawFrame") Clay_RenderCommandArray UpdateDrawFrame(float width, float height, float mouseWheelX, float mouseWheelY, float mousePositionX, float mousePositionY, bool isTouchDown, bool isMouseDown, bool arrowKeyDownPressedThisFrame, bool arrowKeyUpPressedThisFrame, bool dKeyPressedThisFrame, float deltaTime) {
frameArena.offset = 0;
windowWidth = width;
windowHeight = height;
Clay_SetLayoutDimensions((Clay_Dimensions) { width, height });