Debug Tools (#15)

This commit is contained in:
Nic Barker 2024-09-16 21:34:59 +12:00 committed by GitHub
parent b3d768c00d
commit a4f90a217d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
21 changed files with 1381 additions and 373 deletions

View File

@ -371,7 +371,7 @@ The supported directives are:
- `CLAY_DISABLE_CULLING` - Disables [Visibility Culling](#visibility-culling) of render commands. - `CLAY_DISABLE_CULLING` - Disables [Visibility Culling](#visibility-culling) of render commands.
- `CLAY_WASM` - Required when targeting Web Assembly. - `CLAY_WASM` - Required when targeting Web Assembly.
- `CLAY_OVERFLOW_TRAP` - By default, clay will continue to allow function calls without crashing even when it exhausts all its available pre-allocated memory. This can produce erroneous layout results that are difficult to interpret. If `CLAY_OVERFLOW_TRAP` is defined, clay will raise a `SIGTRAP` signal that will be caught by your debugger. Relies on `signal.h` being available in your environment. - `CLAY_OVERFLOW_TRAP` - By default, clay will continue to allow function calls without crashing even when it exhausts all its available pre-allocated memory. This can produce erroneous layout results that are difficult to interpret. If `CLAY_OVERFLOW_TRAP` is defined, clay will raise a `SIGTRAP` signal that will be caught by your debugger. Relies on `signal.h` being available in your environment.
- `CLAY_DEBUG` - Used for debugging clay's internal implementation. Useful if you want to modify or debug clay, or learn how things work. It enables a number of debug features such as preserving source strings for has IDs to make debugging easier. - `CLAY_DEBUG` - Used for debugging clay's internal implementation. Useful if you want to modify or debug clay, or learn how things work. It enables a number of debug features such as preserving source strings for hash IDs to make debugging easier.
- `CLAY_EXTEND_CONFIG_RECTANGLE` - Provide additional struct members to `CLAY_RECTANGLE_CONFIG` that will be passed through with output render commands. - `CLAY_EXTEND_CONFIG_RECTANGLE` - Provide additional struct members to `CLAY_RECTANGLE_CONFIG` that will be passed through with output render commands.
- `CLAY_EXTEND_CONFIG_TEXT` - Provide additional struct members to `CLAY_TEXT_CONFIG` that will be passed through with output render commands. - `CLAY_EXTEND_CONFIG_TEXT` - Provide additional struct members to `CLAY_TEXT_CONFIG` that will be passed through with output render commands.
- `CLAY_EXTEND_CONFIG_IMAGE` - Provide additional struct members to `CLAY_IMAGE_CONFIG` that will be passed through with output render commands. - `CLAY_EXTEND_CONFIG_IMAGE` - Provide additional struct members to `CLAY_IMAGE_CONFIG` that will be passed through with output render commands.
@ -384,6 +384,20 @@ There are also supported bindings for other languages, including:
- [Odin Bindings](https://github.com/nicbarker/clay/tree/main/bindings/odin) - [Odin Bindings](https://github.com/nicbarker/clay/tree/main/bindings/odin)
### Debug Tools
Clay includes built-in UI debugging tools, similar to the "inspector" in browsers such as Chrome or Firefox. These tools are included in `clay.h`, and work by injecting additional render commands into the output [Clay_RenderCommandArray](#clay_rendercommandarray).
As long as the renderer that you're using works correctly, no additional setup or configuration is required to use the debug tools.
To enable the debug tools, use the function `Clay_SetDebugModeEnabled(bool enabled)`. This boolean is persistent and does not need to be set every frame.
The debug tooling by default will render as a panel to the right side of the screen, compressing your layout by its width. The default width is 400 and is currently configurable via the direct mutation of the internal variable `Clay__debugViewWidth`, however this is an internal API and is potentially subject to change.
<img width="1506" alt="Screenshot 2024-09-12 at 12 54 03 PM" src="https://github.com/user-attachments/assets/2d122658-3305-4e27-88d6-44f08c0cb4e6">
_The official Clay website with debug tooling visible_
# API # API
### Naming Conventions ### Naming Conventions
@ -1422,13 +1436,13 @@ switch (renderCommand->commandType) {
`uint32_t CLAY_ID(char *label)` `uint32_t CLAY_ID(char *label)`
Generates a `uint32_t` string hash from the provided `char *label`. Used both to generate ids when defining element macros, as well as for referencing ids later when using utility functions such as [Clay_PointerOver](#clay-pointerover) Generates a `uint32_t` string id from the provided `char *label`. Used both to generate ids when defining element macros, as well as for referencing ids later when using utility functions such as [Clay_PointerOver](#clay-pointerover)
### CLAY_IDI() ### CLAY_IDI()
`uint32_t CLAY_IDI(char *label, int index)` `uint32_t CLAY_IDI(char *label, int index)`
Generates a `uint32_t` string hash from the provided `char *label`, combined with the `int index`. Used for generating ids for sequential elements (such as in a `for` loop) without having to construct dynamic strings at runtime. Generates a `uint32_t` string id from the provided `char *label`, combined with the `int index`. Used for generating ids for sequential elements (such as in a `for` loop) without having to construct dynamic strings at runtime.
## Data Structures & Definitions ## Data Structures & Definitions

View File

@ -57,6 +57,13 @@ BorderData :: struct {
color: Color, color: Color,
} }
ElementId :: struct {
id: u32,
offset: u32,
baseId: u32,
stringId: String,
}
when ODIN_OS == .Windows { when ODIN_OS == .Windows {
EnumBackingType :: u32 EnumBackingType :: u32
} else { } else {
@ -79,12 +86,19 @@ RectangleElementConfig :: struct {
cornerRadius: CornerRadius, cornerRadius: CornerRadius,
} }
TextWrapMode :: enum EnumBackingType {
Words,
Newlines,
None,
}
TextElementConfig :: struct { TextElementConfig :: struct {
textColor: Color, textColor: Color,
fontId: u16, fontId: u16,
fontSize: u16, fontSize: u16,
letterSpacing: u16, letterSpacing: u16,
lineSpacing: u16, lineSpacing: u16,
wrapMode: TextWrapMode,
} }
ImageElementConfig :: struct { ImageElementConfig :: struct {
@ -234,15 +248,17 @@ ClayArray :: struct($type: typeid) {
foreign Clay { foreign Clay {
MinMemorySize :: proc() -> u32 --- MinMemorySize :: proc() -> u32 ---
CreateArenaWithCapacityAndMemory :: proc(capacity: u32, offset: [^]u8) -> Arena --- CreateArenaWithCapacityAndMemory :: proc(capacity: u32, offset: [^]u8) -> Arena ---
SetPointerPosition :: proc(position: Vector2) --- SetPointerState :: proc(position: Vector2, pointerDown: bool) ---
Initialize :: proc(arena: Arena) --- Initialize :: proc(arena: Arena, layoutDimensions: Dimensions) ---
UpdateScrollContainers :: proc(isPointerActive: bool, scrollDelta: Vector2, deltaTime: c.float) --- UpdateScrollContainers :: proc(isPointerActive: bool, scrollDelta: Vector2, deltaTime: c.float) ---
BeginLayout :: proc(screenWidth: c.int, screenHeight: c.int) --- SetLayoutDimensions :: proc(dimensions: Dimensions) ---
EndLayout :: proc(screenWidth: c.int, screenHeight: c.int) -> ClayArray(RenderCommand) --- BeginLayout :: proc() ---
PointerOver :: proc(id: u32) -> bool --- EndLayout :: proc() -> ClayArray(RenderCommand) ---
GetScrollContainerData :: proc(id: u32) -> ScrollContainerData --- PointerOver :: proc(id: ElementId) -> bool ---
GetScrollContainerData :: proc(id: ElementId) -> ScrollContainerData ---
SetMeasureTextFunction :: proc(measureTextFunction: proc "c" (text: ^String, config: ^TextElementConfig) -> Dimensions) --- SetMeasureTextFunction :: proc(measureTextFunction: proc "c" (text: ^String, config: ^TextElementConfig) -> Dimensions) ---
RenderCommandArray_Get :: proc(array: ^ClayArray(RenderCommand), index: i32) -> ^RenderCommand --- RenderCommandArray_Get :: proc(array: ^ClayArray(RenderCommand), index: i32) -> ^RenderCommand ---
SetDebugModeEnabled :: proc(enabled: bool) ---
} }
@(private, link_prefix = "Clay_", default_calling_convention = "c") @(private, link_prefix = "Clay_", default_calling_convention = "c")
@ -259,14 +275,14 @@ foreign _ {
@(link_prefix = "Clay_", default_calling_convention = "c", private) @(link_prefix = "Clay_", default_calling_convention = "c", private)
foreign Clay { foreign Clay {
_OpenContainerElement :: proc(id: u32, layoutConfig: ^LayoutConfig) --- _OpenContainerElement :: proc(id: ElementId, layoutConfig: ^LayoutConfig) ---
_OpenRectangleElement :: proc(id: u32, layoutConfig: ^LayoutConfig, rectangleConfig: ^RectangleElementConfig) --- _OpenRectangleElement :: proc(id: ElementId, layoutConfig: ^LayoutConfig, rectangleConfig: ^RectangleElementConfig) ---
_OpenTextElement :: proc(id: u32, text: String, textConfig: ^TextElementConfig) --- _OpenTextElement :: proc(id: ElementId, text: String, textConfig: ^TextElementConfig) ---
_OpenImageElement :: proc(id: u32, layoutConfig: ^LayoutConfig, imageConfig: ^ImageElementConfig) --- _OpenImageElement :: proc(id: ElementId, layoutConfig: ^LayoutConfig, imageConfig: ^ImageElementConfig) ---
_OpenScrollElement :: proc(id: u32, layoutConfig: ^LayoutConfig, imageConfig: ^ScrollElementConfig) -> rawptr --- _OpenScrollElement :: proc(id: ElementId, layoutConfig: ^LayoutConfig, imageConfig: ^ScrollElementConfig) ---
_OpenFloatingElement :: proc(id: u32, layoutConfig: ^LayoutConfig, imageConfig: ^FloatingElementConfig) -> rawptr --- _OpenFloatingElement :: proc(id: ElementId, layoutConfig: ^LayoutConfig, imageConfig: ^FloatingElementConfig) ---
_OpenBorderElement :: proc(id: u32, layoutConfig: ^LayoutConfig, imageConfig: ^BorderElementConfig) --- _OpenBorderElement :: proc(id: ElementId, layoutConfig: ^LayoutConfig, imageConfig: ^BorderElementConfig) ---
_OpenCustomElement :: proc(id: u32, layoutConfig: ^LayoutConfig, imageConfig: ^CustomElementConfig) --- _OpenCustomElement :: proc(id: ElementId, layoutConfig: ^LayoutConfig, imageConfig: ^CustomElementConfig) ---
_CloseElementWithChildren :: proc() --- _CloseElementWithChildren :: proc() ---
_CloseScrollElement :: proc() --- _CloseScrollElement :: proc() ---
_CloseFloatingElement :: proc() --- _CloseFloatingElement :: proc() ---
@ -278,52 +294,52 @@ foreign Clay {
_CustomElementConfigArray_Add :: proc(array: ^ClayArray(CustomElementConfig), config: CustomElementConfig) -> ^CustomElementConfig --- _CustomElementConfigArray_Add :: proc(array: ^ClayArray(CustomElementConfig), config: CustomElementConfig) -> ^CustomElementConfig ---
_ScrollElementConfigArray_Add :: proc(array: ^ClayArray(ScrollElementConfig), config: ScrollElementConfig) -> ^ScrollElementConfig --- _ScrollElementConfigArray_Add :: proc(array: ^ClayArray(ScrollElementConfig), config: ScrollElementConfig) -> ^ScrollElementConfig ---
_BorderElementConfigArray_Add :: proc(array: ^ClayArray(BorderElementConfig), config: BorderElementConfig) -> ^BorderElementConfig --- _BorderElementConfigArray_Add :: proc(array: ^ClayArray(BorderElementConfig), config: BorderElementConfig) -> ^BorderElementConfig ---
_HashString :: proc(toHash: String, index: u32) -> u32 --- _HashString :: proc(toHash: String, index: u32) -> ElementId ---
} }
@(require_results, deferred_none = _CloseElementWithChildren) @(require_results, deferred_none = _CloseElementWithChildren)
Container :: proc(id: u32, layoutConfig: ^LayoutConfig) -> bool { Container :: proc(id: ElementId, layoutConfig: ^LayoutConfig) -> bool {
_OpenContainerElement(id, layoutConfig) _OpenContainerElement(id, layoutConfig)
return true return true
} }
@(require_results, deferred_none = _CloseElementWithChildren) @(require_results, deferred_none = _CloseElementWithChildren)
Rectangle :: proc(id: u32, layoutConfig: ^LayoutConfig, rectangleConfig: ^RectangleElementConfig) -> bool { Rectangle :: proc(id: ElementId, layoutConfig: ^LayoutConfig, rectangleConfig: ^RectangleElementConfig) -> bool {
_OpenRectangleElement(id, layoutConfig, rectangleConfig) _OpenRectangleElement(id, layoutConfig, rectangleConfig)
return true return true
} }
Text :: proc(id: u32, text: string, textConfig: ^TextElementConfig) -> bool { Text :: proc(id: ElementId, text: string, textConfig: ^TextElementConfig) -> bool {
_OpenTextElement(id, MakeString(text), textConfig) _OpenTextElement(id, MakeString(text), textConfig)
return true return true
} }
@(require_results, deferred_none = _CloseElementWithChildren) @(require_results, deferred_none = _CloseElementWithChildren)
Image :: proc(id: u32, layoutConfig: ^LayoutConfig, imageConfig: ^ImageElementConfig) -> bool { Image :: proc(id: ElementId, layoutConfig: ^LayoutConfig, imageConfig: ^ImageElementConfig) -> bool {
_OpenImageElement(id, layoutConfig, imageConfig) _OpenImageElement(id, layoutConfig, imageConfig)
return true return true
} }
@(require_results, deferred_none = _CloseScrollElement) @(require_results, deferred_none = _CloseScrollElement)
Scroll :: proc(id: u32, layoutConfig: ^LayoutConfig, scrollConfig: ^ScrollElementConfig) -> bool { Scroll :: proc(id: ElementId, layoutConfig: ^LayoutConfig, scrollConfig: ^ScrollElementConfig) -> bool {
_OpenScrollElement(id, layoutConfig, scrollConfig) _OpenScrollElement(id, layoutConfig, scrollConfig)
return true return true
} }
@(require_results, deferred_none = _CloseFloatingElement) @(require_results, deferred_none = _CloseFloatingElement)
Floating :: proc(id: u32, layoutConfig: ^LayoutConfig, floatingConfig: ^FloatingElementConfig) -> bool { Floating :: proc(id: ElementId, layoutConfig: ^LayoutConfig, floatingConfig: ^FloatingElementConfig) -> bool {
_OpenFloatingElement(id, layoutConfig, floatingConfig) _OpenFloatingElement(id, layoutConfig, floatingConfig)
return true return true
} }
@(require_results, deferred_none = _CloseElementWithChildren) @(require_results, deferred_none = _CloseElementWithChildren)
Border :: proc(id: u32, layoutConfig: ^LayoutConfig, borderConfig: ^BorderElementConfig) -> bool { Border :: proc(id: ElementId, layoutConfig: ^LayoutConfig, borderConfig: ^BorderElementConfig) -> bool {
_OpenBorderElement(id, layoutConfig, borderConfig) _OpenBorderElement(id, layoutConfig, borderConfig)
return true return true
} }
@(require_results, deferred_none = _CloseElementWithChildren) @(require_results, deferred_none = _CloseElementWithChildren)
Custom :: proc(id: u32, layoutConfig: ^LayoutConfig, customConfig: ^CustomElementConfig) -> bool { Custom :: proc(id: ElementId, layoutConfig: ^LayoutConfig, customConfig: ^CustomElementConfig) -> bool {
_OpenCustomElement(id, layoutConfig, customConfig) _OpenCustomElement(id, layoutConfig, customConfig)
return true return true
} }
@ -412,6 +428,6 @@ MakeString :: proc(label: string) -> String {
return String{chars = raw_data(label), length = cast(c.int)len(label)} return String{chars = raw_data(label), length = cast(c.int)len(label)}
} }
ID :: proc(label: string, index: u32 = 0) -> u32 { ID :: proc(label: string, index: u32 = 0) -> ElementId {
return _HashString(MakeString(label), index) return _HashString(MakeString(label), index)
} }

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -15,7 +15,8 @@ checkImage3: raylib.Texture2D = {}
checkImage4: raylib.Texture2D = {} checkImage4: raylib.Texture2D = {}
checkImage5: raylib.Texture2D = {} checkImage5: raylib.Texture2D = {}
FONT_ID_TITLE_56 :: 0 FONT_ID_BODY_16 :: 0
FONT_ID_TITLE_56 :: 9
FONT_ID_TITLE_52 :: 1 FONT_ID_TITLE_52 :: 1
FONT_ID_TITLE_48 :: 2 FONT_ID_TITLE_48 :: 2
FONT_ID_TITLE_36 :: 3 FONT_ID_TITLE_36 :: 3
@ -24,7 +25,6 @@ FONT_ID_BODY_36 :: 5
FONT_ID_BODY_30 :: 6 FONT_ID_BODY_30 :: 6
FONT_ID_BODY_28 :: 7 FONT_ID_BODY_28 :: 7
FONT_ID_BODY_24 :: 8 FONT_ID_BODY_24 :: 8
FONT_ID_BODY_16 :: 9
COLOR_LIGHT :: clay.Color{244, 235, 230, 255} COLOR_LIGHT :: clay.Color{244, 235, 230, 255}
COLOR_LIGHT_HOVER :: clay.Color{224, 215, 210, 255} COLOR_LIGHT_HOVER :: clay.Color{224, 215, 210, 255}
@ -112,13 +112,15 @@ LandingPageDesktop :: proc() {
LandingPageMobile :: proc() { LandingPageMobile :: proc() {
if clay.Container( if clay.Container(
clay.ID("LandingPage1Mobile"), clay.ID("LandingPage1Mobile"),
clay.Layout({ clay.Layout(
layoutDirection = .TOP_TO_BOTTOM, {
sizing = {width = clay.SizingGrow({}), height = clay.SizingFit({min = cast(f32)windowHeight - 70})}, layoutDirection = .TOP_TO_BOTTOM,
childAlignment = {x = .CENTER, y = .CENTER}, sizing = {width = clay.SizingGrow({}), height = clay.SizingFit({min = cast(f32)windowHeight - 70})},
padding = {16, 32}, childAlignment = {x = .CENTER, y = .CENTER},
childGap = 32, padding = {16, 32},
}), childGap = 32,
},
),
) { ) {
if clay.Container(clay.ID("LeftText"), clay.Layout({sizing = {width = clay.SizingGrow({})}, layoutDirection = .TOP_TO_BOTTOM, childGap = 8})) { if clay.Container(clay.ID("LeftText"), clay.Layout({sizing = {width = clay.SizingGrow({})}, layoutDirection = .TOP_TO_BOTTOM, childGap = 8})) {
clay.Text( clay.Text(
@ -331,7 +333,7 @@ HighPerformancePageMobile :: proc(lerpValue: f32) {
} }
} }
RendererButtonActive :: proc(id: u32, index: i32, text: string) { RendererButtonActive :: proc(id: clay.ElementId, index: i32, text: string) {
if clay.Rectangle( if clay.Rectangle(
id, id,
clay.Layout({sizing = {width = clay.SizingFixed(300)}, padding = {16, 16}}), clay.Layout({sizing = {width = clay.SizingFixed(300)}, padding = {16, 16}}),
@ -341,7 +343,7 @@ RendererButtonActive :: proc(id: u32, index: i32, text: string) {
} }
} }
RendererButtonInactive :: proc(id: u32, index: u32, text: string) { RendererButtonInactive :: proc(id: clay.ElementId, index: u32, text: string) {
if clay.Border(id, clay.Layout({}), clay.BorderConfigOutsideRadius({2, COLOR_RED}, 10)) { if clay.Border(id, clay.Layout({}), clay.BorderConfigOutsideRadius({2, COLOR_RED}, 10)) {
if clay.Rectangle( if clay.Rectangle(
clay.ID("RendererButtonInactiveInner", index), clay.ID("RendererButtonInactiveInner", index),
@ -377,11 +379,7 @@ RendererPage :: proc(titleTextConfig: clay.TextElementConfig, widthSizing: clay.
clay.ID("RendererRightText"), clay.ID("RendererRightText"),
clay.Layout({sizing = {width = widthSizing}, childAlignment = {x = .CENTER}, layoutDirection = .TOP_TO_BOTTOM, childGap = 16}), clay.Layout({sizing = {width = widthSizing}, childAlignment = {x = .CENTER}, layoutDirection = .TOP_TO_BOTTOM, childGap = 16}),
) { ) {
clay.Text( clay.Text(clay.ID("RendererTextRightTitle"), "Try changing renderer!", clay.TextConfig({fontSize = 36, fontId = FONT_ID_BODY_36, textColor = COLOR_ORANGE}))
clay.ID("RendererTextRightTitle"),
"Try changing renderer!",
clay.TextConfig({fontSize = 36, fontId = FONT_ID_BODY_36, textColor = COLOR_ORANGE}),
)
if clay.Container(clay.ID("Spacer"), clay.Layout({sizing = {width = clay.SizingGrow({max = 32})}})) {} if clay.Container(clay.ID("Spacer"), clay.Layout({sizing = {width = clay.SizingGrow({max = 32})}})) {}
RendererButtonActive(clay.ID("RendererSelectButtonActive", 0), 0, "Raylib Renderer") RendererButtonActive(clay.ID("RendererSelectButtonActive", 0), 0, "Raylib Renderer")
} }
@ -405,13 +403,15 @@ RendererPageDesktop :: proc() {
RendererPageMobile :: proc() { RendererPageMobile :: proc() {
if clay.Rectangle( if clay.Rectangle(
clay.ID("RendererMobile"), clay.ID("RendererMobile"),
clay.Layout({ clay.Layout(
layoutDirection = .TOP_TO_BOTTOM, {
sizing = {clay.SizingGrow({}), clay.SizingFit({min = cast(f32)windowHeight - 50})}, layoutDirection = .TOP_TO_BOTTOM,
childAlignment = {x = .CENTER, y = .CENTER}, sizing = {clay.SizingGrow({}), clay.SizingFit({min = cast(f32)windowHeight - 50})},
padding = {x = 16, y = 32}, childAlignment = {x = .CENTER, y = .CENTER},
childGap = 32, padding = {x = 16, y = 32},
}), childGap = 32,
},
),
clay.RectangleConfig({color = COLOR_LIGHT}), clay.RectangleConfig({color = COLOR_LIGHT}),
) { ) {
RendererPage({fontSize = 48, fontId = FONT_ID_TITLE_48, textColor = COLOR_RED}, clay.SizingGrow({})) RendererPage({fontSize = 48, fontId = FONT_ID_TITLE_48, textColor = COLOR_RED}, clay.SizingGrow({}))
@ -429,7 +429,7 @@ animationLerpValue: f32 = -1.0
createLayout :: proc(lerpValue: f32) -> clay.ClayArray(clay.RenderCommand) { createLayout :: proc(lerpValue: f32) -> clay.ClayArray(clay.RenderCommand) {
mobileScreen := windowWidth < 750 mobileScreen := windowWidth < 750
clay.BeginLayout(windowWidth, windowHeight) clay.BeginLayout()
if clay.Rectangle( if clay.Rectangle(
clay.ID("OuterContainer"), clay.ID("OuterContainer"),
clay.Layout({layoutDirection = .TOP_TO_BOTTOM, sizing = {clay.SizingGrow({}), clay.SizingGrow({})}}), clay.Layout({layoutDirection = .TOP_TO_BOTTOM, sizing = {clay.SizingGrow({}), clay.SizingGrow({})}}),
@ -450,7 +450,7 @@ createLayout :: proc(lerpValue: f32) -> clay.ClayArray(clay.RenderCommand) {
clay.Text(clay.ID("LinkDocsText"), "Docs", clay.TextConfig({fontId = FONT_ID_BODY_24, fontSize = 24, textColor = {61, 26, 5, 255}})) clay.Text(clay.ID("LinkDocsText"), "Docs", clay.TextConfig({fontId = FONT_ID_BODY_24, fontSize = 24, textColor = {61, 26, 5, 255}}))
} }
} }
githubButtonId: u32 = clay.ID("HeaderButtonGithub") githubButtonId: clay.ElementId = clay.ID("HeaderButtonGithub")
if clay.Border(clay.ID("LinkGithubOuter"), clay.Layout({}), clay.BorderConfigOutsideRadius({2, COLOR_RED}, 10)) { if clay.Border(clay.ID("LinkGithubOuter"), clay.Layout({}), clay.BorderConfigOutsideRadius({2, COLOR_RED}, 10)) {
if clay.Rectangle( if clay.Rectangle(
githubButtonId, githubButtonId,
@ -494,7 +494,7 @@ createLayout :: proc(lerpValue: f32) -> clay.ClayArray(clay.RenderCommand) {
} }
} }
} }
return clay.EndLayout(windowWidth, windowHeight) return clay.EndLayout()
} }
loadFont :: proc(fontId: u16, fontSize: u16, path: cstring) { loadFont :: proc(fontId: u16, fontSize: u16, path: cstring) {
@ -510,7 +510,7 @@ main :: proc() {
memory := make([^]u8, minMemorySize) memory := make([^]u8, minMemorySize)
arena: clay.Arena = clay.CreateArenaWithCapacityAndMemory(minMemorySize, memory) arena: clay.Arena = clay.CreateArenaWithCapacityAndMemory(minMemorySize, memory)
clay.SetMeasureTextFunction(measureText) clay.SetMeasureTextFunction(measureText)
clay.Initialize(arena) clay.Initialize(arena, {cast(f32)raylib.GetScreenWidth(), cast(f32)raylib.GetScreenHeight()})
raylib.SetConfigFlags({.VSYNC_HINT, .WINDOW_RESIZABLE, .WINDOW_HIGHDPI, .MSAA_4X_HINT}) raylib.SetConfigFlags({.VSYNC_HINT, .WINDOW_RESIZABLE, .WINDOW_HIGHDPI, .MSAA_4X_HINT})
raylib.InitWindow(windowWidth, windowHeight, "Raylib Odin Example") raylib.InitWindow(windowWidth, windowHeight, "Raylib Odin Example")
@ -533,17 +533,24 @@ main :: proc() {
checkImage4 = raylib.LoadTextureFromImage(raylib.LoadImage("resources/check_4.png")) checkImage4 = raylib.LoadTextureFromImage(raylib.LoadImage("resources/check_4.png"))
checkImage5 = raylib.LoadTextureFromImage(raylib.LoadImage("resources/check_5.png")) checkImage5 = raylib.LoadTextureFromImage(raylib.LoadImage("resources/check_5.png"))
debugModeEnabled: bool = false
for !raylib.WindowShouldClose() { for !raylib.WindowShouldClose() {
defer free_all(context.temp_allocator) defer free_all(context.temp_allocator)
animationLerpValue += raylib.GetFrameTime() animationLerpValue += raylib.GetFrameTime()
if animationLerpValue > 1 { if animationLerpValue > 1 {
animationLerpValue = animationLerpValue - 2 animationLerpValue = animationLerpValue - 2
} }
windowWidth = raylib.GetScreenWidth() windowWidth = raylib.GetScreenWidth()
windowHeight = raylib.GetScreenHeight() windowHeight = raylib.GetScreenHeight()
clay.SetPointerPosition(transmute(clay.Vector2)raylib.GetMousePosition()) if (raylib.IsKeyPressed(.D)) {
debugModeEnabled = !debugModeEnabled
clay.SetDebugModeEnabled(debugModeEnabled)
}
clay.SetPointerState(transmute(clay.Vector2)raylib.GetMousePosition(), raylib.IsMouseButtonDown(raylib.MouseButton.LEFT))
clay.UpdateScrollContainers(false, transmute(clay.Vector2)raylib.GetMouseWheelMoveV(), raylib.GetFrameTime()) clay.UpdateScrollContainers(false, transmute(clay.Vector2)raylib.GetMouseWheelMoveV(), raylib.GetFrameTime())
clay.SetLayoutDimensions({cast(f32)raylib.GetScreenWidth(), cast(f32)raylib.GetScreenHeight()})
renderCommands: clay.ClayArray(clay.RenderCommand) = createLayout(animationLerpValue < 0 ? (animationLerpValue + 1) : (1 - animationLerpValue)) renderCommands: clay.ClayArray(clay.RenderCommand) = createLayout(animationLerpValue < 0 ? (animationLerpValue + 1) : (1 - animationLerpValue))
raylib.BeginDrawing() raylib.BeginDrawing()
clayRaylibRender(&renderCommands) clayRaylibRender(&renderCommands)

View File

@ -26,7 +26,7 @@ measureText :: proc "c" (text: ^clay.String, config: ^clay.TextElementConfig) ->
textHeight := cast(f32)config.fontSize textHeight := cast(f32)config.fontSize
fontToUse := raylibFonts[config.fontId].font fontToUse := raylibFonts[config.fontId].font
for i in 0..<int(text.length) { for i in 0 ..< int(text.length) {
if (text.chars[i] == '\n') { if (text.chars[i] == '\n') {
maxTextWidth = max(maxTextWidth, lineTextWidth) maxTextWidth = max(maxTextWidth, lineTextWidth)
lineTextWidth = 0 lineTextWidth = 0
@ -49,25 +49,25 @@ measureText :: proc "c" (text: ^clay.String, config: ^clay.TextElementConfig) ->
} }
clayRaylibRender :: proc(renderCommands: ^clay.ClayArray(clay.RenderCommand), allocator := context.temp_allocator) { clayRaylibRender :: proc(renderCommands: ^clay.ClayArray(clay.RenderCommand), allocator := context.temp_allocator) {
for i in 0..<int(renderCommands.length) { for i in 0 ..< int(renderCommands.length) {
renderCommand := clay.RenderCommandArray_Get(renderCommands, cast(i32)i) renderCommand := clay.RenderCommandArray_Get(renderCommands, cast(i32)i)
boundingBox := renderCommand.boundingBox boundingBox := renderCommand.boundingBox
switch (renderCommand.commandType) { switch (renderCommand.commandType) {
case clay.RenderCommandType.None: case clay.RenderCommandType.None:
{} {}
case clay.RenderCommandType.Text: case clay.RenderCommandType.Text:
// Raylib uses standard C strings so isn't compatible with cheap slices, we need to clone the string to append null terminator // Raylib uses standard C strings so isn't compatible with cheap slices, we need to clone the string to append null terminator
text := string(renderCommand.text.chars[:renderCommand.text.length]) text := string(renderCommand.text.chars[:renderCommand.text.length])
cloned := strings.clone_to_cstring(text, allocator) cloned := strings.clone_to_cstring(text, allocator)
fontToUse: raylib.Font = raylibFonts[renderCommand.config.textElementConfig.fontId].font fontToUse: raylib.Font = raylibFonts[renderCommand.config.textElementConfig.fontId].font
raylib.DrawTextEx( raylib.DrawTextEx(
fontToUse, fontToUse,
cloned, cloned,
raylib.Vector2{boundingBox.x, boundingBox.y}, raylib.Vector2{boundingBox.x, boundingBox.y},
cast(f32)renderCommand.config.textElementConfig.fontSize, cast(f32)renderCommand.config.textElementConfig.fontSize,
cast(f32)renderCommand.config.textElementConfig.letterSpacing, cast(f32)renderCommand.config.textElementConfig.letterSpacing,
clayColorToRaylibColor(renderCommand.config.textElementConfig.textColor), clayColorToRaylibColor(renderCommand.config.textElementConfig.textColor),
) )
case clay.RenderCommandType.Image: case clay.RenderCommandType.Image:
// TODO image handling // TODO image handling
imageTexture := cast(^raylib.Texture2D)renderCommand.config.imageElementConfig.imageData imageTexture := cast(^raylib.Texture2D)renderCommand.config.imageElementConfig.imageData
@ -85,20 +85,9 @@ clayRaylibRender :: proc(renderCommands: ^clay.ClayArray(clay.RenderCommand), al
config: ^clay.RectangleElementConfig = renderCommand.config.rectangleElementConfig config: ^clay.RectangleElementConfig = renderCommand.config.rectangleElementConfig
if (config.cornerRadius.topLeft > 0) { if (config.cornerRadius.topLeft > 0) {
radius: f32 = (config.cornerRadius.topLeft * 2) / min(boundingBox.width, boundingBox.height) radius: f32 = (config.cornerRadius.topLeft * 2) / min(boundingBox.width, boundingBox.height)
raylib.DrawRectangleRounded( raylib.DrawRectangleRounded(raylib.Rectangle{boundingBox.x, boundingBox.y, boundingBox.width, boundingBox.height}, radius, 8, clayColorToRaylibColor(config.color))
raylib.Rectangle{boundingBox.x, boundingBox.y, boundingBox.width, boundingBox.height},
radius,
8,
clayColorToRaylibColor(config.color),
)
} else { } else {
raylib.DrawRectangle( raylib.DrawRectangle(cast(i32)boundingBox.x, cast(i32)boundingBox.y, cast(i32)boundingBox.width, cast(i32)boundingBox.height, clayColorToRaylibColor(config.color))
cast(i32)boundingBox.x,
cast(i32)boundingBox.y,
cast(i32)boundingBox.width,
cast(i32)boundingBox.height,
clayColorToRaylibColor(config.color),
)
} }
case clay.RenderCommandType.Border: case clay.RenderCommandType.Border:
config := renderCommand.config.borderElementConfig config := renderCommand.config.borderElementConfig
@ -166,10 +155,7 @@ clayRaylibRender :: proc(renderCommands: ^clay.ClayArray(clay.RenderCommand), al
} }
if (config.cornerRadius.bottomLeft > 0) { if (config.cornerRadius.bottomLeft > 0) {
raylib.DrawRing( raylib.DrawRing(
raylib.Vector2 { raylib.Vector2{math.round(boundingBox.x + config.cornerRadius.bottomLeft), math.round(boundingBox.y + boundingBox.height - config.cornerRadius.bottomLeft)},
math.round(boundingBox.x + config.cornerRadius.bottomLeft),
math.round(boundingBox.y + boundingBox.height - config.cornerRadius.bottomLeft),
},
math.round(config.cornerRadius.bottomLeft - cast(f32)config.top.width), math.round(config.cornerRadius.bottomLeft - cast(f32)config.top.width),
config.cornerRadius.bottomLeft, config.cornerRadius.bottomLeft,
90, 90,
@ -193,7 +179,7 @@ clayRaylibRender :: proc(renderCommands: ^clay.ClayArray(clay.RenderCommand), al
) )
} }
case clay.RenderCommandType.Custom: case clay.RenderCommandType.Custom:
// Implement custom element rendering here // Implement custom element rendering here
} }
} }
} }

1275
clay.h

File diff suppressed because it is too large Load Diff

View File

@ -2,6 +2,7 @@ mkdir -p build/clay \
&& clang \ && clang \
-Os \ -Os \
-DCLAY_WASM \ -DCLAY_WASM \
-DCLAY_DEBUG \
-mbulk-memory \ -mbulk-memory \
--target=wasm32 \ --target=wasm32 \
-nostdlib \ -nostdlib \

Binary file not shown.

After

Width:  |  Height:  |  Size: 296 KiB

View File

@ -13,6 +13,7 @@
padding: 0; padding: 0;
margin: 0; margin: 0;
pointer-events: none; pointer-events: none;
background: rgb(244, 235, 230);
} }
/* Import the font using @font-face */ /* Import the font using @font-face */
@font-face { @font-face {
@ -48,7 +49,7 @@
.text { .text {
pointer-events: all; pointer-events: all;
white-space: nowrap; white-space: pre;
} }
</style> </style>
</head> </head>
@ -63,14 +64,14 @@
const CLAY_RENDER_COMMAND_TYPE_CUSTOM = 7; const CLAY_RENDER_COMMAND_TYPE_CUSTOM = 7;
const GLOBAL_FONT_SCALING_FACTOR = 0.8; const GLOBAL_FONT_SCALING_FACTOR = 0.8;
let renderCommandSize = 0; let renderCommandSize = 0;
let scratchSpaceAddress = 0; let scratchSpaceAddress = 8;
let heapSpaceAddress = 0; let heapSpaceAddress = 0;
let memoryDataView; let memoryDataView;
let textDecoder = new TextDecoder("utf-8"); let textDecoder = new TextDecoder("utf-8");
let previousFrameTime; let previousFrameTime;
let fontsById = [ let fontsById = [
'Calistoga',
'Quicksand', 'Quicksand',
'Calistoga',
'Quicksand', 'Quicksand',
'Quicksand', 'Quicksand',
'Quicksand', 'Quicksand',
@ -117,6 +118,7 @@
{ name: 'fontSize', type: 'uint16_t' }, { name: 'fontSize', type: 'uint16_t' },
{ name: 'letterSpacing', type: 'uint16_t' }, { name: 'letterSpacing', type: 'uint16_t' },
{ name: 'lineSpacing', type: 'uint16_t' }, { name: 'lineSpacing', type: 'uint16_t' },
{ name: 'wrapMode', type: 'uint32_t' },
{ name: 'disablePointerEvents', type: 'uint8_t' } { name: 'disablePointerEvents', type: 'uint8_t' }
]}; ]};
let imageConfigDefinition = { name: 'image', type: 'struct', members: [ let imageConfigDefinition = { name: 'image', type: 'struct', members: [
@ -212,6 +214,18 @@
instance.exports.Clay_CreateArenaWithCapacityAndMemory(arenaStructAddress, memorySize, arenaMemoryAddress); instance.exports.Clay_CreateArenaWithCapacityAndMemory(arenaStructAddress, memorySize, arenaMemoryAddress);
} }
async function init() { async function init() {
await new Promise((resolve, reject) => {
// repeatedly poll check
const poller = setInterval(async () => {
await Promise.all(fontsById.map(f => document.fonts.load(`12px "${f}"`)));
console.log(`12px "${fontsById[0]}"`);
if (document.fonts.check(`12px "${fontsById[0]}"`)) {
clearInterval(poller);
resolve(true);
}
}, 10);
setTimeout(() => {clearInterval(poller); resolve()}, 1000);
});
window.htmlRoot = document.body.appendChild(document.createElement('div')); window.htmlRoot = document.body.appendChild(document.createElement('div'));
window.canvasRoot = document.body.appendChild(document.createElement('canvas')); window.canvasRoot = document.body.appendChild(document.createElement('canvas'));
window.canvasContext = window.canvasRoot.getContext("2d"); window.canvasContext = window.canvasRoot.getContext("2d");
@ -224,7 +238,7 @@
window.arrowKeyUpPressedThisFrame = false; window.arrowKeyUpPressedThisFrame = false;
let zeroTimeout = null; let zeroTimeout = null;
addEventListener("wheel", (event) => { addEventListener("wheel", (event) => {
window.mouseWheelXThisFrame = event.deltaX * 0.1; window.mouseWheelXThisFrame = event.deltaX * -0.1;
window.mouseWheelYThisFrame = event.deltaY * -0.1; window.mouseWheelYThisFrame = event.deltaY * -0.1;
clearTimeout(zeroTimeout); clearTimeout(zeroTimeout);
zeroTimeout = setTimeout(() => { zeroTimeout = setTimeout(() => {
@ -270,6 +284,9 @@
if (event.key === "ArrowUp") { if (event.key === "ArrowUp") {
window.arrowKeyUpPressedThisFrame = true; window.arrowKeyUpPressedThisFrame = true;
} }
if (event.key === "d") {
window.dKeyPressedThisFrame = true;
}
}); });
const importObject = { const importObject = {
@ -293,7 +310,9 @@
let arenaAddress = scratchSpaceAddress; let arenaAddress = scratchSpaceAddress;
window.instance = instance; window.instance = instance;
createMainArena(arenaAddress, heapSpaceAddress); createMainArena(arenaAddress, heapSpaceAddress);
instance.exports.Clay_Initialize(arenaAddress); 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);
renderCommandSize = getStructTotalSize(renderCommandDefinition); renderCommandSize = getStructTotalSize(renderCommandDefinition);
renderLoop(); renderLoop();
} }
@ -326,7 +345,9 @@
} }
break; break;
} }
case CLAY_RENDER_COMMAND_TYPE_IMAGE: { elementType = 'img'; break; } case CLAY_RENDER_COMMAND_TYPE_IMAGE: {
elementType = 'img'; break;
}
default: break; default: break;
} }
element = document.createElement(elementType); element = document.createElement(elementType);
@ -349,7 +370,7 @@
if (parentElement.nextElementIndex === 0) { if (parentElement.nextElementIndex === 0) {
parentElement.element.insertAdjacentElement('afterbegin', element); parentElement.element.insertAdjacentElement('afterbegin', element);
} else { } else {
parentElement.element.childNodes[parentElement.nextElementIndex - 1].insertAdjacentElement('afterend', element); parentElement.element.childNodes[Math.min(parentElement.nextElementIndex - 1, parentElement.element.childNodes.length - 1)].insertAdjacentElement('afterend', element);
} }
} }
@ -375,7 +396,8 @@
let config = readStructAtAddress(renderCommand.config.value, rectangleConfigDefinition); let config = readStructAtAddress(renderCommand.config.value, rectangleConfigDefinition);
let configMemory = new Uint8Array(memoryDataView.buffer.slice(renderCommand.config.value, renderCommand.config.value + config.__size)); 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; 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.mouseDownThisFrame || window.touchDown) && instance.exports.Clay_PointerOver(renderCommand.id.value)) { memoryDataView.setUint32(0, renderCommand.id.value, true);
if (linkContents.length > 0 && (window.mouseDownThisFrame || window.touchDown) && instance.exports.Clay_PointerOver(0)) {
window.location.href = linkContents; window.location.href = linkContents;
} }
if (!dirty && !MemoryIsDifferent(configMemory, elementData.previousMemoryConfig, config.__size)) { if (!dirty && !MemoryIsDifferent(configMemory, elementData.previousMemoryConfig, config.__size)) {
@ -504,8 +526,8 @@
let arrayOffset = memoryDataView.getUint32(scratchSpaceAddress + 8, true); let arrayOffset = memoryDataView.getUint32(scratchSpaceAddress + 8, true);
window.canvasRoot.width = window.innerWidth * window.devicePixelRatio; window.canvasRoot.width = window.innerWidth * window.devicePixelRatio;
window.canvasRoot.height = window.innerHeight * window.devicePixelRatio; window.canvasRoot.height = window.innerHeight * window.devicePixelRatio;
window.canvasRoot.style.width = window.innerWidth; window.canvasRoot.style.width = window.innerWidth + 'px';
window.canvasRoot.style.height = window.innerHeight; window.canvasRoot.style.height = window.innerHeight + 'px';
let ctx = window.canvasContext; let ctx = window.canvasContext;
let scale = window.devicePixelRatio; let scale = window.devicePixelRatio;
for (let i = 0; i < length; i++, arrayOffset += renderCommandSize) { for (let i = 0; i < length; i++, arrayOffset += renderCommandSize) {
@ -530,7 +552,8 @@
ctx.closePath(); ctx.closePath();
// Handle link clicks // 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; 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.mouseDownThisFrame || window.touchDown) && instance.exports.Clay_PointerOver(renderCommand.id.value)) { memoryDataView.setUint32(0, renderCommand.id.value, true);
if (linkContents.length > 0 && (window.mouseDownThisFrame || window.touchDown) && instance.exports.Clay_PointerOver(0)) {
window.location.href = linkContents; window.location.href = linkContents;
} }
break; break;
@ -643,9 +666,11 @@
break; break;
} }
case (CLAY_RENDER_COMMAND_TYPE_SCISSOR_START): { case (CLAY_RENDER_COMMAND_TYPE_SCISSOR_START): {
window.canvasContext.save();
window.canvasContext.beginPath(); window.canvasContext.beginPath();
window.canvasContext.rect(boundingBox.x.value * scale, boundingBox.y.value * scale, boundingBox.width.value * scale, boundingBox.height.value * scale); window.canvasContext.rect(boundingBox.x.value * scale, boundingBox.y.value * scale, boundingBox.width.value * scale, boundingBox.height.value * scale);
window.canvasContext.clip(); window.canvasContext.clip();
window.canvasContext.closePath();
break; break;
} }
case (CLAY_RENDER_COMMAND_TYPE_SCISSOR_END): { case (CLAY_RENDER_COMMAND_TYPE_SCISSOR_END): {
@ -676,7 +701,7 @@
const elapsed = currentTime - previousFrameTime; const elapsed = currentTime - previousFrameTime;
previousFrameTime = currentTime; previousFrameTime = currentTime;
let activeRendererIndex = memoryDataView.getUint32(instance.exports.ACTIVE_RENDERER_INDEX.value, true); let activeRendererIndex = memoryDataView.getUint32(instance.exports.ACTIVE_RENDERER_INDEX.value, true);
instance.exports.UpdateDrawFrame(scratchSpaceAddress, window.innerWidth, window.innerHeight, window.mouseWheelXThisFrame, window.mouseWheelYThisFrame, window.mousePositionXThisFrame, window.mousePositionYThisFrame, window.touchDown, window.mouseDown, window.arrowKeyDownPressedThisFrame, window.arrowKeyUpPressedThisFrame, elapsed / 1000); instance.exports.UpdateDrawFrame(scratchSpaceAddress, window.innerWidth, window.innerHeight, window.mouseWheelXThisFrame, window.mouseWheelYThisFrame, window.mousePositionXThisFrame, window.mousePositionYThisFrame, window.touchDown, window.mouseDown, window.arrowKeyDownPressedThisFrame, window.arrowKeyUpPressedThisFrame, window.dKeyPressedThisFrame, elapsed / 1000);
let rendererChanged = activeRendererIndex !== window.previousActiveRendererIndex; let rendererChanged = activeRendererIndex !== window.previousActiveRendererIndex;
switch (activeRendererIndex) { switch (activeRendererIndex) {
case 0: { case 0: {
@ -701,6 +726,7 @@
window.mouseDownThisFrame = false; window.mouseDownThisFrame = false;
window.arrowKeyUpPressedThisFrame = false; window.arrowKeyUpPressedThisFrame = false;
window.arrowKeyDownPressedThisFrame = false; window.arrowKeyDownPressedThisFrame = false;
window.dKeyPressedThisFrame = false;
} }
init(); init();
</script> </script>

View File

@ -7,9 +7,9 @@ double windowWidth = 1024, windowHeight = 768;
float modelPageOneZRotation = 0; float modelPageOneZRotation = 0;
int ACTIVE_RENDERER_INDEX = 0; int ACTIVE_RENDERER_INDEX = 0;
const uint32_t FONT_ID_TITLE_56 = 0; const uint32_t FONT_ID_BODY_16 = 0;
const uint32_t FONT_ID_BODY_24 = 1; const uint32_t FONT_ID_TITLE_56 = 1;
const uint32_t FONT_ID_BODY_16 = 2; const uint32_t FONT_ID_BODY_24 = 2;
const uint32_t FONT_ID_BODY_36 = 3; const uint32_t FONT_ID_BODY_36 = 3;
const uint32_t FONT_ID_TITLE_36 = 4; const uint32_t FONT_ID_TITLE_36 = 4;
const uint32_t FONT_ID_MONOSPACE_24 = 5; const uint32_t FONT_ID_MONOSPACE_24 = 5;
@ -18,7 +18,6 @@ const Clay_Color COLOR_LIGHT = (Clay_Color) {244, 235, 230, 255};
Clay_Color COLOR_LIGHT_HOVER = (Clay_Color) {224, 215, 210, 255}; Clay_Color COLOR_LIGHT_HOVER = (Clay_Color) {224, 215, 210, 255};
Clay_Color COLOR_BUTTON_HOVER = (Clay_Color) {238, 227, 225, 255}; Clay_Color COLOR_BUTTON_HOVER = (Clay_Color) {238, 227, 225, 255};
Clay_Color COLOR_BROWN = (Clay_Color) {61, 26, 5, 255}; Clay_Color COLOR_BROWN = (Clay_Color) {61, 26, 5, 255};
//Clay_Color COLOR_RED = (Clay_Color) {252, 67, 27, 255};
Clay_Color COLOR_RED = (Clay_Color) {168, 66, 28, 255}; Clay_Color COLOR_RED = (Clay_Color) {168, 66, 28, 255};
Clay_Color COLOR_RED_HOVER = (Clay_Color) {148, 46, 8, 255}; Clay_Color COLOR_RED_HOVER = (Clay_Color) {148, 46, 8, 255};
Clay_Color COLOR_ORANGE = (Clay_Color) {225, 138, 50, 255}; Clay_Color COLOR_ORANGE = (Clay_Color) {225, 138, 50, 255};
@ -56,7 +55,7 @@ void LandingPageDesktop() {
CLAY_BORDER_CONTAINER(CLAY_ID("LandingPage1"), CLAY_LAYOUT(.sizing = { CLAY_SIZING_GROW(), CLAY_SIZING_GROW() }, .childAlignment = {.y = CLAY_ALIGN_Y_CENTER}, .padding = { 32, 32 }, .childGap = 32), CLAY_BORDER_CONFIG(.left = { 2, COLOR_RED }, .right = { 2, COLOR_RED }), { CLAY_BORDER_CONTAINER(CLAY_ID("LandingPage1"), CLAY_LAYOUT(.sizing = { CLAY_SIZING_GROW(), CLAY_SIZING_GROW() }, .childAlignment = {.y = CLAY_ALIGN_Y_CENTER}, .padding = { 32, 32 }, .childGap = 32), CLAY_BORDER_CONFIG(.left = { 2, COLOR_RED }, .right = { 2, COLOR_RED }), {
CLAY_CONTAINER(CLAY_ID("LeftText"), CLAY_LAYOUT(.sizing = { .width = CLAY_SIZING_PERCENT(0.55f) }, .layoutDirection = CLAY_TOP_TO_BOTTOM, .childGap = 8), { CLAY_CONTAINER(CLAY_ID("LeftText"), CLAY_LAYOUT(.sizing = { .width = CLAY_SIZING_PERCENT(0.55f) }, .layoutDirection = CLAY_TOP_TO_BOTTOM, .childGap = 8), {
CLAY_TEXT(CLAY_ID("LeftTextTitle"), CLAY_STRING("Clay is a flex-box style UI auto layout library in C, with declarative syntax and microsecond performance."), CLAY_TEXT_CONFIG(.fontSize = 56, .fontId = FONT_ID_TITLE_56, .textColor = COLOR_RED)); CLAY_TEXT(CLAY_ID("LeftTextTitle"), CLAY_STRING("Clay is a flex-box style UI auto layout library in C, with declarative syntax and microsecond performance."), CLAY_TEXT_CONFIG(.fontSize = 56, .fontId = FONT_ID_TITLE_56, .textColor = COLOR_RED));
CLAY_CONTAINER(CLAY_ID("Spacer"), CLAY_LAYOUT(.sizing = { .width = CLAY_SIZING_GROW(), .height = CLAY_SIZING_FIXED(32) }), {}); CLAY_CONTAINER(CLAY_ID("LandingPageSpacer"), CLAY_LAYOUT(.sizing = { .width = CLAY_SIZING_GROW(), .height = CLAY_SIZING_FIXED(32) }), {});
CLAY_TEXT(CLAY_ID("LeftTextTagline"), CLAY_STRING("Clay is laying out this webpage right now!"), CLAY_TEXT_CONFIG(.fontSize = 36, .fontId = FONT_ID_TITLE_36, .textColor = COLOR_ORANGE)); CLAY_TEXT(CLAY_ID("LeftTextTagline"), CLAY_STRING("Clay is laying out this webpage right now!"), CLAY_TEXT_CONFIG(.fontSize = 36, .fontId = FONT_ID_TITLE_36, .textColor = COLOR_ORANGE));
}); });
CLAY_CONTAINER(CLAY_ID("HeroImageOuter"), CLAY_LAYOUT(.layoutDirection = CLAY_TOP_TO_BOTTOM, .sizing = { .width = CLAY_SIZING_PERCENT(0.45f) }, .childAlignment = { CLAY_ALIGN_X_CENTER }, .childGap = 16), { CLAY_CONTAINER(CLAY_ID("HeroImageOuter"), CLAY_LAYOUT(.layoutDirection = CLAY_TOP_TO_BOTTOM, .sizing = { .width = CLAY_SIZING_PERCENT(0.45f) }, .childAlignment = { CLAY_ALIGN_X_CENTER }, .childGap = 16), {
@ -74,7 +73,7 @@ void LandingPageMobile() {
CLAY_CONTAINER(CLAY_ID("LandingPage1Mobile"), CLAY_LAYOUT(.layoutDirection = CLAY_TOP_TO_BOTTOM, .sizing = { .width = CLAY_SIZING_GROW(), .height = CLAY_SIZING_FIT(.min = windowHeight - 70) }, .childAlignment = {CLAY_ALIGN_X_CENTER, .y = CLAY_ALIGN_Y_CENTER}, .padding = { 16, 32 }, .childGap = 32), { CLAY_CONTAINER(CLAY_ID("LandingPage1Mobile"), CLAY_LAYOUT(.layoutDirection = CLAY_TOP_TO_BOTTOM, .sizing = { .width = CLAY_SIZING_GROW(), .height = CLAY_SIZING_FIT(.min = windowHeight - 70) }, .childAlignment = {CLAY_ALIGN_X_CENTER, .y = CLAY_ALIGN_Y_CENTER}, .padding = { 16, 32 }, .childGap = 32), {
CLAY_CONTAINER(CLAY_ID("LeftText"), CLAY_LAYOUT(.sizing = { .width = CLAY_SIZING_GROW() }, .layoutDirection = CLAY_TOP_TO_BOTTOM, .childGap = 8), { CLAY_CONTAINER(CLAY_ID("LeftText"), CLAY_LAYOUT(.sizing = { .width = CLAY_SIZING_GROW() }, .layoutDirection = CLAY_TOP_TO_BOTTOM, .childGap = 8), {
CLAY_TEXT(CLAY_ID("LeftTextTitle"), CLAY_STRING("Clay is a flex-box style UI auto layout library in C, with declarative syntax and microsecond performance."), CLAY_TEXT_CONFIG(.fontSize = 48, .fontId = FONT_ID_TITLE_56, .textColor = COLOR_RED)); CLAY_TEXT(CLAY_ID("LeftTextTitle"), CLAY_STRING("Clay is a flex-box style UI auto layout library in C, with declarative syntax and microsecond performance."), CLAY_TEXT_CONFIG(.fontSize = 48, .fontId = FONT_ID_TITLE_56, .textColor = COLOR_RED));
CLAY_CONTAINER(CLAY_ID("Spacer"), CLAY_LAYOUT(.sizing = { .width = CLAY_SIZING_GROW(), .height = CLAY_SIZING_FIXED(32) }), {}); CLAY_CONTAINER(CLAY_ID("LandingPageSpacer"), CLAY_LAYOUT(.sizing = { .width = CLAY_SIZING_GROW(), .height = CLAY_SIZING_FIXED(32) }), {});
CLAY_TEXT(CLAY_ID("LeftTextTagline"), CLAY_STRING("Clay is laying out this webpage right now!"), CLAY_TEXT_CONFIG(.fontSize = 32, .fontId = FONT_ID_TITLE_36, .textColor = COLOR_ORANGE)); CLAY_TEXT(CLAY_ID("LeftTextTagline"), CLAY_STRING("Clay is laying out this webpage right now!"), CLAY_TEXT_CONFIG(.fontSize = 32, .fontId = FONT_ID_TITLE_36, .textColor = COLOR_ORANGE));
}); });
CLAY_CONTAINER(CLAY_ID("HeroImageOuter"), CLAY_LAYOUT(.layoutDirection = CLAY_TOP_TO_BOTTOM, .sizing = { .width = CLAY_SIZING_GROW() }, .childAlignment = { CLAY_ALIGN_X_CENTER }, .childGap = 16), { CLAY_CONTAINER(CLAY_ID("HeroImageOuter"), CLAY_LAYOUT(.layoutDirection = CLAY_TOP_TO_BOTTOM, .sizing = { .width = CLAY_SIZING_GROW() }, .childAlignment = { CLAY_ALIGN_X_CENTER }, .childGap = 16), {
@ -136,7 +135,7 @@ void DeclarativeSyntaxPageDesktop() {
CLAY_TEXT(CLAY_ID("SyntaxPageTextSubTitle3"), 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_TEXT(CLAY_ID("SyntaxPageTextSubTitle3"), 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_CONTAINER(CLAY_ID("SyntaxPageRightImage"), CLAY_LAYOUT(.sizing = { CLAY_SIZING_PERCENT(0.50) }, .childAlignment = {.x = CLAY_ALIGN_X_CENTER}), { CLAY_CONTAINER(CLAY_ID("SyntaxPageRightImage"), CLAY_LAYOUT(.sizing = { CLAY_SIZING_PERCENT(0.50) }, .childAlignment = {.x = CLAY_ALIGN_X_CENTER}), {
CLAY_IMAGE(CLAY_ID("SyntaxPageRightImage"), CLAY_LAYOUT(.sizing = { CLAY_SIZING_GROW(.max = 568) }), CLAY_IMAGE_CONFIG(.sourceDimensions = {1136, 1194}, .sourceURL = CLAY_STRING("/clay/images/declarative.png")), {}); CLAY_IMAGE(CLAY_ID("SyntaxPageRightImageInner"), CLAY_LAYOUT(.sizing = { CLAY_SIZING_GROW(.max = 568) }), CLAY_IMAGE_CONFIG(.sourceDimensions = {1136, 1194}, .sourceURL = CLAY_STRING("/clay/images/declarative.png")), {});
}); });
}); });
}); });
@ -152,7 +151,7 @@ void DeclarativeSyntaxPageMobile() {
CLAY_TEXT(CLAY_ID("SyntaxPageTextSubTitle3"), 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_TEXT(CLAY_ID("SyntaxPageTextSubTitle3"), 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_CONTAINER(CLAY_ID("SyntaxPageRightImage"), CLAY_LAYOUT(.sizing = { CLAY_SIZING_GROW() }, .childAlignment = {.x = CLAY_ALIGN_X_CENTER}), { CLAY_CONTAINER(CLAY_ID("SyntaxPageRightImage"), CLAY_LAYOUT(.sizing = { CLAY_SIZING_GROW() }, .childAlignment = {.x = CLAY_ALIGN_X_CENTER}), {
CLAY_IMAGE(CLAY_ID("SyntaxPageRightImage"), CLAY_LAYOUT(.sizing = { CLAY_SIZING_GROW(.max = 568) }), CLAY_IMAGE_CONFIG(.sourceDimensions = {1136, 1194}, .sourceURL = CLAY_STRING("/clay/images/declarative.png")), {}); CLAY_IMAGE(CLAY_ID("SyntaxPageRightImageInner"), CLAY_LAYOUT(.sizing = { CLAY_SIZING_GROW(.max = 568) }), CLAY_IMAGE_CONFIG(.sourceDimensions = {1136, 1194}, .sourceURL = CLAY_STRING("/clay/images/declarative.png")), {});
}); });
}); });
} }
@ -172,7 +171,7 @@ void HighPerformancePageDesktop(float lerpValue) {
CLAY_RECTANGLE(CLAY_ID("PerformanceDesktop"), CLAY_LAYOUT(.sizing = { CLAY_SIZING_GROW(), CLAY_SIZING_FIT(.min = windowHeight - 50) }, .childAlignment = {0, CLAY_ALIGN_Y_CENTER}, .padding = {.x = 82, 32}, .childGap = 64), CLAY_RECTANGLE_CONFIG(.color = COLOR_RED), { CLAY_RECTANGLE(CLAY_ID("PerformanceDesktop"), CLAY_LAYOUT(.sizing = { CLAY_SIZING_GROW(), CLAY_SIZING_FIT(.min = windowHeight - 50) }, .childAlignment = {0, CLAY_ALIGN_Y_CENTER}, .padding = {.x = 82, 32}, .childGap = 64), CLAY_RECTANGLE_CONFIG(.color = COLOR_RED), {
CLAY_CONTAINER(CLAY_ID("PerformanceLeftText"), CLAY_LAYOUT(.sizing = { CLAY_SIZING_PERCENT(0.5) }, .layoutDirection = CLAY_TOP_TO_BOTTOM, .childGap = 8), { CLAY_CONTAINER(CLAY_ID("PerformanceLeftText"), CLAY_LAYOUT(.sizing = { CLAY_SIZING_PERCENT(0.5) }, .layoutDirection = CLAY_TOP_TO_BOTTOM, .childGap = 8), {
CLAY_TEXT(CLAY_ID("PerformanceTextTitle"), CLAY_STRING("High Performance"), CLAY_TEXT_CONFIG(.fontSize = 52, .fontId = FONT_ID_TITLE_56, .textColor = COLOR_LIGHT)); CLAY_TEXT(CLAY_ID("PerformanceTextTitle"), CLAY_STRING("High Performance"), CLAY_TEXT_CONFIG(.fontSize = 52, .fontId = FONT_ID_TITLE_56, .textColor = COLOR_LIGHT));
CLAY_CONTAINER(CLAY_ID("SyntaxSpacer"), CLAY_LAYOUT(.sizing = { CLAY_SIZING_GROW(.max = 16) }), {}); CLAY_CONTAINER(CLAY_ID("PerformanceSpacer"), CLAY_LAYOUT(.sizing = { CLAY_SIZING_GROW(.max = 16) }), {});
CLAY_TEXT(CLAY_IDI("PerformanceTextSubTitle", 1), CLAY_STRING("Fast enough to recompute your entire UI every frame."), CLAY_TEXT_CONFIG(.fontSize = 28, .fontId = FONT_ID_BODY_36, .textColor = COLOR_LIGHT)); CLAY_TEXT(CLAY_IDI("PerformanceTextSubTitle", 1), CLAY_STRING("Fast enough to recompute your entire UI every frame."), CLAY_TEXT_CONFIG(.fontSize = 28, .fontId = FONT_ID_BODY_36, .textColor = COLOR_LIGHT));
CLAY_TEXT(CLAY_IDI("PerformanceTextSubTitle", 2), CLAY_STRING("Small memory footprint (3.5mb default) with static allocation & reuse. No malloc / free."), CLAY_TEXT_CONFIG(.fontSize = 28, .fontId = FONT_ID_BODY_36, .textColor = COLOR_LIGHT)); CLAY_TEXT(CLAY_IDI("PerformanceTextSubTitle", 2), CLAY_STRING("Small memory footprint (3.5mb default) with static allocation & reuse. No malloc / free."), CLAY_TEXT_CONFIG(.fontSize = 28, .fontId = FONT_ID_BODY_36, .textColor = COLOR_LIGHT));
CLAY_TEXT(CLAY_IDI("PerformanceTextSubTitle", 3), CLAY_STRING("Simplify animations and reactive UI design by avoiding the standard performance hacks."), CLAY_TEXT_CONFIG(.fontSize = 28, .fontId = FONT_ID_BODY_36, .textColor = COLOR_LIGHT)); CLAY_TEXT(CLAY_IDI("PerformanceTextSubTitle", 3), CLAY_STRING("Simplify animations and reactive UI design by avoiding the standard performance hacks."), CLAY_TEXT_CONFIG(.fontSize = 28, .fontId = FONT_ID_BODY_36, .textColor = COLOR_LIGHT));
@ -194,7 +193,7 @@ void HighPerformancePageMobile(float lerpValue) {
CLAY_RECTANGLE(CLAY_ID("PerformanceMobile"), CLAY_LAYOUT(.layoutDirection = CLAY_TOP_TO_BOTTOM, .sizing = { CLAY_SIZING_GROW(), CLAY_SIZING_FIT(.min = windowHeight - 50) }, .childAlignment = {CLAY_ALIGN_X_CENTER, CLAY_ALIGN_Y_CENTER}, .padding = {.x = 16, 32}, .childGap = 32), CLAY_RECTANGLE_CONFIG(.color = COLOR_RED), { CLAY_RECTANGLE(CLAY_ID("PerformanceMobile"), CLAY_LAYOUT(.layoutDirection = CLAY_TOP_TO_BOTTOM, .sizing = { CLAY_SIZING_GROW(), CLAY_SIZING_FIT(.min = windowHeight - 50) }, .childAlignment = {CLAY_ALIGN_X_CENTER, CLAY_ALIGN_Y_CENTER}, .padding = {.x = 16, 32}, .childGap = 32), CLAY_RECTANGLE_CONFIG(.color = COLOR_RED), {
CLAY_CONTAINER(CLAY_ID("PerformanceLeftText"), CLAY_LAYOUT(.sizing = { CLAY_SIZING_GROW() }, .layoutDirection = CLAY_TOP_TO_BOTTOM, .childGap = 8), { CLAY_CONTAINER(CLAY_ID("PerformanceLeftText"), CLAY_LAYOUT(.sizing = { CLAY_SIZING_GROW() }, .layoutDirection = CLAY_TOP_TO_BOTTOM, .childGap = 8), {
CLAY_TEXT(CLAY_ID("PerformanceTextTitle"), CLAY_STRING("High Performance"), CLAY_TEXT_CONFIG(.fontSize = 48, .fontId = FONT_ID_TITLE_56, .textColor = COLOR_LIGHT)); CLAY_TEXT(CLAY_ID("PerformanceTextTitle"), CLAY_STRING("High Performance"), CLAY_TEXT_CONFIG(.fontSize = 48, .fontId = FONT_ID_TITLE_56, .textColor = COLOR_LIGHT));
CLAY_CONTAINER(CLAY_ID("SyntaxSpacer"), CLAY_LAYOUT(.sizing = { CLAY_SIZING_GROW(.max = 16) }), {}); CLAY_CONTAINER(CLAY_ID("PerformanceSpacer"), CLAY_LAYOUT(.sizing = { CLAY_SIZING_GROW(.max = 16) }), {});
CLAY_TEXT(CLAY_IDI("PerformanceTextSubTitle", 1), CLAY_STRING("Fast enough to recompute your entire UI every frame."), CLAY_TEXT_CONFIG(.fontSize = 28, .fontId = FONT_ID_BODY_36, .textColor = COLOR_LIGHT)); CLAY_TEXT(CLAY_IDI("PerformanceTextSubTitle", 1), CLAY_STRING("Fast enough to recompute your entire UI every frame."), CLAY_TEXT_CONFIG(.fontSize = 28, .fontId = FONT_ID_BODY_36, .textColor = COLOR_LIGHT));
CLAY_TEXT(CLAY_IDI("PerformanceTextSubTitle", 2), CLAY_STRING("Small memory footprint (3.5mb default) with static allocation & reuse. No malloc / free."), CLAY_TEXT_CONFIG(.fontSize = 28, .fontId = FONT_ID_BODY_36, .textColor = COLOR_LIGHT)); CLAY_TEXT(CLAY_IDI("PerformanceTextSubTitle", 2), CLAY_STRING("Small memory footprint (3.5mb default) with static allocation & reuse. No malloc / free."), CLAY_TEXT_CONFIG(.fontSize = 28, .fontId = FONT_ID_BODY_36, .textColor = COLOR_LIGHT));
CLAY_TEXT(CLAY_IDI("PerformanceTextSubTitle", 3), CLAY_STRING("Simplify animations and reactive UI design by avoiding the standard performance hacks."), CLAY_TEXT_CONFIG(.fontSize = 28, .fontId = FONT_ID_BODY_36, .textColor = COLOR_LIGHT)); CLAY_TEXT(CLAY_IDI("PerformanceTextSubTitle", 3), CLAY_STRING("Simplify animations and reactive UI design by avoiding the standard performance hacks."), CLAY_TEXT_CONFIG(.fontSize = 28, .fontId = FONT_ID_BODY_36, .textColor = COLOR_LIGHT));
@ -212,13 +211,13 @@ void HighPerformancePageMobile(float lerpValue) {
}); });
} }
void RendererButtonActive(uint32_t id, int index, Clay_String text) { void RendererButtonActive(Clay_ElementId id, int index, Clay_String text) {
CLAY_RECTANGLE(id, CLAY_LAYOUT(.sizing = {CLAY_SIZING_FIXED(300) }, .padding = {16, 16}), CLAY_RECTANGLE_CONFIG(.color = Clay_PointerOver(id) ? COLOR_RED_HOVER : COLOR_RED, .cornerRadius = CLAY_CORNER_RADIUS(10)), { CLAY_RECTANGLE(id, CLAY_LAYOUT(.sizing = {CLAY_SIZING_FIXED(300) }, .padding = {16, 16}), CLAY_RECTANGLE_CONFIG(.color = Clay_PointerOver(id) ? COLOR_RED_HOVER : COLOR_RED, .cornerRadius = CLAY_CORNER_RADIUS(10)), {
CLAY_TEXT(CLAY_ID("RendererButtonActiveText"), text, CLAY_TEXT_CONFIG(.disablePointerEvents = true, .fontSize = 28, .fontId = FONT_ID_BODY_36, .textColor = COLOR_LIGHT)); CLAY_TEXT(CLAY_ID("RendererButtonActiveText"), text, CLAY_TEXT_CONFIG(.disablePointerEvents = true, .fontSize = 28, .fontId = FONT_ID_BODY_36, .textColor = COLOR_LIGHT));
}); });
} }
void RendererButtonInactive(uint32_t id, int index, Clay_String text) { void RendererButtonInactive(Clay_ElementId id, int index, Clay_String text) {
CLAY_BORDER_CONTAINER(id, CLAY_LAYOUT(), CLAY_BORDER_CONFIG_OUTSIDE_RADIUS(2, COLOR_RED, 10), { CLAY_BORDER_CONTAINER(id, CLAY_LAYOUT(), CLAY_BORDER_CONFIG_OUTSIDE_RADIUS(2, COLOR_RED, 10), {
CLAY_RECTANGLE(CLAY_IDI("RendererButtonInactiveInner", index), CLAY_LAYOUT(.sizing = {CLAY_SIZING_FIXED(300) }, .padding = {16, 16}), CLAY_RECTANGLE_CONFIG(.color = Clay_PointerOver(id) ? COLOR_LIGHT_HOVER : COLOR_LIGHT, .cornerRadius = CLAY_CORNER_RADIUS(10), .cursorPointer = true), { CLAY_RECTANGLE(CLAY_IDI("RendererButtonInactiveInner", index), CLAY_LAYOUT(.sizing = {CLAY_SIZING_FIXED(300) }, .padding = {16, 16}), CLAY_RECTANGLE_CONFIG(.color = Clay_PointerOver(id) ? COLOR_LIGHT_HOVER : COLOR_LIGHT, .cornerRadius = CLAY_CORNER_RADIUS(10), .cursorPointer = true), {
CLAY_TEXT(CLAY_IDI("RendererButtonInactiveText", index), text, CLAY_TEXT_CONFIG(.disablePointerEvents = true, .fontSize = 28, .fontId = FONT_ID_BODY_36, .textColor = COLOR_RED)); CLAY_TEXT(CLAY_IDI("RendererButtonInactiveText", index), text, CLAY_TEXT_CONFIG(.disablePointerEvents = true, .fontSize = 28, .fontId = FONT_ID_BODY_36, .textColor = COLOR_RED));
@ -231,14 +230,14 @@ void RendererPageDesktop() {
CLAY_BORDER_CONTAINER(CLAY_ID("RendererPage"), CLAY_LAYOUT(.sizing = { CLAY_SIZING_GROW(), CLAY_SIZING_GROW() }, .childAlignment = { 0, CLAY_ALIGN_Y_CENTER }, .padding = { 32, 32 }, .childGap = 32), CLAY_BORDER_CONFIG(.left = { 2, COLOR_RED }, .right = { 2, COLOR_RED }), { CLAY_BORDER_CONTAINER(CLAY_ID("RendererPage"), CLAY_LAYOUT(.sizing = { CLAY_SIZING_GROW(), CLAY_SIZING_GROW() }, .childAlignment = { 0, CLAY_ALIGN_Y_CENTER }, .padding = { 32, 32 }, .childGap = 32), CLAY_BORDER_CONFIG(.left = { 2, COLOR_RED }, .right = { 2, COLOR_RED }), {
CLAY_CONTAINER(CLAY_ID("RendererLeftText"), CLAY_LAYOUT(.sizing = { CLAY_SIZING_PERCENT(0.5) }, .layoutDirection = CLAY_TOP_TO_BOTTOM, .childGap = 8), { CLAY_CONTAINER(CLAY_ID("RendererLeftText"), CLAY_LAYOUT(.sizing = { CLAY_SIZING_PERCENT(0.5) }, .layoutDirection = CLAY_TOP_TO_BOTTOM, .childGap = 8), {
CLAY_TEXT(CLAY_ID("RendererTextTitle"), CLAY_STRING("Renderer & Platform Agnostic"), CLAY_TEXT_CONFIG(.fontSize = 52, .fontId = FONT_ID_TITLE_56, .textColor = COLOR_RED)); CLAY_TEXT(CLAY_ID("RendererTextTitle"), CLAY_STRING("Renderer & Platform Agnostic"), CLAY_TEXT_CONFIG(.fontSize = 52, .fontId = FONT_ID_TITLE_56, .textColor = COLOR_RED));
CLAY_CONTAINER(CLAY_ID("Spacer"), CLAY_LAYOUT(.sizing = { CLAY_SIZING_GROW(.max = 16) }), {}); CLAY_CONTAINER(CLAY_ID("RendererSpacerLeft"), CLAY_LAYOUT(.sizing = { CLAY_SIZING_GROW(.max = 16) }), {});
CLAY_TEXT(CLAY_IDI("RendererTextSubTitle", 1), CLAY_STRING("Clay outputs a sorted array of primitive render commands, such as RECTANGLE, TEXT or IMAGE."), CLAY_TEXT_CONFIG(.fontSize = 28, .fontId = FONT_ID_BODY_36, .textColor = COLOR_RED)); CLAY_TEXT(CLAY_IDI("RendererTextSubTitle", 1), CLAY_STRING("Clay outputs a sorted array of primitive render commands, such as RECTANGLE, TEXT or IMAGE."), CLAY_TEXT_CONFIG(.fontSize = 28, .fontId = FONT_ID_BODY_36, .textColor = COLOR_RED));
CLAY_TEXT(CLAY_IDI("RendererTextSubTitle", 2), CLAY_STRING("Write your own renderer in a few hundred lines of code, or use the provided examples for Raylib, WebGL canvas and more."), CLAY_TEXT_CONFIG(.fontSize = 28, .fontId = FONT_ID_BODY_36, .textColor = COLOR_RED)); CLAY_TEXT(CLAY_IDI("RendererTextSubTitle", 2), CLAY_STRING("Write your own renderer in a few hundred lines of code, or use the provided examples for Raylib, WebGL canvas and more."), CLAY_TEXT_CONFIG(.fontSize = 28, .fontId = FONT_ID_BODY_36, .textColor = COLOR_RED));
CLAY_TEXT(CLAY_IDI("RendererTextSubTitle", 3), CLAY_STRING("There's even an HTML renderer - you're looking at it right now!"), CLAY_TEXT_CONFIG(.fontSize = 28, .fontId = FONT_ID_BODY_36, .textColor = COLOR_RED)); CLAY_TEXT(CLAY_IDI("RendererTextSubTitle", 3), CLAY_STRING("There's even an HTML renderer - you're looking at it right now!"), CLAY_TEXT_CONFIG(.fontSize = 28, .fontId = FONT_ID_BODY_36, .textColor = COLOR_RED));
}); });
CLAY_CONTAINER(CLAY_ID("RendererRightText"), CLAY_LAYOUT(.sizing = { CLAY_SIZING_PERCENT(0.5) }, .childAlignment = {CLAY_ALIGN_X_CENTER}, .layoutDirection = CLAY_TOP_TO_BOTTOM, .childGap = 16), { CLAY_CONTAINER(CLAY_ID("RendererRightText"), CLAY_LAYOUT(.sizing = { CLAY_SIZING_PERCENT(0.5) }, .childAlignment = {CLAY_ALIGN_X_CENTER}, .layoutDirection = CLAY_TOP_TO_BOTTOM, .childGap = 16), {
CLAY_TEXT(CLAY_ID("RendererTextRightTitle"), CLAY_STRING("Try changing renderer!"), CLAY_TEXT_CONFIG(.fontSize = 36, .fontId = FONT_ID_BODY_36, .textColor = COLOR_ORANGE)); CLAY_TEXT(CLAY_ID("RendererTextRightTitle"), CLAY_STRING("Try changing renderer!"), CLAY_TEXT_CONFIG(.fontSize = 36, .fontId = FONT_ID_BODY_36, .textColor = COLOR_ORANGE));
CLAY_CONTAINER(CLAY_ID("Spacer"), CLAY_LAYOUT(.sizing = { CLAY_SIZING_GROW(.max = 32) }), {}); CLAY_CONTAINER(CLAY_ID("RendererSpacerRight"), CLAY_LAYOUT(.sizing = { CLAY_SIZING_GROW(.max = 32) }), {});
if (ACTIVE_RENDERER_INDEX == 0) { if (ACTIVE_RENDERER_INDEX == 0) {
RendererButtonActive(CLAY_IDI("RendererSelectButtonActive", 0), 0, CLAY_STRING("HTML Renderer")); RendererButtonActive(CLAY_IDI("RendererSelectButtonActive", 0), 0, CLAY_STRING("HTML Renderer"));
RendererButtonInactive(CLAY_ID("RendererSelectButtonCanvas"), 1, CLAY_STRING("Canvas Renderer")); RendererButtonInactive(CLAY_ID("RendererSelectButtonCanvas"), 1, CLAY_STRING("Canvas Renderer"));
@ -255,14 +254,14 @@ void RendererPageMobile() {
CLAY_RECTANGLE(CLAY_ID("RendererMobile"), CLAY_LAYOUT(.layoutDirection = CLAY_TOP_TO_BOTTOM, .sizing = { CLAY_SIZING_GROW(), CLAY_SIZING_FIT(.min = windowHeight - 50) }, .childAlignment = {.x = CLAY_ALIGN_X_CENTER, .y = CLAY_ALIGN_Y_CENTER}, .padding = {.x = 16, 32}, .childGap = 32), CLAY_RECTANGLE_CONFIG(.color = COLOR_LIGHT), { CLAY_RECTANGLE(CLAY_ID("RendererMobile"), CLAY_LAYOUT(.layoutDirection = CLAY_TOP_TO_BOTTOM, .sizing = { CLAY_SIZING_GROW(), CLAY_SIZING_FIT(.min = windowHeight - 50) }, .childAlignment = {.x = CLAY_ALIGN_X_CENTER, .y = CLAY_ALIGN_Y_CENTER}, .padding = {.x = 16, 32}, .childGap = 32), CLAY_RECTANGLE_CONFIG(.color = COLOR_LIGHT), {
CLAY_CONTAINER(CLAY_ID("RendererLeftText"), CLAY_LAYOUT(.sizing = { CLAY_SIZING_GROW() }, .layoutDirection = CLAY_TOP_TO_BOTTOM, .childGap = 8), { CLAY_CONTAINER(CLAY_ID("RendererLeftText"), CLAY_LAYOUT(.sizing = { CLAY_SIZING_GROW() }, .layoutDirection = CLAY_TOP_TO_BOTTOM, .childGap = 8), {
CLAY_TEXT(CLAY_ID("RendererTextTitle"), CLAY_STRING("Renderer & Platform Agnostic"), CLAY_TEXT_CONFIG(.fontSize = 48, .fontId = FONT_ID_TITLE_56, .textColor = COLOR_RED)); CLAY_TEXT(CLAY_ID("RendererTextTitle"), CLAY_STRING("Renderer & Platform Agnostic"), CLAY_TEXT_CONFIG(.fontSize = 48, .fontId = FONT_ID_TITLE_56, .textColor = COLOR_RED));
CLAY_CONTAINER(CLAY_ID("Spacer"), CLAY_LAYOUT(.sizing = { CLAY_SIZING_GROW(.max = 16) }), {}); CLAY_CONTAINER(CLAY_ID("RendererSpacerLeft"), CLAY_LAYOUT(.sizing = { CLAY_SIZING_GROW(.max = 16) }), {});
CLAY_TEXT(CLAY_IDI("RendererTextSubTitle", 1), CLAY_STRING("Clay outputs a sorted array of primitive render commands, such as RECTANGLE, TEXT or IMAGE."), CLAY_TEXT_CONFIG(.fontSize = 28, .fontId = FONT_ID_BODY_36, .textColor = COLOR_RED)); CLAY_TEXT(CLAY_IDI("RendererTextSubTitle", 1), CLAY_STRING("Clay outputs a sorted array of primitive render commands, such as RECTANGLE, TEXT or IMAGE."), CLAY_TEXT_CONFIG(.fontSize = 28, .fontId = FONT_ID_BODY_36, .textColor = COLOR_RED));
CLAY_TEXT(CLAY_IDI("RendererTextSubTitle", 2), CLAY_STRING("Write your own renderer in a few hundred lines of code, or use the provided examples for Raylib, WebGL canvas and more."), CLAY_TEXT_CONFIG(.fontSize = 28, .fontId = FONT_ID_BODY_36, .textColor = COLOR_RED)); CLAY_TEXT(CLAY_IDI("RendererTextSubTitle", 2), CLAY_STRING("Write your own renderer in a few hundred lines of code, or use the provided examples for Raylib, WebGL canvas and more."), CLAY_TEXT_CONFIG(.fontSize = 28, .fontId = FONT_ID_BODY_36, .textColor = COLOR_RED));
CLAY_TEXT(CLAY_IDI("RendererTextSubTitle", 3), CLAY_STRING("There's even an HTML renderer - you're looking at it right now!"), CLAY_TEXT_CONFIG(.fontSize = 28, .fontId = FONT_ID_BODY_36, .textColor = COLOR_RED)); CLAY_TEXT(CLAY_IDI("RendererTextSubTitle", 3), CLAY_STRING("There's even an HTML renderer - you're looking at it right now!"), CLAY_TEXT_CONFIG(.fontSize = 28, .fontId = FONT_ID_BODY_36, .textColor = COLOR_RED));
}); });
CLAY_CONTAINER(CLAY_ID("RendererRightText"), CLAY_LAYOUT(.sizing = { CLAY_SIZING_GROW() }, .layoutDirection = CLAY_TOP_TO_BOTTOM, .childGap = 16), { CLAY_CONTAINER(CLAY_ID("RendererRightText"), CLAY_LAYOUT(.sizing = { CLAY_SIZING_GROW() }, .layoutDirection = CLAY_TOP_TO_BOTTOM, .childGap = 16), {
CLAY_TEXT(CLAY_ID("RendererTextRightTitle"), CLAY_STRING("Try changing renderer!"), CLAY_TEXT_CONFIG(.fontSize = 36, .fontId = FONT_ID_BODY_36, .textColor = COLOR_ORANGE)); CLAY_TEXT(CLAY_ID("RendererTextRightTitle"), CLAY_STRING("Try changing renderer!"), CLAY_TEXT_CONFIG(.fontSize = 36, .fontId = FONT_ID_BODY_36, .textColor = COLOR_ORANGE));
CLAY_CONTAINER(CLAY_ID("Spacer"), CLAY_LAYOUT(.sizing = { CLAY_SIZING_GROW(.max = 32) }), {}); CLAY_CONTAINER(CLAY_ID("RendererSpacerRight"), CLAY_LAYOUT(.sizing = { CLAY_SIZING_GROW(.max = 32) }), {});
if (ACTIVE_RENDERER_INDEX == 0) { if (ACTIVE_RENDERER_INDEX == 0) {
RendererButtonActive(CLAY_IDI("RendererSelectButtonActive", 0), 0, CLAY_STRING("HTML Renderer")); RendererButtonActive(CLAY_IDI("RendererSelectButtonActive", 0), 0, CLAY_STRING("HTML Renderer"));
RendererButtonInactive(CLAY_ID("RendererSelectButtonCanvas"), 1, CLAY_STRING("Canvas Renderer")); RendererButtonInactive(CLAY_ID("RendererSelectButtonCanvas"), 1, CLAY_STRING("Canvas Renderer"));
@ -274,6 +273,22 @@ void RendererPageMobile() {
}); });
} }
void DebuggerPageDesktop() {
CLAY_RECTANGLE(CLAY_ID("DebuggerDesktop"), CLAY_LAYOUT(.sizing = { CLAY_SIZING_GROW(), CLAY_SIZING_FIT(.min = windowHeight - 50) }, .childAlignment = {0, CLAY_ALIGN_Y_CENTER}, .padding = {.x = 82, 32}, .childGap = 64), CLAY_RECTANGLE_CONFIG(.color = COLOR_RED), {
CLAY_CONTAINER(CLAY_ID("DebuggerLeftText"), CLAY_LAYOUT(.sizing = { CLAY_SIZING_PERCENT(0.5) }, .layoutDirection = CLAY_TOP_TO_BOTTOM, .childGap = 8), {
CLAY_TEXT(CLAY_ID("DebuggerTextTitle"), CLAY_STRING("Integrated Debug Tools"), CLAY_TEXT_CONFIG(.fontSize = 52, .fontId = FONT_ID_TITLE_56, .textColor = COLOR_LIGHT));
CLAY_CONTAINER(CLAY_ID("DebuggerSpacer"), CLAY_LAYOUT(.sizing = { CLAY_SIZING_GROW(.max = 16) }), {});
CLAY_TEXT(CLAY_IDI("DebuggerTextSubTitle", 1), CLAY_STRING("Clay includes built in \"Chrome Inspector\"-style debug tooling."), CLAY_TEXT_CONFIG(.fontSize = 28, .fontId = FONT_ID_BODY_36, .textColor = COLOR_LIGHT));
CLAY_TEXT(CLAY_IDI("DebuggerTextSubTitle", 2), CLAY_STRING("View your layout hierarchy and config in real time."), CLAY_TEXT_CONFIG(.fontSize = 28, .fontId = FONT_ID_BODY_36, .textColor = COLOR_LIGHT));
CLAY_CONTAINER(CLAY_ID("DebuggerPageSpacer"), CLAY_LAYOUT(.sizing = { .width = CLAY_SIZING_GROW(), .height = CLAY_SIZING_FIXED(32) }), {});
CLAY_TEXT(CLAY_ID("DebuggerTagline"), 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_CONTAINER(CLAY_ID("DebuggerRightImageOuter"), CLAY_LAYOUT(.sizing = { CLAY_SIZING_PERCENT(0.50) }, .childAlignment = {CLAY_ALIGN_X_CENTER}), {
CLAY_IMAGE(CLAY_ID("DebuggerPageRightImageInner"), CLAY_LAYOUT(.sizing = { CLAY_SIZING_GROW(.max = 558) }), CLAY_IMAGE_CONFIG(.sourceDimensions = {1620, 1474}, .sourceURL = CLAY_STRING("/clay/images/debugger.png")), {});
});
});
}
typedef struct typedef struct
{ {
Clay_Vector2 clickOrigin; Clay_Vector2 clickOrigin;
@ -284,9 +299,8 @@ typedef struct
ScrollbarData scrollbarData = (ScrollbarData) {}; ScrollbarData scrollbarData = (ScrollbarData) {};
float animationLerpValue = -1.0f; float animationLerpValue = -1.0f;
Clay_RenderCommandArray CreateLayout(float lerpValue) { Clay_RenderCommandArray CreateLayout(bool mobileScreen, float lerpValue) {
bool mobileScreen = windowWidth < 750; Clay_BeginLayout();
Clay_BeginLayout((int)windowWidth, (int)windowHeight);
CLAY_RECTANGLE(CLAY_ID("OuterContainer"), CLAY_LAYOUT(.layoutDirection = CLAY_TOP_TO_BOTTOM, .sizing = { CLAY_SIZING_GROW(), CLAY_SIZING_GROW() }), CLAY_RECTANGLE_CONFIG(.color = COLOR_LIGHT), { CLAY_RECTANGLE(CLAY_ID("OuterContainer"), CLAY_LAYOUT(.layoutDirection = CLAY_TOP_TO_BOTTOM, .sizing = { CLAY_SIZING_GROW(), CLAY_SIZING_GROW() }), CLAY_RECTANGLE_CONFIG(.color = COLOR_LIGHT), {
CLAY_CONTAINER(CLAY_ID("Header"), CLAY_LAYOUT(.sizing = { CLAY_SIZING_GROW(), CLAY_SIZING_FIXED(50) }, .childAlignment = { 0, CLAY_ALIGN_Y_CENTER }, .childGap = 24, .padding = { 32 }), { CLAY_CONTAINER(CLAY_ID("Header"), CLAY_LAYOUT(.sizing = { CLAY_SIZING_GROW(), CLAY_SIZING_FIXED(50) }, .childAlignment = { 0, CLAY_ALIGN_Y_CENTER }, .childGap = 24, .padding = { 32 }), {
CLAY_TEXT(CLAY_ID("Logo"), CLAY_STRING("Clay"), &headerTextConfig); CLAY_TEXT(CLAY_ID("Logo"), CLAY_STRING("Clay"), &headerTextConfig);
@ -300,7 +314,7 @@ Clay_RenderCommandArray CreateLayout(float lerpValue) {
CLAY_TEXT(CLAY_ID("LinkDocsText"), CLAY_STRING("Docs"), CLAY_TEXT_CONFIG(.disablePointerEvents = true, .fontId = FONT_ID_BODY_24, .fontSize = 24, .textColor = {61, 26, 5, 255})); CLAY_TEXT(CLAY_ID("LinkDocsText"), CLAY_STRING("Docs"), CLAY_TEXT_CONFIG(.disablePointerEvents = true, .fontId = FONT_ID_BODY_24, .fontSize = 24, .textColor = {61, 26, 5, 255}));
}); });
} }
uint32_t githubButtonId = CLAY_ID("HeaderButtonGithub"); Clay_ElementId githubButtonId = CLAY_ID("HeaderButtonGithub");
CLAY_BORDER_CONTAINER(CLAY_ID("LinkGithubOuter"), CLAY_LAYOUT(), CLAY_BORDER_CONFIG_OUTSIDE_RADIUS(2, COLOR_RED, 10), { CLAY_BORDER_CONTAINER(CLAY_ID("LinkGithubOuter"), CLAY_LAYOUT(), CLAY_BORDER_CONFIG_OUTSIDE_RADIUS(2, COLOR_RED, 10), {
CLAY_RECTANGLE(githubButtonId, CLAY_LAYOUT(.padding = {16, 6}), CLAY_RECTANGLE_CONFIG(.cornerRadius = CLAY_CORNER_RADIUS(10), .link = CLAY_STRING("https://github.com/nicbarker/clay"), .color = Clay_PointerOver(githubButtonId) ? COLOR_LIGHT_HOVER : COLOR_LIGHT), { CLAY_RECTANGLE(githubButtonId, CLAY_LAYOUT(.padding = {16, 6}), CLAY_RECTANGLE_CONFIG(.cornerRadius = CLAY_CORNER_RADIUS(10), .link = CLAY_STRING("https://github.com/nicbarker/clay"), .color = Clay_PointerOver(githubButtonId) ? COLOR_LIGHT_HOVER : COLOR_LIGHT), {
CLAY_TEXT(CLAY_ID("LinkGithubText"), CLAY_STRING("Github"), CLAY_TEXT_CONFIG(.disablePointerEvents = true, .fontId = FONT_ID_BODY_24, .fontSize = 24, .textColor = {61, 26, 5, 255})); CLAY_TEXT(CLAY_ID("LinkGithubText"), CLAY_STRING("Github"), CLAY_TEXT_CONFIG(.disablePointerEvents = true, .fontId = FONT_ID_BODY_24, .fontSize = 24, .textColor = {61, 26, 5, 255}));
@ -327,6 +341,7 @@ Clay_RenderCommandArray CreateLayout(float lerpValue) {
DeclarativeSyntaxPageDesktop(); DeclarativeSyntaxPageDesktop();
HighPerformancePageDesktop(lerpValue); HighPerformancePageDesktop(lerpValue);
RendererPageDesktop(); RendererPageDesktop();
DebuggerPageDesktop();
} }
}); });
}); });
@ -342,16 +357,19 @@ Clay_RenderCommandArray CreateLayout(float lerpValue) {
scrollbarColor = (Clay_Color){225, 138, 50, 160}; scrollbarColor = (Clay_Color){225, 138, 50, 160};
} }
float scrollHeight = scrollData.scrollContainerDimensions.height - 12; 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_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").id, .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), {}); 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); return Clay_EndLayout();
} }
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, float deltaTime) { bool debugModeEnabled = false;
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) {
windowWidth = width; windowWidth = width;
windowHeight = height; windowHeight = height;
Clay_SetLayoutDimensions((Clay_Dimensions) { width, height });
if (deltaTime == deltaTime) { // NaN propagation can cause pain here if (deltaTime == deltaTime) { // NaN propagation can cause pain here
animationLerpValue += deltaTime; animationLerpValue += deltaTime;
if (animationLerpValue > 1) { if (animationLerpValue > 1) {
@ -359,6 +377,11 @@ CLAY_WASM_EXPORT("UpdateDrawFrame") Clay_RenderCommandArray UpdateDrawFrame(floa
} }
} }
if (dKeyPressedThisFrame) {
debugModeEnabled = !debugModeEnabled;
Clay_SetDebugModeEnabled(debugModeEnabled);
}
if (isTouchDown || isMouseDown) { if (isTouchDown || isMouseDown) {
if (Clay_PointerOver(CLAY_ID("RendererSelectButtonHTML"))) { if (Clay_PointerOver(CLAY_ID("RendererSelectButtonHTML"))) {
ACTIVE_RENDERER_INDEX = 0; ACTIVE_RENDERER_INDEX = 0;
@ -366,9 +389,10 @@ CLAY_WASM_EXPORT("UpdateDrawFrame") Clay_RenderCommandArray UpdateDrawFrame(floa
ACTIVE_RENDERER_INDEX = 1; ACTIVE_RENDERER_INDEX = 1;
} }
} }
//----------------------------------------------------------------------------------
// Handle scroll containers Clay__debugViewHighlightColor = (Clay_Color) {105,210,231, 120};
Clay_SetPointerPosition((Clay_Vector2) {mousePositionX, mousePositionY});
Clay_SetPointerState((Clay_Vector2) {mousePositionX, mousePositionY}, isMouseDown);
if (!isMouseDown) { if (!isMouseDown) {
scrollbarData.mouseDown = false; scrollbarData.mouseDown = false;
@ -408,7 +432,11 @@ CLAY_WASM_EXPORT("UpdateDrawFrame") Clay_RenderCommandArray UpdateDrawFrame(floa
} }
Clay_UpdateScrollContainers(isTouchDown, (Clay_Vector2) {mouseWheelX, mouseWheelY}, deltaTime); Clay_UpdateScrollContainers(isTouchDown, (Clay_Vector2) {mouseWheelX, mouseWheelY}, deltaTime);
return CreateLayout(animationLerpValue < 0 ? (animationLerpValue + 1) : (1 - animationLerpValue)); bool isMobileScreen = windowWidth < 750;
if (debugModeEnabled) {
isMobileScreen = windowWidth < 950;
}
return CreateLayout(isMobileScreen, animationLerpValue < 0 ? (animationLerpValue + 1) : (1 - animationLerpValue));
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
} }

View File

@ -20,7 +20,7 @@ set(CMAKE_C_STANDARD 99)
add_executable(clay_examples_raylib_sidebar_scrolling_container main.c) add_executable(clay_examples_raylib_sidebar_scrolling_container main.c)
target_compile_options(clay_examples_raylib_sidebar_scrolling_container PUBLIC -Wno-initializer-overrides) target_compile_options(clay_examples_raylib_sidebar_scrolling_container PUBLIC -DCLAY_DEBUG)
target_include_directories(clay_examples_raylib_sidebar_scrolling_container PUBLIC .) target_include_directories(clay_examples_raylib_sidebar_scrolling_container PUBLIC .)
target_link_libraries(clay_examples_raylib_sidebar_scrolling_container PUBLIC raylib) target_link_libraries(clay_examples_raylib_sidebar_scrolling_container PUBLIC raylib)

View File

@ -14,7 +14,7 @@ Clay_TextElementConfig headerTextConfig = (Clay_TextElementConfig) { .fontId = F
// Examples of re-usable "Components" // Examples of re-usable "Components"
void RenderHeaderButton(uint16_t index, Clay_String text) { void RenderHeaderButton(uint16_t index, Clay_String text) {
uint32_t buttonId = CLAY_IDI("HeaderButton", index); Clay_ElementId buttonId = CLAY_IDI("HeaderButton", index);
CLAY_RECTANGLE(buttonId, CLAY_LAYOUT(.padding = {16, 8}), CLAY_RECTANGLE_CONFIG(.color = Clay_PointerOver(buttonId) ? COLOR_BLUE : COLOR_ORANGE), { CLAY_RECTANGLE(buttonId, CLAY_LAYOUT(.padding = {16, 8}), CLAY_RECTANGLE_CONFIG(.color = Clay_PointerOver(buttonId) ? COLOR_BLUE : COLOR_ORANGE), {
CLAY_TEXT(CLAY_IDI("Button", index), text, &headerTextConfig); CLAY_TEXT(CLAY_IDI("Button", index), text, &headerTextConfig);
}); });
@ -24,14 +24,14 @@ Clay_LayoutConfig dropdownTextItemLayout = (Clay_LayoutConfig) { .padding = {8,
Clay_RectangleElementConfig dropdownRectangleConfig = (Clay_RectangleElementConfig) { .color = {180, 180, 180, 255} }; Clay_RectangleElementConfig dropdownRectangleConfig = (Clay_RectangleElementConfig) { .color = {180, 180, 180, 255} };
Clay_TextElementConfig dropdownTextElementConfig = (Clay_TextElementConfig) { .fontSize = 24, .textColor = {255,255,255,255} }; Clay_TextElementConfig dropdownTextElementConfig = (Clay_TextElementConfig) { .fontSize = 24, .textColor = {255,255,255,255} };
void RenderDropdownTextItem() { void RenderDropdownTextItem(int index) {
CLAY_RECTANGLE(CLAY_ID("ScrollContainerItem"), &dropdownTextItemLayout, &dropdownRectangleConfig, { // We can save a lot of memory by re-using configs in loops rather than redefining them CLAY_RECTANGLE(CLAY_IDI("ScrollContainerItem", index), &dropdownTextItemLayout, &dropdownRectangleConfig, { // We can save a lot of memory by re-using configs in loops rather than redefining them
CLAY_TEXT(CLAY_ID("ScrollContainerText"), CLAY_STRING("I'm a text field in a scroll container."), &dropdownTextElementConfig); CLAY_TEXT(CLAY_IDI("ScrollContainerText", index), CLAY_STRING("I'm a text field in a scroll container."), &dropdownTextElementConfig);
}); });
} }
Clay_RenderCommandArray CreateLayout() { Clay_RenderCommandArray CreateLayout() {
Clay_BeginLayout((int)GetScreenWidth(), (int)GetScreenHeight()); Clay_BeginLayout();
CLAY_RECTANGLE(CLAY_ID("OuterContainer"), CLAY_LAYOUT(.sizing = { .width = CLAY_SIZING_GROW(), .height = CLAY_SIZING_GROW() }, .padding = { 16, 16 }, .childGap = 16), CLAY_RECTANGLE_CONFIG(.color = {200, 200, 200, 255}), { CLAY_RECTANGLE(CLAY_ID("OuterContainer"), CLAY_LAYOUT(.sizing = { .width = CLAY_SIZING_GROW(), .height = CLAY_SIZING_GROW() }, .padding = { 16, 16 }, .childGap = 16), CLAY_RECTANGLE_CONFIG(.color = {200, 200, 200, 255}), {
CLAY_RECTANGLE(CLAY_ID("SideBar"), CLAY_LAYOUT(.layoutDirection = CLAY_TOP_TO_BOTTOM, .sizing = { .width = CLAY_SIZING_FIXED(300), .height = CLAY_SIZING_GROW() }, .padding = {16, 16}, .childGap = 16), CLAY_RECTANGLE_CONFIG(.color = {150, 150, 255, 255}), { CLAY_RECTANGLE(CLAY_ID("SideBar"), CLAY_LAYOUT(.layoutDirection = CLAY_TOP_TO_BOTTOM, .sizing = { .width = CLAY_SIZING_FIXED(300), .height = CLAY_SIZING_GROW() }, .padding = {16, 16}, .childGap = 16), CLAY_RECTANGLE_CONFIG(.color = {150, 150, 255, 255}), {
CLAY_RECTANGLE(CLAY_ID("ProfilePictureOuter"), CLAY_LAYOUT(.sizing = { .width = CLAY_SIZING_GROW() }, .padding = { 8, 8 }, .childGap = 8, .childAlignment = { .y = CLAY_ALIGN_Y_CENTER }), CLAY_RECTANGLE_CONFIG(.color = {130, 130, 255, 255}), { CLAY_RECTANGLE(CLAY_ID("ProfilePictureOuter"), CLAY_LAYOUT(.sizing = { .width = CLAY_SIZING_GROW() }, .padding = { 8, 8 }, .childGap = 8, .childAlignment = { .y = CLAY_ALIGN_Y_CENTER }), CLAY_RECTANGLE_CONFIG(.color = {130, 130, 255, 255}), {
@ -52,9 +52,11 @@ Clay_RenderCommandArray CreateLayout() {
}); });
CLAY_SCROLL_CONTAINER(CLAY_ID("MainContent"), CLAY_LAYOUT(.sizing = { .width = CLAY_SIZING_GROW(), .height = CLAY_SIZING_GROW() }), CLAY_SCROLL_CONFIG(.vertical = true), { CLAY_SCROLL_CONTAINER(CLAY_ID("MainContent"), CLAY_LAYOUT(.sizing = { .width = CLAY_SIZING_GROW(), .height = CLAY_SIZING_GROW() }), CLAY_SCROLL_CONFIG(.vertical = true), {
CLAY_RECTANGLE(CLAY_ID("MainContentInner"), CLAY_LAYOUT(.layoutDirection = CLAY_TOP_TO_BOTTOM, .padding = {16, 16}, .childGap = 16), CLAY_RECTANGLE_CONFIG(.color = {200, 200, 255, 255}), { CLAY_RECTANGLE(CLAY_ID("MainContentInner"), CLAY_LAYOUT(.layoutDirection = CLAY_TOP_TO_BOTTOM, .padding = {16, 16}, .childGap = 16), CLAY_RECTANGLE_CONFIG(.color = {200, 200, 255, 255}), {
CLAY_FLOATING_CONTAINER(CLAY_ID("FloatingContainer"), CLAY_LAYOUT(.sizing = { .width = CLAY_SIZING_FIXED(300), .height = CLAY_SIZING_FIXED(300) }, .padding = {16, 16}), CLAY_FLOATING_CONFIG(.zIndex = 1, .attachment = { CLAY_ATTACH_POINT_CENTER_TOP, CLAY_ATTACH_POINT_CENTER_TOP }, .offset = {0, -16}), { CLAY_FLOATING_CONTAINER(CLAY_ID("FloatingContainer"), CLAY_LAYOUT(.sizing = { .width = CLAY_SIZING_FIXED(300), .height = CLAY_SIZING_FIXED(300) }), CLAY_FLOATING_CONFIG(.zIndex = 1, .attachment = { CLAY_ATTACH_POINT_CENTER_TOP, CLAY_ATTACH_POINT_CENTER_TOP }, .offset = {0, -16}), {
CLAY_RECTANGLE(CLAY_ID("FloatingContainerBackground"), CLAY_LAYOUT(.sizing = { CLAY_SIZING_GROW(), CLAY_SIZING_GROW() }), CLAY_RECTANGLE_CONFIG(.color = {140,80, 200, 200}), { CLAY_BORDER_CONTAINER(CLAY_ID("FloatingContainerBorder"), CLAY_LAYOUT(.sizing = { CLAY_SIZING_GROW(), CLAY_SIZING_GROW() }, .padding = { 16, 16 }), CLAY_BORDER_CONFIG_OUTSIDE(.color = {80, 80, 80, 255}, .width = 2), {
CLAY_TEXT(CLAY_ID("FloatingContainerText"), CLAY_STRING("I'm an inline floating container."), CLAY_TEXT_CONFIG(.fontSize = 24, .textColor = {255,255,255,255})); CLAY_RECTANGLE(CLAY_ID("FloatingContainerBackground"), CLAY_LAYOUT(.sizing = { CLAY_SIZING_GROW(), CLAY_SIZING_GROW() }), CLAY_RECTANGLE_CONFIG(.color = {140,80, 200, 200}), {
CLAY_TEXT(CLAY_ID("FloatingContainerText"), CLAY_STRING("I'm an inline floating container."), CLAY_TEXT_CONFIG(.fontSize = 24, .textColor = {255,255,255,255}));
});
}); });
}); });
@ -62,10 +64,10 @@ Clay_RenderCommandArray CreateLayout() {
CLAY_STRING("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt."), CLAY_STRING("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt."),
CLAY_TEXT_CONFIG(.fontId = FONT_ID_BODY_24, .fontSize = 24, .textColor = {0,0,0,255})); CLAY_TEXT_CONFIG(.fontId = FONT_ID_BODY_24, .fontSize = 24, .textColor = {0,0,0,255}));
CLAY_RECTANGLE(CLAY_ID("Photos"), CLAY_LAYOUT(.childGap = 16, .padding = { 16, 16 }), CLAY_RECTANGLE_CONFIG(.color = {180, 180, 220, 255}), { CLAY_RECTANGLE(CLAY_ID("Photos2"), CLAY_LAYOUT(.childGap = 16, .padding = { 16, 16 }), CLAY_RECTANGLE_CONFIG(.color = {180, 180, 220, 255}), {
CLAY_IMAGE(CLAY_ID("Picture1"), CLAY_LAYOUT( .sizing = { .width = CLAY_SIZING_FIXED(120), .height = CLAY_SIZING_FIXED(120) }), CLAY_IMAGE_CONFIG(.imageData = &profilePicture, .sourceDimensions = {120, 120}), {}); CLAY_IMAGE(CLAY_ID("Picture4"), CLAY_LAYOUT( .sizing = { .width = CLAY_SIZING_FIXED(120), .height = CLAY_SIZING_FIXED(120) }), CLAY_IMAGE_CONFIG(.imageData = &profilePicture, .sourceDimensions = {120, 120}), {});
CLAY_IMAGE(CLAY_ID("Picture2"), CLAY_LAYOUT( .sizing = { .width = CLAY_SIZING_FIXED(120), .height = CLAY_SIZING_FIXED(120) }), CLAY_IMAGE_CONFIG(.imageData = &profilePicture, .sourceDimensions = {120, 120}), {}); CLAY_IMAGE(CLAY_ID("Picture5"), CLAY_LAYOUT( .sizing = { .width = CLAY_SIZING_FIXED(120), .height = CLAY_SIZING_FIXED(120) }), CLAY_IMAGE_CONFIG(.imageData = &profilePicture, .sourceDimensions = {120, 120}), {});
CLAY_IMAGE(CLAY_ID("Picture3"), CLAY_LAYOUT( .sizing = { .width = CLAY_SIZING_FIXED(120), .height = CLAY_SIZING_FIXED(120) }), CLAY_IMAGE_CONFIG(.imageData = &profilePicture, .sourceDimensions = {120, 120}), {}); CLAY_IMAGE(CLAY_ID("Picture6"), CLAY_LAYOUT( .sizing = { .width = CLAY_SIZING_FIXED(120), .height = CLAY_SIZING_FIXED(120) }), CLAY_IMAGE_CONFIG(.imageData = &profilePicture, .sourceDimensions = {120, 120}), {});
}); });
CLAY_TEXT(CLAY_ID("BodyText2"), CLAY_TEXT(CLAY_ID("BodyText2"),
@ -79,8 +81,8 @@ Clay_RenderCommandArray CreateLayout() {
CLAY_RECTANGLE(CLAY_ID("Photos"), CLAY_LAYOUT(.sizing = { .width = CLAY_SIZING_GROW() }, .childAlignment = { .x = CLAY_ALIGN_X_CENTER, .y = CLAY_ALIGN_Y_CENTER }, .childGap = 16, .padding = {16, 16}), CLAY_RECTANGLE_CONFIG(.color = {180, 180, 220, 255}), { CLAY_RECTANGLE(CLAY_ID("Photos"), CLAY_LAYOUT(.sizing = { .width = CLAY_SIZING_GROW() }, .childAlignment = { .x = CLAY_ALIGN_X_CENTER, .y = CLAY_ALIGN_Y_CENTER }, .childGap = 16, .padding = {16, 16}), CLAY_RECTANGLE_CONFIG(.color = {180, 180, 220, 255}), {
CLAY_IMAGE(CLAY_ID("Picture2"), CLAY_LAYOUT(.sizing = { .width = CLAY_SIZING_FIXED(120), .height = CLAY_SIZING_FIXED(120) }), CLAY_IMAGE_CONFIG(.imageData = &profilePicture, .sourceDimensions = {120, 120}), {}); CLAY_IMAGE(CLAY_ID("Picture2"), CLAY_LAYOUT(.sizing = { .width = CLAY_SIZING_FIXED(120), .height = CLAY_SIZING_FIXED(120) }), CLAY_IMAGE_CONFIG(.imageData = &profilePicture, .sourceDimensions = {120, 120}), {});
CLAY_RECTANGLE(CLAY_ID("Picture1"), CLAY_LAYOUT(.childAlignment = { .x = CLAY_ALIGN_X_CENTER }, .layoutDirection = CLAY_TOP_TO_BOTTOM, .padding = {8, 8}), CLAY_RECTANGLE_CONFIG(.color = {170, 170, 220, 255}), { CLAY_RECTANGLE(CLAY_ID("Picture1"), CLAY_LAYOUT(.childAlignment = { .x = CLAY_ALIGN_X_CENTER }, .layoutDirection = CLAY_TOP_TO_BOTTOM, .padding = {8, 8}), CLAY_RECTANGLE_CONFIG(.color = {170, 170, 220, 255}), {
CLAY_IMAGE(CLAY_ID("ProfilePicture"), CLAY_LAYOUT(.sizing = { .width = CLAY_SIZING_FIXED(60), .height = CLAY_SIZING_FIXED(60) }), CLAY_IMAGE_CONFIG(.imageData = &profilePicture, .sourceDimensions = {60, 60}), {}); CLAY_IMAGE(CLAY_ID("ProfilePicture2"), CLAY_LAYOUT(.sizing = { .width = CLAY_SIZING_FIXED(60), .height = CLAY_SIZING_FIXED(60) }), CLAY_IMAGE_CONFIG(.imageData = &profilePicture, .sourceDimensions = {60, 60}), {});
CLAY_TEXT(CLAY_ID("ProfileTitle"), CLAY_STRING("Image caption below"), CLAY_TEXT_CONFIG(.fontSize = 24, .textColor = {0,0,0,255})); CLAY_TEXT(CLAY_ID("ProfileTitle2"), CLAY_STRING("Image caption below"), CLAY_TEXT_CONFIG(.fontSize = 24, .textColor = {0,0,0,255}));
}); });
CLAY_IMAGE(CLAY_ID("Picture3"), CLAY_LAYOUT( .sizing = { .width = CLAY_SIZING_FIXED(120), .height = CLAY_SIZING_FIXED(120) }), CLAY_IMAGE_CONFIG(.imageData = &profilePicture, .sourceDimensions = {120, 120}), {}); CLAY_IMAGE(CLAY_ID("Picture3"), CLAY_LAYOUT( .sizing = { .width = CLAY_SIZING_FIXED(120), .height = CLAY_SIZING_FIXED(120) }), CLAY_IMAGE_CONFIG(.imageData = &profilePicture, .sourceDimensions = {120, 120}), {});
}); });
@ -92,26 +94,26 @@ Clay_RenderCommandArray CreateLayout() {
}); });
}); });
CLAY_FLOATING_CONTAINER(CLAY_ID("Blob4Floating"), &CLAY_LAYOUT_DEFAULT, CLAY_FLOATING_CONFIG(.zIndex = 1, .parentId = CLAY_ID("SidebarBlob4")), { CLAY_FLOATING_CONTAINER(CLAY_ID("Blob4Floating2"), &CLAY_LAYOUT_DEFAULT, CLAY_FLOATING_CONFIG(.zIndex = 1, .parentId = CLAY_ID("SidebarBlob4").id), {
CLAY_SCROLL_CONTAINER(CLAY_ID("ScrollContainer"), CLAY_LAYOUT(.sizing = { .height = CLAY_SIZING_FIXED(200) }, .childGap = 2), CLAY_SCROLL_CONFIG(.vertical = true), { CLAY_SCROLL_CONTAINER(CLAY_ID("ScrollContainer"), CLAY_LAYOUT(.sizing = { .height = CLAY_SIZING_FIXED(200) }, .childGap = 2), CLAY_SCROLL_CONFIG(.vertical = true), {
CLAY_FLOATING_CONTAINER(CLAY_ID("FloatingContainer"), CLAY_LAYOUT(), CLAY_FLOATING_CONFIG(.zIndex = 1), { CLAY_FLOATING_CONTAINER(CLAY_ID("FloatingContainer2"), CLAY_LAYOUT(), CLAY_FLOATING_CONFIG(.zIndex = 1), {
CLAY_RECTANGLE(CLAY_ID("FLoatingContainerInner"), CLAY_LAYOUT(.sizing = { .width = CLAY_SIZING_FIXED(300), .height = CLAY_SIZING_FIXED(300) }, .padding = {16, 16}), CLAY_RECTANGLE_CONFIG(.color = {140,80, 200, 200}), { CLAY_RECTANGLE(CLAY_ID("FloatingContainerInner"), CLAY_LAYOUT(.sizing = { .width = CLAY_SIZING_FIXED(300), .height = CLAY_SIZING_FIXED(300) }, .padding = {16, 16}), CLAY_RECTANGLE_CONFIG(.color = {140,80, 200, 200}), {
CLAY_TEXT(CLAY_ID("FloatingContainerText"), CLAY_STRING("I'm an inline floating container."), CLAY_TEXT_CONFIG(.fontSize = 24, .textColor = {255,255,255,255})); CLAY_TEXT(CLAY_ID("FloatingContainerText2"), CLAY_STRING("I'm an inline floating container."), CLAY_TEXT_CONFIG(.fontSize = 24, .textColor = {255,255,255,255}));
}); });
}); });
CLAY_RECTANGLE(CLAY_ID("ScrollContainerInner"), CLAY_LAYOUT(.layoutDirection = CLAY_TOP_TO_BOTTOM), CLAY_RECTANGLE_CONFIG(.color = {160, 160, 160, 255}), { CLAY_RECTANGLE(CLAY_ID("ScrollContainerInner"), CLAY_LAYOUT(.layoutDirection = CLAY_TOP_TO_BOTTOM), CLAY_RECTANGLE_CONFIG(.color = {160, 160, 160, 255}), {
for (int i = 0; i < 100; i++) { // for (int i = 0; i < 100; i++) {
RenderDropdownTextItem(); // RenderDropdownTextItem(i);
} // }
}); });
}); });
}); });
Clay_ScrollContainerData scrollData = Clay_GetScrollContainerData(CLAY_ID("MainContent")); Clay_ScrollContainerData scrollData = Clay_GetScrollContainerData(CLAY_ID("MainContent"));
CLAY_FLOATING_CONTAINER(CLAY_ID("ScrollBar"), &CLAY_LAYOUT_DEFAULT, CLAY_FLOATING_CONFIG(.offset = { .y = -(scrollData.scrollPosition->y / scrollData.contentDimensions.height) * scrollData.scrollContainerDimensions.height }, .zIndex = 1, .parentId = CLAY_ID("MainContent"), .attachment = {.element = CLAY_ATTACH_POINT_RIGHT_TOP, .parent = CLAY_ATTACH_POINT_RIGHT_TOP}), { CLAY_FLOATING_CONTAINER(CLAY_ID("ScrollBar"), &CLAY_LAYOUT_DEFAULT, CLAY_FLOATING_CONFIG(.offset = { .y = -(scrollData.scrollPosition->y / scrollData.contentDimensions.height) * scrollData.scrollContainerDimensions.height }, .zIndex = 1, .parentId = CLAY_ID("MainContent").id, .attachment = {.element = CLAY_ATTACH_POINT_RIGHT_TOP, .parent = CLAY_ATTACH_POINT_RIGHT_TOP}), {
CLAY_RECTANGLE(CLAY_ID("ScrollBarButton"), CLAY_LAYOUT(.sizing = {CLAY_SIZING_FIXED(12), CLAY_SIZING_FIXED((scrollData.scrollContainerDimensions.height / scrollData.contentDimensions.height) * scrollData.scrollContainerDimensions.height)}), CLAY_RECTANGLE_CONFIG(.cornerRadius = 6, .color = Clay_PointerOver(CLAY_ID("ScrollBar")) ? (Clay_Color){100, 100, 140, 150} : (Clay_Color){120, 120, 160, 150}), {}); CLAY_RECTANGLE(CLAY_ID("ScrollBarButton"), CLAY_LAYOUT(.sizing = {CLAY_SIZING_FIXED(12), CLAY_SIZING_FIXED((scrollData.scrollContainerDimensions.height / scrollData.contentDimensions.height) * scrollData.scrollContainerDimensions.height)}), CLAY_RECTANGLE_CONFIG(.cornerRadius = 6, .color = Clay_PointerOver(CLAY_ID("ScrollBar")) ? (Clay_Color){100, 100, 140, 150} : (Clay_Color){120, 120, 160, 150}), {});
}); });
}); });
return Clay_EndLayout(GetScreenWidth(), GetScreenHeight()); return Clay_EndLayout();
} }
typedef struct typedef struct
@ -123,16 +125,23 @@ typedef struct
ScrollbarData scrollbarData = (ScrollbarData) {}; ScrollbarData scrollbarData = (ScrollbarData) {};
bool debugEnabled = false;
void UpdateDrawFrame(void) void UpdateDrawFrame(void)
{ {
float mouseWheelX = 0, mouseWheelY = 0;
Vector2 mouseWheelDelta = GetMouseWheelMoveV(); Vector2 mouseWheelDelta = GetMouseWheelMoveV();
mouseWheelX = mouseWheelDelta.x; float mouseWheelX = mouseWheelDelta.x;
mouseWheelY = mouseWheelDelta.y; float mouseWheelY = mouseWheelDelta.y;
if (IsKeyPressed(KEY_D)) {
debugEnabled = !debugEnabled;
Clay_SetDebugModeEnabled(debugEnabled);
}
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Handle scroll containers // Handle scroll containers
Clay_Vector2 mousePosition = RAYLIB_VECTOR2_TO_CLAY_VECTOR2(GetMousePosition()); Clay_Vector2 mousePosition = RAYLIB_VECTOR2_TO_CLAY_VECTOR2(GetMousePosition());
Clay_SetPointerPosition(mousePosition); Clay_SetPointerState(mousePosition, IsMouseButtonDown(0));
Clay_SetLayoutDimensions((Clay_Dimensions) { (float)GetScreenWidth(), (float)GetScreenHeight() });
if (!IsMouseButtonDown(0)) { if (!IsMouseButtonDown(0)) {
scrollbarData.mouseDown = false; scrollbarData.mouseDown = false;
} }
@ -166,6 +175,7 @@ void UpdateDrawFrame(void)
// RENDERING --------------------------------- // RENDERING ---------------------------------
// currentTime = GetTime(); // currentTime = GetTime();
BeginDrawing(); BeginDrawing();
ClearBackground(BLACK);
Clay_Raylib_Render(renderCommands); Clay_Raylib_Render(renderCommands);
EndDrawing(); EndDrawing();
// printf("render time: %f ms\n", (GetTime() - currentTime) * 1000); // printf("render time: %f ms\n", (GetTime() - currentTime) * 1000);
@ -177,7 +187,7 @@ int main(void) {
uint64_t totalMemorySize = Clay_MinMemorySize(); uint64_t totalMemorySize = Clay_MinMemorySize();
Clay_Arena clayMemory = (Clay_Arena) { .label = CLAY_STRING("Clay Memory Arena"), .memory = malloc(totalMemorySize), .capacity = totalMemorySize }; Clay_Arena clayMemory = (Clay_Arena) { .label = CLAY_STRING("Clay Memory Arena"), .memory = malloc(totalMemorySize), .capacity = totalMemorySize };
Clay_SetMeasureTextFunction(Raylib_MeasureText); Clay_SetMeasureTextFunction(Raylib_MeasureText);
Clay_Initialize(clayMemory); Clay_Initialize(clayMemory, (Clay_Dimensions) { (float)GetScreenWidth(), (float)GetScreenHeight() });
Clay_Raylib_Initialize(FLAG_VSYNC_HINT | FLAG_WINDOW_RESIZABLE | FLAG_WINDOW_HIGHDPI | FLAG_MSAA_4X_HINT); Clay_Raylib_Initialize(FLAG_VSYNC_HINT | FLAG_WINDOW_RESIZABLE | FLAG_WINDOW_HIGHDPI | FLAG_MSAA_4X_HINT);
profilePicture = LoadTextureFromImage(LoadImage("resources/profile-picture.png")); profilePicture = LoadTextureFromImage(LoadImage("resources/profile-picture.png"));
Raylib_fonts[FONT_ID_BODY_24] = (Raylib_Font) { Raylib_fonts[FONT_ID_BODY_24] = (Raylib_Font) {

View File

@ -3,7 +3,9 @@ void $NAME$_Set($NAME$ *array, int index, $TYPE$ value) {
array->internalArray[index] = value; array->internalArray[index] = value;
array->length = index < array->length ? array->length : index + 1; array->length = index < array->length ? array->length : index + 1;
} else { } else {
Clay__StringArray_Add(&Clay_warnings, CLAY_STRING("Attempting to allocate array in arena, but arena is already at capacity and would overflow.")); if (Clay__warningsEnabled) {
Clay__WarningArray_Add(&Clay_warnings, (Clay__Warning) { CLAY_STRING("Attempting to allocate array in arena, but arena is already at capacity and would overflow.") });
}
#ifdef CLAY_OVERFLOW_TRAP #ifdef CLAY_OVERFLOW_TRAP
raise(SIGTRAP); raise(SIGTRAP);
#endif #endif

View File

@ -102,6 +102,7 @@ static inline Clay_Dimensions Raylib_MeasureText(Clay_String *text, Clay_TextEle
float textHeight = config->fontSize; float textHeight = config->fontSize;
Font fontToUse = Raylib_fonts[config->fontId].font; Font fontToUse = Raylib_fonts[config->fontId].font;
float scaleFactor = config->fontSize/(float)fontToUse.baseSize;
for (int i = 0; i < text->length; ++i) for (int i = 0; i < text->length; ++i)
{ {
@ -117,7 +118,7 @@ static inline Clay_Dimensions Raylib_MeasureText(Clay_String *text, Clay_TextEle
maxTextWidth = fmax(maxTextWidth, lineTextWidth); maxTextWidth = fmax(maxTextWidth, lineTextWidth);
textSize.width = maxTextWidth / 2; textSize.width = maxTextWidth * scaleFactor;
textSize.height = textHeight; textSize.height = textHeight;
return textSize; return textSize;
@ -170,7 +171,7 @@ void Clay_Raylib_Render(Clay_RenderCommandArray renderCommands)
case CLAY_RENDER_COMMAND_TYPE_RECTANGLE: { case CLAY_RENDER_COMMAND_TYPE_RECTANGLE: {
Clay_RectangleElementConfig *config = renderCommand->config.rectangleElementConfig; Clay_RectangleElementConfig *config = renderCommand->config.rectangleElementConfig;
if (config->cornerRadius.topLeft > 0) { if (config->cornerRadius.topLeft > 0) {
float radius = (config->cornerRadius.topLeft * 2) / (boundingBox.width > boundingBox.height) ? boundingBox.height : boundingBox.width; float radius = (config->cornerRadius.topLeft * 2) / (float)((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)); DrawRectangleRounded((Rectangle) { boundingBox.x, boundingBox.y, boundingBox.width, boundingBox.height }, radius, 8, CLAY_COLOR_TO_RAYLIB_COLOR(config->color));
} else { } else {
DrawRectangle(boundingBox.x, boundingBox.y, boundingBox.width, boundingBox.height, CLAY_COLOR_TO_RAYLIB_COLOR(config->color)); DrawRectangle(boundingBox.x, boundingBox.y, boundingBox.width, boundingBox.height, CLAY_COLOR_TO_RAYLIB_COLOR(config->color));

View File

@ -111,6 +111,7 @@
{ name: 'fontSize', type: 'uint16_t' }, { name: 'fontSize', type: 'uint16_t' },
{ name: 'letterSpacing', type: 'uint16_t' }, { name: 'letterSpacing', type: 'uint16_t' },
{ name: 'lineSpacing', type: 'uint16_t' }, { name: 'lineSpacing', type: 'uint16_t' },
{ name: 'wrapMode', type: 'uint32_t' },
{ name: 'disablePointerEvents', type: 'uint8_t' } { name: 'disablePointerEvents', type: 'uint8_t' }
] ]
}; };
@ -259,6 +260,18 @@
window.mouseDown = true; window.mouseDown = true;
}); });
document.addEventListener("keydown", (event) => {
if (event.key === "ArrowDown") {
window.arrowKeyDownPressedThisFrame = true;
}
if (event.key === "ArrowUp") {
window.arrowKeyUpPressedThisFrame = true;
}
if (event.key === "d") {
window.dKeyPressedThisFrame = true;
}
});
const importObject = { const importObject = {
clay: { clay: {
measureTextFunction: (addressOfDimensions, textToMeasure, addressOfConfig) => { measureTextFunction: (addressOfDimensions, textToMeasure, addressOfConfig) => {
@ -288,26 +301,22 @@
} }
function renderLoopCanvas() { function renderLoopCanvas() {
// Note: Rendering to canvas needs to be scaled up by window.devicePixelRatio in both width and height. // Note: Rendering to canvas needs to be scaled up by window.devicePixelRatio in both width and height.
// e.g. if we're working on a device where devicePixelRatio is 2, we need to render // e.g. if we're working on a device where devicePixelRatio is 2, we need to render
// everything at width^2 x height^2 resolution, then scale back down with css to get the correct pixel density. // everything at width^2 x height^2 resolution, then scale back down with css to get the correct pixel density.
let capacity = memoryDataView.getUint32(scratchSpaceAddress, true); let capacity = memoryDataView.getUint32(scratchSpaceAddress, true);
let length = memoryDataView.getUint32(scratchSpaceAddress + 4, true); let length = memoryDataView.getUint32(scratchSpaceAddress + 4, true);
let arrayOffset = memoryDataView.getUint32(scratchSpaceAddress + 8, true); let arrayOffset = memoryDataView.getUint32(scratchSpaceAddress + 8, true);
if (window.previousWidth !== window.innerWidth) { window.canvasRoot.width = window.innerWidth * window.devicePixelRatio;
window.canvasRoot.width = window.innerWidth * window.devicePixelRatio; window.canvasRoot.height = window.innerHeight * window.devicePixelRatio;
window.previousWidth = window.innerWidth; window.canvasRoot.style.width = window.innerWidth + 'px';
} window.canvasRoot.style.height = window.innerHeight + 'px';
if (window.previousHeight !== window.innerHeight) {
window.canvasRoot.height = window.innerHeight * window.devicePixelRatio;
window.previousHeight = window.innerHeight;
}
let ctx = window.canvasContext; let ctx = window.canvasContext;
let scale = window.devicePixelRatio; let scale = window.devicePixelRatio;
for (let i = 0; i < length; i++, arrayOffset += renderCommandSize) { for (let i = 0; i < length; i++, arrayOffset += renderCommandSize) {
let renderCommand = readStructAtAddress(arrayOffset, renderCommandDefinition); let renderCommand = readStructAtAddress(arrayOffset, renderCommandDefinition);
let boundingBox = renderCommand.boundingBox; let boundingBox = renderCommand.boundingBox;
switch (renderCommand.commandType.value) { switch(renderCommand.commandType.value) {
case (CLAY_RENDER_COMMAND_TYPE_NONE): { case (CLAY_RENDER_COMMAND_TYPE_NONE): {
break; break;
} }
@ -315,7 +324,7 @@
let config = readStructAtAddress(renderCommand.config.value, rectangleConfigDefinition); let config = readStructAtAddress(renderCommand.config.value, rectangleConfigDefinition);
let color = config.color; let color = config.color;
ctx.beginPath(); 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( window.canvasContext.roundRect(
boundingBox.x.value * scale, // x boundingBox.x.value * scale, // x
boundingBox.y.value * scale, // y boundingBox.y.value * scale, // y
@ -326,7 +335,8 @@
ctx.closePath(); ctx.closePath();
// Handle link clicks // 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; 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)) { memoryDataView.setUint32(0, renderCommand.id.value, true);
if (linkContents.length > 0 && (window.mouseDownThisFrame || window.touchDown) && instance.exports.Clay_PointerOver(0)) {
window.location.href = linkContents; window.location.href = linkContents;
} }
break; break;
@ -342,7 +352,7 @@
ctx.moveTo((boundingBox.x.value + halfLineWidth) * scale, (boundingBox.y.value + config.cornerRadius.topLeft.value + halfLineWidth) * scale); ctx.moveTo((boundingBox.x.value + halfLineWidth) * scale, (boundingBox.y.value + config.cornerRadius.topLeft.value + halfLineWidth) * scale);
let color = config.top.color; let color = config.top.color;
ctx.lineWidth = lineWidth * 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 + halfLineWidth) * scale, (boundingBox.x.value + config.cornerRadius.topLeft.value + halfLineWidth) * scale, (boundingBox.y.value + halfLineWidth) * scale, config.cornerRadius.topLeft.value * scale); 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(); ctx.stroke();
} }
@ -352,7 +362,7 @@
let halfLineWidth = lineWidth / 2; let halfLineWidth = lineWidth / 2;
let color = config.top.color; let color = config.top.color;
ctx.lineWidth = lineWidth * 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.moveTo((boundingBox.x.value + config.cornerRadius.topLeft.value + halfLineWidth) * scale, (boundingBox.y.value + halfLineWidth) * scale); 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.lineTo((boundingBox.x.value + boundingBox.width.value - config.cornerRadius.topRight.value - halfLineWidth) * scale, (boundingBox.y.value + halfLineWidth) * scale);
ctx.stroke(); ctx.stroke();
@ -364,7 +374,7 @@
ctx.moveTo((boundingBox.x.value + boundingBox.width.value - config.cornerRadius.topRight.value - halfLineWidth) * scale, (boundingBox.y.value + halfLineWidth) * scale); ctx.moveTo((boundingBox.x.value + boundingBox.width.value - config.cornerRadius.topRight.value - halfLineWidth) * scale, (boundingBox.y.value + halfLineWidth) * scale);
let color = config.top.color; let color = config.top.color;
ctx.lineWidth = lineWidth * 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 + 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.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(); ctx.stroke();
} }
@ -374,7 +384,7 @@
let lineWidth = config.right.width.value; let lineWidth = config.right.width.value;
let halfLineWidth = lineWidth / 2; let halfLineWidth = lineWidth / 2;
ctx.lineWidth = lineWidth * 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.moveTo((boundingBox.x.value + boundingBox.width.value - halfLineWidth) * scale, (boundingBox.y.value + config.cornerRadius.topRight.value + halfLineWidth) * scale); 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.lineTo((boundingBox.x.value + boundingBox.width.value - halfLineWidth) * scale, (boundingBox.y.value + boundingBox.height.value - config.cornerRadius.topRight.value - halfLineWidth) * scale);
ctx.stroke(); ctx.stroke();
@ -386,7 +396,7 @@
let halfLineWidth = lineWidth / 2; 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.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.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.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(); ctx.stroke();
} }
@ -396,7 +406,7 @@
let lineWidth = config.bottom.width.value; let lineWidth = config.bottom.width.value;
let halfLineWidth = lineWidth / 2; let halfLineWidth = lineWidth / 2;
ctx.lineWidth = lineWidth * 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.moveTo((boundingBox.x.value + config.cornerRadius.bottomLeft.value + halfLineWidth) * scale, (boundingBox.y.value + boundingBox.height.value - halfLineWidth) * scale); 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.lineTo((boundingBox.x.value + boundingBox.width.value - config.cornerRadius.bottomRight.value - halfLineWidth) * scale, (boundingBox.y.value + boundingBox.height.value - halfLineWidth) * scale);
ctx.stroke(); ctx.stroke();
@ -408,7 +418,7 @@
let halfLineWidth = lineWidth / 2; let halfLineWidth = lineWidth / 2;
ctx.moveTo((boundingBox.x.value + config.cornerRadius.bottomLeft.value + halfLineWidth) * scale, (boundingBox.y.value + boundingBox.height.value - halfLineWidth) * scale); ctx.moveTo((boundingBox.x.value + config.cornerRadius.bottomLeft.value + halfLineWidth) * scale, (boundingBox.y.value + boundingBox.height.value - halfLineWidth) * scale);
ctx.lineWidth = lineWidth * 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.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(); ctx.stroke();
} }
@ -418,7 +428,7 @@
let lineWidth = config.left.width.value; let lineWidth = config.left.width.value;
let halfLineWidth = lineWidth / 2; let halfLineWidth = lineWidth / 2;
ctx.lineWidth = lineWidth * 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.moveTo((boundingBox.x.value + halfLineWidth) * scale, (boundingBox.y.value + boundingBox.height.value - config.cornerRadius.bottomLeft.value - halfLineWidth) * scale); 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.lineTo((boundingBox.x.value + halfLineWidth) * scale, (boundingBox.y.value + config.cornerRadius.bottomRight.value + halfLineWidth) * scale);
ctx.stroke(); ctx.stroke();
@ -434,14 +444,16 @@
ctx.font = `${fontSize}px ${fontsById[config.fontId.value]}`; ctx.font = `${fontSize}px ${fontsById[config.fontId.value]}`;
let color = config.textColor; let color = config.textColor;
ctx.textBaseline = 'middle'; 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); ctx.fillText(textDecoder.decode(stringContents), boundingBox.x.value * scale, (boundingBox.y.value + boundingBox.height.value / 2 + 1) * scale);
break; break;
} }
case (CLAY_RENDER_COMMAND_TYPE_SCISSOR_START): { case (CLAY_RENDER_COMMAND_TYPE_SCISSOR_START): {
window.canvasContext.save();
window.canvasContext.beginPath(); window.canvasContext.beginPath();
window.canvasContext.rect(boundingBox.x.value * scale, boundingBox.y.value * scale, boundingBox.width.value * scale, boundingBox.height.value * scale); window.canvasContext.rect(boundingBox.x.value * scale, boundingBox.y.value * scale, boundingBox.width.value * scale, boundingBox.height.value * scale);
window.canvasContext.clip(); window.canvasContext.clip();
window.canvasContext.closePath();
break; break;
} }
case (CLAY_RENDER_COMMAND_TYPE_SCISSOR_END): { case (CLAY_RENDER_COMMAND_TYPE_SCISSOR_END): {

View File

@ -51,7 +51,7 @@
.text { .text {
pointer-events: all; pointer-events: all;
white-space: nowrap; white-space: pre;
} }
</style> </style>
</head> </head>
@ -279,12 +279,13 @@
document.addEventListener("keydown", (event) => { document.addEventListener("keydown", (event) => {
if (event.key === "ArrowDown") { if (event.key === "ArrowDown") {
console.log("arrowdown"); window.arrowKeyDownPressedThisFrame = true;
} }
if (event.key === "ArrowUp") { if (event.key === "ArrowUp") {
console.log("arrowup"); window.arrowKeyUpPressedThisFrame = true;
} }
}); });
const importObject = { const importObject = {
clay: { clay: {
measureTextFunction: (addressOfDimensions, textToMeasure, addressOfConfig) => { measureTextFunction: (addressOfDimensions, textToMeasure, addressOfConfig) => {
@ -361,7 +362,7 @@
let elementData = elementCache[renderCommand.id.value]; let elementData = elementCache[renderCommand.id.value];
element = elementData.element; element = elementData.element;
if (Array.prototype.indexOf.call(parentElement.element.children, element) !== parentElement.nextElementIndex) { if (Array.prototype.indexOf.call(parentElement.element.children, element) !== parentElement.nextElementIndex) {
if (parentElement.nextElementIndex === 0) { if (parentElement.nextElementIndex === 0 || !parentElement.element.childNodes[parentElement.nextElementIndex - 1]) {
parentElement.element.insertAdjacentElement('afterbegin', element); parentElement.element.insertAdjacentElement('afterbegin', element);
} else { } else {
parentElement.element.childNodes[parentElement.nextElementIndex - 1].insertAdjacentElement('afterend', element); parentElement.element.childNodes[parentElement.nextElementIndex - 1].insertAdjacentElement('afterend', element);
@ -390,7 +391,8 @@
let config = readStructAtAddress(renderCommand.config.value, rectangleConfigDefinition); let config = readStructAtAddress(renderCommand.config.value, rectangleConfigDefinition);
let configMemory = new Uint8Array(memoryDataView.buffer.slice(renderCommand.config.value, renderCommand.config.value + config.__size)); 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; 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.mouseDownThisFrame || window.touchDown) && instance.exports.Clay_PointerOver(renderCommand.id.value)) { memoryDataView.setUint32(0, renderCommand.id.value, true);
if (linkContents.length > 0 && (window.mouseDownThisFrame || window.touchDown) && instance.exports.Clay_PointerOver(0)) {
window.location.href = linkContents; window.location.href = linkContents;
} }
if (!dirty && !MemoryIsDifferent(configMemory, elementData.previousMemoryConfig, config.__size)) { if (!dirty && !MemoryIsDifferent(configMemory, elementData.previousMemoryConfig, config.__size)) {