mirror of
https://github.com/nicbarker/clay.git
synced 2025-01-23 18:06:04 +00:00
Debug Tools (#15)
This commit is contained in:
parent
b3d768c00d
commit
a4f90a217d
20
README.md
20
README.md
@ -371,7 +371,7 @@ The supported directives are:
|
||||
- `CLAY_DISABLE_CULLING` - Disables [Visibility Culling](#visibility-culling) of render commands.
|
||||
- `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_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_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.
|
||||
@ -384,6 +384,20 @@ There are also supported bindings for other languages, including:
|
||||
|
||||
- [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
|
||||
|
||||
### Naming Conventions
|
||||
@ -1422,13 +1436,13 @@ switch (renderCommand->commandType) {
|
||||
|
||||
`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()
|
||||
|
||||
`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
|
||||
|
||||
|
@ -57,6 +57,13 @@ BorderData :: struct {
|
||||
color: Color,
|
||||
}
|
||||
|
||||
ElementId :: struct {
|
||||
id: u32,
|
||||
offset: u32,
|
||||
baseId: u32,
|
||||
stringId: String,
|
||||
}
|
||||
|
||||
when ODIN_OS == .Windows {
|
||||
EnumBackingType :: u32
|
||||
} else {
|
||||
@ -79,12 +86,19 @@ RectangleElementConfig :: struct {
|
||||
cornerRadius: CornerRadius,
|
||||
}
|
||||
|
||||
TextWrapMode :: enum EnumBackingType {
|
||||
Words,
|
||||
Newlines,
|
||||
None,
|
||||
}
|
||||
|
||||
TextElementConfig :: struct {
|
||||
textColor: Color,
|
||||
fontId: u16,
|
||||
fontSize: u16,
|
||||
letterSpacing: u16,
|
||||
lineSpacing: u16,
|
||||
wrapMode: TextWrapMode,
|
||||
}
|
||||
|
||||
ImageElementConfig :: struct {
|
||||
@ -234,15 +248,17 @@ ClayArray :: struct($type: typeid) {
|
||||
foreign Clay {
|
||||
MinMemorySize :: proc() -> u32 ---
|
||||
CreateArenaWithCapacityAndMemory :: proc(capacity: u32, offset: [^]u8) -> Arena ---
|
||||
SetPointerPosition :: proc(position: Vector2) ---
|
||||
Initialize :: proc(arena: Arena) ---
|
||||
SetPointerState :: proc(position: Vector2, pointerDown: bool) ---
|
||||
Initialize :: proc(arena: Arena, layoutDimensions: Dimensions) ---
|
||||
UpdateScrollContainers :: proc(isPointerActive: bool, scrollDelta: Vector2, deltaTime: c.float) ---
|
||||
BeginLayout :: proc(screenWidth: c.int, screenHeight: c.int) ---
|
||||
EndLayout :: proc(screenWidth: c.int, screenHeight: c.int) -> ClayArray(RenderCommand) ---
|
||||
PointerOver :: proc(id: u32) -> bool ---
|
||||
GetScrollContainerData :: proc(id: u32) -> ScrollContainerData ---
|
||||
SetLayoutDimensions :: proc(dimensions: Dimensions) ---
|
||||
BeginLayout :: proc() ---
|
||||
EndLayout :: proc() -> ClayArray(RenderCommand) ---
|
||||
PointerOver :: proc(id: ElementId) -> bool ---
|
||||
GetScrollContainerData :: proc(id: ElementId) -> ScrollContainerData ---
|
||||
SetMeasureTextFunction :: proc(measureTextFunction: proc "c" (text: ^String, config: ^TextElementConfig) -> Dimensions) ---
|
||||
RenderCommandArray_Get :: proc(array: ^ClayArray(RenderCommand), index: i32) -> ^RenderCommand ---
|
||||
SetDebugModeEnabled :: proc(enabled: bool) ---
|
||||
}
|
||||
|
||||
@(private, link_prefix = "Clay_", default_calling_convention = "c")
|
||||
@ -259,14 +275,14 @@ foreign _ {
|
||||
|
||||
@(link_prefix = "Clay_", default_calling_convention = "c", private)
|
||||
foreign Clay {
|
||||
_OpenContainerElement :: proc(id: u32, layoutConfig: ^LayoutConfig) ---
|
||||
_OpenRectangleElement :: proc(id: u32, layoutConfig: ^LayoutConfig, rectangleConfig: ^RectangleElementConfig) ---
|
||||
_OpenTextElement :: proc(id: u32, text: String, textConfig: ^TextElementConfig) ---
|
||||
_OpenImageElement :: proc(id: u32, layoutConfig: ^LayoutConfig, imageConfig: ^ImageElementConfig) ---
|
||||
_OpenScrollElement :: proc(id: u32, layoutConfig: ^LayoutConfig, imageConfig: ^ScrollElementConfig) -> rawptr ---
|
||||
_OpenFloatingElement :: proc(id: u32, layoutConfig: ^LayoutConfig, imageConfig: ^FloatingElementConfig) -> rawptr ---
|
||||
_OpenBorderElement :: proc(id: u32, layoutConfig: ^LayoutConfig, imageConfig: ^BorderElementConfig) ---
|
||||
_OpenCustomElement :: proc(id: u32, layoutConfig: ^LayoutConfig, imageConfig: ^CustomElementConfig) ---
|
||||
_OpenContainerElement :: proc(id: ElementId, layoutConfig: ^LayoutConfig) ---
|
||||
_OpenRectangleElement :: proc(id: ElementId, layoutConfig: ^LayoutConfig, rectangleConfig: ^RectangleElementConfig) ---
|
||||
_OpenTextElement :: proc(id: ElementId, text: String, textConfig: ^TextElementConfig) ---
|
||||
_OpenImageElement :: proc(id: ElementId, layoutConfig: ^LayoutConfig, imageConfig: ^ImageElementConfig) ---
|
||||
_OpenScrollElement :: proc(id: ElementId, layoutConfig: ^LayoutConfig, imageConfig: ^ScrollElementConfig) ---
|
||||
_OpenFloatingElement :: proc(id: ElementId, layoutConfig: ^LayoutConfig, imageConfig: ^FloatingElementConfig) ---
|
||||
_OpenBorderElement :: proc(id: ElementId, layoutConfig: ^LayoutConfig, imageConfig: ^BorderElementConfig) ---
|
||||
_OpenCustomElement :: proc(id: ElementId, layoutConfig: ^LayoutConfig, imageConfig: ^CustomElementConfig) ---
|
||||
_CloseElementWithChildren :: proc() ---
|
||||
_CloseScrollElement :: proc() ---
|
||||
_CloseFloatingElement :: proc() ---
|
||||
@ -278,52 +294,52 @@ foreign Clay {
|
||||
_CustomElementConfigArray_Add :: proc(array: ^ClayArray(CustomElementConfig), config: CustomElementConfig) -> ^CustomElementConfig ---
|
||||
_ScrollElementConfigArray_Add :: proc(array: ^ClayArray(ScrollElementConfig), config: ScrollElementConfig) -> ^ScrollElementConfig ---
|
||||
_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)
|
||||
Container :: proc(id: u32, layoutConfig: ^LayoutConfig) -> bool {
|
||||
Container :: proc(id: ElementId, layoutConfig: ^LayoutConfig) -> bool {
|
||||
_OpenContainerElement(id, layoutConfig)
|
||||
return true
|
||||
}
|
||||
|
||||
@(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)
|
||||
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)
|
||||
return true
|
||||
}
|
||||
|
||||
@(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)
|
||||
return true
|
||||
}
|
||||
|
||||
@(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)
|
||||
return true
|
||||
}
|
||||
|
||||
@(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)
|
||||
return true
|
||||
}
|
||||
|
||||
@(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)
|
||||
return true
|
||||
}
|
||||
|
||||
@(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)
|
||||
return true
|
||||
}
|
||||
@ -412,6 +428,6 @@ MakeString :: proc(label: string) -> String {
|
||||
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)
|
||||
}
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
bindings/odin/clay-official-website
Executable file
BIN
bindings/odin/clay-official-website
Executable file
Binary file not shown.
@ -15,7 +15,8 @@ checkImage3: raylib.Texture2D = {}
|
||||
checkImage4: 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_48 :: 2
|
||||
FONT_ID_TITLE_36 :: 3
|
||||
@ -24,7 +25,6 @@ FONT_ID_BODY_36 :: 5
|
||||
FONT_ID_BODY_30 :: 6
|
||||
FONT_ID_BODY_28 :: 7
|
||||
FONT_ID_BODY_24 :: 8
|
||||
FONT_ID_BODY_16 :: 9
|
||||
|
||||
COLOR_LIGHT :: clay.Color{244, 235, 230, 255}
|
||||
COLOR_LIGHT_HOVER :: clay.Color{224, 215, 210, 255}
|
||||
@ -112,13 +112,15 @@ LandingPageDesktop :: proc() {
|
||||
LandingPageMobile :: proc() {
|
||||
if clay.Container(
|
||||
clay.ID("LandingPage1Mobile"),
|
||||
clay.Layout({
|
||||
clay.Layout(
|
||||
{
|
||||
layoutDirection = .TOP_TO_BOTTOM,
|
||||
sizing = {width = clay.SizingGrow({}), height = clay.SizingFit({min = cast(f32)windowHeight - 70})},
|
||||
childAlignment = {x = .CENTER, y = .CENTER},
|
||||
padding = {16, 32},
|
||||
childGap = 32,
|
||||
}),
|
||||
},
|
||||
),
|
||||
) {
|
||||
if clay.Container(clay.ID("LeftText"), clay.Layout({sizing = {width = clay.SizingGrow({})}, layoutDirection = .TOP_TO_BOTTOM, childGap = 8})) {
|
||||
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(
|
||||
id,
|
||||
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.Rectangle(
|
||||
clay.ID("RendererButtonInactiveInner", index),
|
||||
@ -377,11 +379,7 @@ RendererPage :: proc(titleTextConfig: clay.TextElementConfig, widthSizing: clay.
|
||||
clay.ID("RendererRightText"),
|
||||
clay.Layout({sizing = {width = widthSizing}, childAlignment = {x = .CENTER}, layoutDirection = .TOP_TO_BOTTOM, childGap = 16}),
|
||||
) {
|
||||
clay.Text(
|
||||
clay.ID("RendererTextRightTitle"),
|
||||
"Try changing renderer!",
|
||||
clay.TextConfig({fontSize = 36, fontId = FONT_ID_BODY_36, textColor = COLOR_ORANGE}),
|
||||
)
|
||||
clay.Text(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})}})) {}
|
||||
RendererButtonActive(clay.ID("RendererSelectButtonActive", 0), 0, "Raylib Renderer")
|
||||
}
|
||||
@ -405,13 +403,15 @@ RendererPageDesktop :: proc() {
|
||||
RendererPageMobile :: proc() {
|
||||
if clay.Rectangle(
|
||||
clay.ID("RendererMobile"),
|
||||
clay.Layout({
|
||||
clay.Layout(
|
||||
{
|
||||
layoutDirection = .TOP_TO_BOTTOM,
|
||||
sizing = {clay.SizingGrow({}), clay.SizingFit({min = cast(f32)windowHeight - 50})},
|
||||
childAlignment = {x = .CENTER, y = .CENTER},
|
||||
padding = {x = 16, y = 32},
|
||||
childGap = 32,
|
||||
}),
|
||||
},
|
||||
),
|
||||
clay.RectangleConfig({color = COLOR_LIGHT}),
|
||||
) {
|
||||
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) {
|
||||
mobileScreen := windowWidth < 750
|
||||
clay.BeginLayout(windowWidth, windowHeight)
|
||||
clay.BeginLayout()
|
||||
if clay.Rectangle(
|
||||
clay.ID("OuterContainer"),
|
||||
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}}))
|
||||
}
|
||||
}
|
||||
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.Rectangle(
|
||||
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) {
|
||||
@ -510,7 +510,7 @@ main :: proc() {
|
||||
memory := make([^]u8, minMemorySize)
|
||||
arena: clay.Arena = clay.CreateArenaWithCapacityAndMemory(minMemorySize, memory)
|
||||
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.InitWindow(windowWidth, windowHeight, "Raylib Odin Example")
|
||||
@ -533,6 +533,8 @@ main :: proc() {
|
||||
checkImage4 = raylib.LoadTextureFromImage(raylib.LoadImage("resources/check_4.png"))
|
||||
checkImage5 = raylib.LoadTextureFromImage(raylib.LoadImage("resources/check_5.png"))
|
||||
|
||||
debugModeEnabled: bool = false
|
||||
|
||||
for !raylib.WindowShouldClose() {
|
||||
defer free_all(context.temp_allocator)
|
||||
|
||||
@ -542,8 +544,13 @@ main :: proc() {
|
||||
}
|
||||
windowWidth = raylib.GetScreenWidth()
|
||||
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.SetLayoutDimensions({cast(f32)raylib.GetScreenWidth(), cast(f32)raylib.GetScreenHeight()})
|
||||
renderCommands: clay.ClayArray(clay.RenderCommand) = createLayout(animationLerpValue < 0 ? (animationLerpValue + 1) : (1 - animationLerpValue))
|
||||
raylib.BeginDrawing()
|
||||
clayRaylibRender(&renderCommands)
|
||||
|
@ -26,7 +26,7 @@ measureText :: proc "c" (text: ^clay.String, config: ^clay.TextElementConfig) ->
|
||||
textHeight := cast(f32)config.fontSize
|
||||
fontToUse := raylibFonts[config.fontId].font
|
||||
|
||||
for i in 0..<int(text.length) {
|
||||
for i in 0 ..< int(text.length) {
|
||||
if (text.chars[i] == '\n') {
|
||||
maxTextWidth = max(maxTextWidth, lineTextWidth)
|
||||
lineTextWidth = 0
|
||||
@ -49,7 +49,7 @@ measureText :: proc "c" (text: ^clay.String, config: ^clay.TextElementConfig) ->
|
||||
}
|
||||
|
||||
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)
|
||||
boundingBox := renderCommand.boundingBox
|
||||
switch (renderCommand.commandType) {
|
||||
@ -85,20 +85,9 @@ clayRaylibRender :: proc(renderCommands: ^clay.ClayArray(clay.RenderCommand), al
|
||||
config: ^clay.RectangleElementConfig = renderCommand.config.rectangleElementConfig
|
||||
if (config.cornerRadius.topLeft > 0) {
|
||||
radius: f32 = (config.cornerRadius.topLeft * 2) / min(boundingBox.width, boundingBox.height)
|
||||
raylib.DrawRectangleRounded(
|
||||
raylib.Rectangle{boundingBox.x, boundingBox.y, boundingBox.width, boundingBox.height},
|
||||
radius,
|
||||
8,
|
||||
clayColorToRaylibColor(config.color),
|
||||
)
|
||||
raylib.DrawRectangleRounded(raylib.Rectangle{boundingBox.x, boundingBox.y, boundingBox.width, boundingBox.height}, radius, 8, clayColorToRaylibColor(config.color))
|
||||
} else {
|
||||
raylib.DrawRectangle(
|
||||
cast(i32)boundingBox.x,
|
||||
cast(i32)boundingBox.y,
|
||||
cast(i32)boundingBox.width,
|
||||
cast(i32)boundingBox.height,
|
||||
clayColorToRaylibColor(config.color),
|
||||
)
|
||||
raylib.DrawRectangle(cast(i32)boundingBox.x, cast(i32)boundingBox.y, cast(i32)boundingBox.width, cast(i32)boundingBox.height, clayColorToRaylibColor(config.color))
|
||||
}
|
||||
case clay.RenderCommandType.Border:
|
||||
config := renderCommand.config.borderElementConfig
|
||||
@ -166,10 +155,7 @@ clayRaylibRender :: proc(renderCommands: ^clay.ClayArray(clay.RenderCommand), al
|
||||
}
|
||||
if (config.cornerRadius.bottomLeft > 0) {
|
||||
raylib.DrawRing(
|
||||
raylib.Vector2 {
|
||||
math.round(boundingBox.x + config.cornerRadius.bottomLeft),
|
||||
math.round(boundingBox.y + boundingBox.height - config.cornerRadius.bottomLeft),
|
||||
},
|
||||
raylib.Vector2{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),
|
||||
config.cornerRadius.bottomLeft,
|
||||
90,
|
||||
|
@ -2,6 +2,7 @@ mkdir -p build/clay \
|
||||
&& clang \
|
||||
-Os \
|
||||
-DCLAY_WASM \
|
||||
-DCLAY_DEBUG \
|
||||
-mbulk-memory \
|
||||
--target=wasm32 \
|
||||
-nostdlib \
|
||||
|
BIN
examples/clay-official-website/images/debugger.png
Normal file
BIN
examples/clay-official-website/images/debugger.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 296 KiB |
@ -13,6 +13,7 @@
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
pointer-events: none;
|
||||
background: rgb(244, 235, 230);
|
||||
}
|
||||
/* Import the font using @font-face */
|
||||
@font-face {
|
||||
@ -48,7 +49,7 @@
|
||||
|
||||
.text {
|
||||
pointer-events: all;
|
||||
white-space: nowrap;
|
||||
white-space: pre;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
@ -63,14 +64,14 @@
|
||||
const CLAY_RENDER_COMMAND_TYPE_CUSTOM = 7;
|
||||
const GLOBAL_FONT_SCALING_FACTOR = 0.8;
|
||||
let renderCommandSize = 0;
|
||||
let scratchSpaceAddress = 0;
|
||||
let scratchSpaceAddress = 8;
|
||||
let heapSpaceAddress = 0;
|
||||
let memoryDataView;
|
||||
let textDecoder = new TextDecoder("utf-8");
|
||||
let previousFrameTime;
|
||||
let fontsById = [
|
||||
'Calistoga',
|
||||
'Quicksand',
|
||||
'Calistoga',
|
||||
'Quicksand',
|
||||
'Quicksand',
|
||||
'Quicksand',
|
||||
@ -117,6 +118,7 @@
|
||||
{ name: 'fontSize', type: 'uint16_t' },
|
||||
{ name: 'letterSpacing', type: 'uint16_t' },
|
||||
{ name: 'lineSpacing', type: 'uint16_t' },
|
||||
{ name: 'wrapMode', type: 'uint32_t' },
|
||||
{ name: 'disablePointerEvents', type: 'uint8_t' }
|
||||
]};
|
||||
let imageConfigDefinition = { name: 'image', type: 'struct', members: [
|
||||
@ -212,6 +214,18 @@
|
||||
instance.exports.Clay_CreateArenaWithCapacityAndMemory(arenaStructAddress, memorySize, arenaMemoryAddress);
|
||||
}
|
||||
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.canvasRoot = document.body.appendChild(document.createElement('canvas'));
|
||||
window.canvasContext = window.canvasRoot.getContext("2d");
|
||||
@ -224,7 +238,7 @@
|
||||
window.arrowKeyUpPressedThisFrame = false;
|
||||
let zeroTimeout = null;
|
||||
addEventListener("wheel", (event) => {
|
||||
window.mouseWheelXThisFrame = event.deltaX * 0.1;
|
||||
window.mouseWheelXThisFrame = event.deltaX * -0.1;
|
||||
window.mouseWheelYThisFrame = event.deltaY * -0.1;
|
||||
clearTimeout(zeroTimeout);
|
||||
zeroTimeout = setTimeout(() => {
|
||||
@ -270,6 +284,9 @@
|
||||
if (event.key === "ArrowUp") {
|
||||
window.arrowKeyUpPressedThisFrame = true;
|
||||
}
|
||||
if (event.key === "d") {
|
||||
window.dKeyPressedThisFrame = true;
|
||||
}
|
||||
});
|
||||
|
||||
const importObject = {
|
||||
@ -293,7 +310,9 @@
|
||||
let arenaAddress = scratchSpaceAddress;
|
||||
window.instance = instance;
|
||||
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);
|
||||
renderLoop();
|
||||
}
|
||||
@ -326,7 +345,9 @@
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CLAY_RENDER_COMMAND_TYPE_IMAGE: { elementType = 'img'; break; }
|
||||
case CLAY_RENDER_COMMAND_TYPE_IMAGE: {
|
||||
elementType = 'img'; break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
element = document.createElement(elementType);
|
||||
@ -349,7 +370,7 @@
|
||||
if (parentElement.nextElementIndex === 0) {
|
||||
parentElement.element.insertAdjacentElement('afterbegin', element);
|
||||
} 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 configMemory = new Uint8Array(memoryDataView.buffer.slice(renderCommand.config.value, renderCommand.config.value + config.__size));
|
||||
let linkContents = config.link.length.value > 0 ? textDecoder.decode(new Uint8Array(memoryDataView.buffer.slice(config.link.chars.value, config.link.chars.value + config.link.length.value))) : 0;
|
||||
if (linkContents.length > 0 && (window.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;
|
||||
}
|
||||
if (!dirty && !MemoryIsDifferent(configMemory, elementData.previousMemoryConfig, config.__size)) {
|
||||
@ -504,8 +526,8 @@
|
||||
let arrayOffset = memoryDataView.getUint32(scratchSpaceAddress + 8, true);
|
||||
window.canvasRoot.width = window.innerWidth * window.devicePixelRatio;
|
||||
window.canvasRoot.height = window.innerHeight * window.devicePixelRatio;
|
||||
window.canvasRoot.style.width = window.innerWidth;
|
||||
window.canvasRoot.style.height = window.innerHeight;
|
||||
window.canvasRoot.style.width = window.innerWidth + 'px';
|
||||
window.canvasRoot.style.height = window.innerHeight + 'px';
|
||||
let ctx = window.canvasContext;
|
||||
let scale = window.devicePixelRatio;
|
||||
for (let i = 0; i < length; i++, arrayOffset += renderCommandSize) {
|
||||
@ -530,7 +552,8 @@
|
||||
ctx.closePath();
|
||||
// Handle link clicks
|
||||
let linkContents = config.link.length.value > 0 ? textDecoder.decode(new Uint8Array(memoryDataView.buffer.slice(config.link.chars.value, config.link.chars.value + config.link.length.value))) : 0;
|
||||
if (linkContents.length > 0 && (window.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;
|
||||
}
|
||||
break;
|
||||
@ -643,9 +666,11 @@
|
||||
break;
|
||||
}
|
||||
case (CLAY_RENDER_COMMAND_TYPE_SCISSOR_START): {
|
||||
window.canvasContext.save();
|
||||
window.canvasContext.beginPath();
|
||||
window.canvasContext.rect(boundingBox.x.value * scale, boundingBox.y.value * scale, boundingBox.width.value * scale, boundingBox.height.value * scale);
|
||||
window.canvasContext.clip();
|
||||
window.canvasContext.closePath();
|
||||
break;
|
||||
}
|
||||
case (CLAY_RENDER_COMMAND_TYPE_SCISSOR_END): {
|
||||
@ -676,7 +701,7 @@
|
||||
const elapsed = currentTime - previousFrameTime;
|
||||
previousFrameTime = currentTime;
|
||||
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;
|
||||
switch (activeRendererIndex) {
|
||||
case 0: {
|
||||
@ -701,6 +726,7 @@
|
||||
window.mouseDownThisFrame = false;
|
||||
window.arrowKeyUpPressedThisFrame = false;
|
||||
window.arrowKeyDownPressedThisFrame = false;
|
||||
window.dKeyPressedThisFrame = false;
|
||||
}
|
||||
init();
|
||||
</script>
|
||||
|
@ -7,9 +7,9 @@ double windowWidth = 1024, windowHeight = 768;
|
||||
float modelPageOneZRotation = 0;
|
||||
int ACTIVE_RENDERER_INDEX = 0;
|
||||
|
||||
const uint32_t FONT_ID_TITLE_56 = 0;
|
||||
const uint32_t FONT_ID_BODY_24 = 1;
|
||||
const uint32_t FONT_ID_BODY_16 = 2;
|
||||
const uint32_t FONT_ID_BODY_16 = 0;
|
||||
const uint32_t FONT_ID_TITLE_56 = 1;
|
||||
const uint32_t FONT_ID_BODY_24 = 2;
|
||||
const uint32_t FONT_ID_BODY_36 = 3;
|
||||
const uint32_t FONT_ID_TITLE_36 = 4;
|
||||
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_BUTTON_HOVER = (Clay_Color) {238, 227, 225, 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_HOVER = (Clay_Color) {148, 46, 8, 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_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_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_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("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_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_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_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_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_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_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", 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));
|
||||
@ -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_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_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", 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));
|
||||
@ -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_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_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));
|
||||
@ -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_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_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", 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_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_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) {
|
||||
RendererButtonActive(CLAY_IDI("RendererSelectButtonActive", 0), 0, CLAY_STRING("HTML 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_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_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", 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_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_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) {
|
||||
RendererButtonActive(CLAY_IDI("RendererSelectButtonActive", 0), 0, CLAY_STRING("HTML 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
|
||||
{
|
||||
Clay_Vector2 clickOrigin;
|
||||
@ -284,9 +299,8 @@ typedef struct
|
||||
ScrollbarData scrollbarData = (ScrollbarData) {};
|
||||
float animationLerpValue = -1.0f;
|
||||
|
||||
Clay_RenderCommandArray CreateLayout(float lerpValue) {
|
||||
bool mobileScreen = windowWidth < 750;
|
||||
Clay_BeginLayout((int)windowWidth, (int)windowHeight);
|
||||
Clay_RenderCommandArray CreateLayout(bool mobileScreen, float lerpValue) {
|
||||
Clay_BeginLayout();
|
||||
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_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}));
|
||||
});
|
||||
}
|
||||
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_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}));
|
||||
@ -327,6 +341,7 @@ Clay_RenderCommandArray CreateLayout(float lerpValue) {
|
||||
DeclarativeSyntaxPageDesktop();
|
||||
HighPerformancePageDesktop(lerpValue);
|
||||
RendererPageDesktop();
|
||||
DebuggerPageDesktop();
|
||||
}
|
||||
});
|
||||
});
|
||||
@ -342,16 +357,19 @@ Clay_RenderCommandArray CreateLayout(float lerpValue) {
|
||||
scrollbarColor = (Clay_Color){225, 138, 50, 160};
|
||||
}
|
||||
float scrollHeight = scrollData.scrollContainerDimensions.height - 12;
|
||||
CLAY_FLOATING_CONTAINER(CLAY_ID("ScrollBar"), &CLAY_LAYOUT_DEFAULT, CLAY_FLOATING_CONFIG(.offset = { .x = -6, .y = -(scrollData.scrollPosition->y / scrollData.contentDimensions.height) * scrollHeight + 6}, .zIndex = 1, .parentId = CLAY_ID("OuterScrollContainer"), .attachment = {.element = CLAY_ATTACH_POINT_RIGHT_TOP, .parent = CLAY_ATTACH_POINT_RIGHT_TOP}), {
|
||||
CLAY_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), {});
|
||||
});
|
||||
}
|
||||
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;
|
||||
windowHeight = height;
|
||||
Clay_SetLayoutDimensions((Clay_Dimensions) { width, height });
|
||||
if (deltaTime == deltaTime) { // NaN propagation can cause pain here
|
||||
animationLerpValue += deltaTime;
|
||||
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 (Clay_PointerOver(CLAY_ID("RendererSelectButtonHTML"))) {
|
||||
ACTIVE_RENDERER_INDEX = 0;
|
||||
@ -366,9 +389,10 @@ CLAY_WASM_EXPORT("UpdateDrawFrame") Clay_RenderCommandArray UpdateDrawFrame(floa
|
||||
ACTIVE_RENDERER_INDEX = 1;
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
// Handle scroll containers
|
||||
Clay_SetPointerPosition((Clay_Vector2) {mousePositionX, mousePositionY});
|
||||
|
||||
Clay__debugViewHighlightColor = (Clay_Color) {105,210,231, 120};
|
||||
|
||||
Clay_SetPointerState((Clay_Vector2) {mousePositionX, mousePositionY}, isMouseDown);
|
||||
|
||||
if (!isMouseDown) {
|
||||
scrollbarData.mouseDown = false;
|
||||
@ -408,7 +432,11 @@ CLAY_WASM_EXPORT("UpdateDrawFrame") Clay_RenderCommandArray UpdateDrawFrame(floa
|
||||
}
|
||||
|
||||
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));
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
|
@ -20,7 +20,7 @@ set(CMAKE_C_STANDARD 99)
|
||||
|
||||
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_link_libraries(clay_examples_raylib_sidebar_scrolling_container PUBLIC raylib)
|
||||
|
@ -14,7 +14,7 @@ Clay_TextElementConfig headerTextConfig = (Clay_TextElementConfig) { .fontId = F
|
||||
|
||||
// Examples of re-usable "Components"
|
||||
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_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_TextElementConfig dropdownTextElementConfig = (Clay_TextElementConfig) { .fontSize = 24, .textColor = {255,255,255,255} };
|
||||
|
||||
void RenderDropdownTextItem() {
|
||||
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_TEXT(CLAY_ID("ScrollContainerText"), CLAY_STRING("I'm a text field in a scroll container."), &dropdownTextElementConfig);
|
||||
void RenderDropdownTextItem(int index) {
|
||||
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_IDI("ScrollContainerText", index), CLAY_STRING("I'm a text field in a scroll container."), &dropdownTextElementConfig);
|
||||
});
|
||||
}
|
||||
|
||||
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("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}), {
|
||||
@ -52,20 +52,22 @@ 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_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_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_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}));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
CLAY_TEXT(CLAY_ID("BodyText1"),
|
||||
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_RECTANGLE(CLAY_ID("Photos"), 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("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("Picture3"), 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("Photos2"), CLAY_LAYOUT(.childGap = 16, .padding = { 16, 16 }), CLAY_RECTANGLE_CONFIG(.color = {180, 180, 220, 255}), {
|
||||
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("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("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"),
|
||||
@ -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_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_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_TEXT(CLAY_ID("ProfileTitle"), CLAY_STRING("Image caption below"), CLAY_TEXT_CONFIG(.fontSize = 24, .textColor = {0,0,0,255}));
|
||||
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("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}), {});
|
||||
});
|
||||
@ -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_FLOATING_CONTAINER(CLAY_ID("FloatingContainer"), 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_TEXT(CLAY_ID("FloatingContainerText"), CLAY_STRING("I'm an inline floating container."), CLAY_TEXT_CONFIG(.fontSize = 24, .textColor = {255,255,255,255}));
|
||||
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_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}), {
|
||||
for (int i = 0; i < 100; i++) {
|
||||
RenderDropdownTextItem();
|
||||
}
|
||||
// for (int i = 0; i < 100; i++) {
|
||||
// RenderDropdownTextItem(i);
|
||||
// }
|
||||
});
|
||||
});
|
||||
});
|
||||
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}), {});
|
||||
});
|
||||
});
|
||||
return Clay_EndLayout(GetScreenWidth(), GetScreenHeight());
|
||||
return Clay_EndLayout();
|
||||
}
|
||||
|
||||
typedef struct
|
||||
@ -123,16 +125,23 @@ typedef struct
|
||||
|
||||
ScrollbarData scrollbarData = (ScrollbarData) {};
|
||||
|
||||
bool debugEnabled = false;
|
||||
|
||||
void UpdateDrawFrame(void)
|
||||
{
|
||||
float mouseWheelX = 0, mouseWheelY = 0;
|
||||
Vector2 mouseWheelDelta = GetMouseWheelMoveV();
|
||||
mouseWheelX = mouseWheelDelta.x;
|
||||
mouseWheelY = mouseWheelDelta.y;
|
||||
float mouseWheelX = mouseWheelDelta.x;
|
||||
float mouseWheelY = mouseWheelDelta.y;
|
||||
|
||||
if (IsKeyPressed(KEY_D)) {
|
||||
debugEnabled = !debugEnabled;
|
||||
Clay_SetDebugModeEnabled(debugEnabled);
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
// Handle scroll containers
|
||||
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)) {
|
||||
scrollbarData.mouseDown = false;
|
||||
}
|
||||
@ -166,6 +175,7 @@ void UpdateDrawFrame(void)
|
||||
// RENDERING ---------------------------------
|
||||
// currentTime = GetTime();
|
||||
BeginDrawing();
|
||||
ClearBackground(BLACK);
|
||||
Clay_Raylib_Render(renderCommands);
|
||||
EndDrawing();
|
||||
// printf("render time: %f ms\n", (GetTime() - currentTime) * 1000);
|
||||
@ -177,7 +187,7 @@ int main(void) {
|
||||
uint64_t totalMemorySize = Clay_MinMemorySize();
|
||||
Clay_Arena clayMemory = (Clay_Arena) { .label = CLAY_STRING("Clay Memory Arena"), .memory = malloc(totalMemorySize), .capacity = totalMemorySize };
|
||||
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);
|
||||
profilePicture = LoadTextureFromImage(LoadImage("resources/profile-picture.png"));
|
||||
Raylib_fonts[FONT_ID_BODY_24] = (Raylib_Font) {
|
||||
|
@ -3,7 +3,9 @@ void $NAME$_Set($NAME$ *array, int index, $TYPE$ value) {
|
||||
array->internalArray[index] = value;
|
||||
array->length = index < array->length ? array->length : index + 1;
|
||||
} 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
|
||||
raise(SIGTRAP);
|
||||
#endif
|
||||
|
@ -102,6 +102,7 @@ static inline Clay_Dimensions Raylib_MeasureText(Clay_String *text, Clay_TextEle
|
||||
|
||||
float textHeight = config->fontSize;
|
||||
Font fontToUse = Raylib_fonts[config->fontId].font;
|
||||
float scaleFactor = config->fontSize/(float)fontToUse.baseSize;
|
||||
|
||||
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);
|
||||
|
||||
textSize.width = maxTextWidth / 2;
|
||||
textSize.width = maxTextWidth * scaleFactor;
|
||||
textSize.height = textHeight;
|
||||
|
||||
return textSize;
|
||||
@ -170,7 +171,7 @@ void Clay_Raylib_Render(Clay_RenderCommandArray renderCommands)
|
||||
case CLAY_RENDER_COMMAND_TYPE_RECTANGLE: {
|
||||
Clay_RectangleElementConfig *config = renderCommand->config.rectangleElementConfig;
|
||||
if (config->cornerRadius.topLeft > 0) {
|
||||
float radius = (config->cornerRadius.topLeft * 2) / (boundingBox.width > boundingBox.height) ? boundingBox.height : boundingBox.width;
|
||||
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));
|
||||
} else {
|
||||
DrawRectangle(boundingBox.x, boundingBox.y, boundingBox.width, boundingBox.height, CLAY_COLOR_TO_RAYLIB_COLOR(config->color));
|
||||
|
@ -111,6 +111,7 @@
|
||||
{ name: 'fontSize', type: 'uint16_t' },
|
||||
{ name: 'letterSpacing', type: 'uint16_t' },
|
||||
{ name: 'lineSpacing', type: 'uint16_t' },
|
||||
{ name: 'wrapMode', type: 'uint32_t' },
|
||||
{ name: 'disablePointerEvents', type: 'uint8_t' }
|
||||
]
|
||||
};
|
||||
@ -259,6 +260,18 @@
|
||||
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 = {
|
||||
clay: {
|
||||
measureTextFunction: (addressOfDimensions, textToMeasure, addressOfConfig) => {
|
||||
@ -294,20 +307,16 @@
|
||||
let capacity = memoryDataView.getUint32(scratchSpaceAddress, true);
|
||||
let length = memoryDataView.getUint32(scratchSpaceAddress + 4, true);
|
||||
let arrayOffset = memoryDataView.getUint32(scratchSpaceAddress + 8, true);
|
||||
if (window.previousWidth !== window.innerWidth) {
|
||||
window.canvasRoot.width = window.innerWidth * window.devicePixelRatio;
|
||||
window.previousWidth = window.innerWidth;
|
||||
}
|
||||
if (window.previousHeight !== window.innerHeight) {
|
||||
window.canvasRoot.height = window.innerHeight * window.devicePixelRatio;
|
||||
window.previousHeight = window.innerHeight;
|
||||
}
|
||||
window.canvasRoot.style.width = window.innerWidth + 'px';
|
||||
window.canvasRoot.style.height = window.innerHeight + 'px';
|
||||
let ctx = window.canvasContext;
|
||||
let scale = window.devicePixelRatio;
|
||||
for (let i = 0; i < length; i++, arrayOffset += renderCommandSize) {
|
||||
let renderCommand = readStructAtAddress(arrayOffset, renderCommandDefinition);
|
||||
let boundingBox = renderCommand.boundingBox;
|
||||
switch (renderCommand.commandType.value) {
|
||||
switch(renderCommand.commandType.value) {
|
||||
case (CLAY_RENDER_COMMAND_TYPE_NONE): {
|
||||
break;
|
||||
}
|
||||
@ -315,7 +324,7 @@
|
||||
let config = readStructAtAddress(renderCommand.config.value, rectangleConfigDefinition);
|
||||
let color = config.color;
|
||||
ctx.beginPath();
|
||||
window.canvasContext.fillStyle = `rgba(${color.r.value}, ${color.g.value}, ${color.b.value}, ${color.a.value})`;
|
||||
window.canvasContext.fillStyle = `rgba(${color.r.value}, ${color.g.value}, ${color.b.value}, ${color.a.value / 255})`;
|
||||
window.canvasContext.roundRect(
|
||||
boundingBox.x.value * scale, // x
|
||||
boundingBox.y.value * scale, // y
|
||||
@ -326,7 +335,8 @@
|
||||
ctx.closePath();
|
||||
// Handle link clicks
|
||||
let linkContents = config.link.length.value > 0 ? textDecoder.decode(new Uint8Array(memoryDataView.buffer.slice(config.link.chars.value, config.link.chars.value + config.link.length.value))) : 0;
|
||||
if (linkContents.length > 0 && (window.mouseDown || window.touchDown) && instance.exports.Clay_PointerOver(renderCommand.id.value)) {
|
||||
memoryDataView.setUint32(0, renderCommand.id.value, true);
|
||||
if (linkContents.length > 0 && (window.mouseDownThisFrame || window.touchDown) && instance.exports.Clay_PointerOver(0)) {
|
||||
window.location.href = linkContents;
|
||||
}
|
||||
break;
|
||||
@ -342,7 +352,7 @@
|
||||
ctx.moveTo((boundingBox.x.value + halfLineWidth) * scale, (boundingBox.y.value + config.cornerRadius.topLeft.value + halfLineWidth) * scale);
|
||||
let color = config.top.color;
|
||||
ctx.lineWidth = lineWidth * scale;
|
||||
ctx.strokeStyle = `rgba(${color.r.value}, ${color.g.value}, ${color.b.value}, ${color.a.value})`;
|
||||
ctx.strokeStyle = `rgba(${color.r.value}, ${color.g.value}, ${color.b.value}, ${color.a.value / 255})`;
|
||||
ctx.arcTo((boundingBox.x.value + halfLineWidth) * scale, (boundingBox.y.value + halfLineWidth) * scale, (boundingBox.x.value + config.cornerRadius.topLeft.value + halfLineWidth) * scale, (boundingBox.y.value + halfLineWidth) * scale, config.cornerRadius.topLeft.value * scale);
|
||||
ctx.stroke();
|
||||
}
|
||||
@ -352,7 +362,7 @@
|
||||
let halfLineWidth = lineWidth / 2;
|
||||
let color = config.top.color;
|
||||
ctx.lineWidth = lineWidth * scale;
|
||||
ctx.strokeStyle = `rgba(${color.r.value}, ${color.g.value}, ${color.b.value}, ${color.a.value})`;
|
||||
ctx.strokeStyle = `rgba(${color.r.value}, ${color.g.value}, ${color.b.value}, ${color.a.value / 255})`;
|
||||
ctx.moveTo((boundingBox.x.value + config.cornerRadius.topLeft.value + halfLineWidth) * scale, (boundingBox.y.value + halfLineWidth) * scale);
|
||||
ctx.lineTo((boundingBox.x.value + boundingBox.width.value - config.cornerRadius.topRight.value - halfLineWidth) * scale, (boundingBox.y.value + halfLineWidth) * scale);
|
||||
ctx.stroke();
|
||||
@ -364,7 +374,7 @@
|
||||
ctx.moveTo((boundingBox.x.value + boundingBox.width.value - config.cornerRadius.topRight.value - halfLineWidth) * scale, (boundingBox.y.value + halfLineWidth) * scale);
|
||||
let color = config.top.color;
|
||||
ctx.lineWidth = lineWidth * scale;
|
||||
ctx.strokeStyle = `rgba(${color.r.value}, ${color.g.value}, ${color.b.value}, ${color.a.value})`;
|
||||
ctx.strokeStyle = `rgba(${color.r.value}, ${color.g.value}, ${color.b.value}, ${color.a.value / 255})`;
|
||||
ctx.arcTo((boundingBox.x.value + boundingBox.width.value - halfLineWidth) * scale, (boundingBox.y.value + halfLineWidth) * scale, (boundingBox.x.value + boundingBox.width.value - halfLineWidth) * scale, (boundingBox.y.value + config.cornerRadius.topRight.value + halfLineWidth) * scale, config.cornerRadius.topRight.value * scale);
|
||||
ctx.stroke();
|
||||
}
|
||||
@ -374,7 +384,7 @@
|
||||
let lineWidth = config.right.width.value;
|
||||
let halfLineWidth = lineWidth / 2;
|
||||
ctx.lineWidth = lineWidth * scale;
|
||||
ctx.strokeStyle = `rgba(${color.r.value}, ${color.g.value}, ${color.b.value}, ${color.a.value})`;
|
||||
ctx.strokeStyle = `rgba(${color.r.value}, ${color.g.value}, ${color.b.value}, ${color.a.value / 255})`;
|
||||
ctx.moveTo((boundingBox.x.value + boundingBox.width.value - halfLineWidth) * scale, (boundingBox.y.value + config.cornerRadius.topRight.value + halfLineWidth) * scale);
|
||||
ctx.lineTo((boundingBox.x.value + boundingBox.width.value - halfLineWidth) * scale, (boundingBox.y.value + boundingBox.height.value - config.cornerRadius.topRight.value - halfLineWidth) * scale);
|
||||
ctx.stroke();
|
||||
@ -386,7 +396,7 @@
|
||||
let halfLineWidth = lineWidth / 2;
|
||||
ctx.moveTo((boundingBox.x.value + boundingBox.width.value - halfLineWidth) * scale, (boundingBox.y.value + boundingBox.height.value - config.cornerRadius.bottomRight.value - halfLineWidth) * scale);
|
||||
ctx.lineWidth = lineWidth * scale;
|
||||
ctx.strokeStyle = `rgba(${color.r.value}, ${color.g.value}, ${color.b.value}, ${color.a.value})`;
|
||||
ctx.strokeStyle = `rgba(${color.r.value}, ${color.g.value}, ${color.b.value}, ${color.a.value / 255})`;
|
||||
ctx.arcTo((boundingBox.x.value + boundingBox.width.value - halfLineWidth) * scale, (boundingBox.y.value + boundingBox.height.value - halfLineWidth) * scale, (boundingBox.x.value + boundingBox.width.value - config.cornerRadius.bottomRight.value - halfLineWidth) * scale, (boundingBox.y.value + boundingBox.height.value - halfLineWidth) * scale, config.cornerRadius.bottomRight.value * scale);
|
||||
ctx.stroke();
|
||||
}
|
||||
@ -396,7 +406,7 @@
|
||||
let lineWidth = config.bottom.width.value;
|
||||
let halfLineWidth = lineWidth / 2;
|
||||
ctx.lineWidth = lineWidth * scale;
|
||||
ctx.strokeStyle = `rgba(${color.r.value}, ${color.g.value}, ${color.b.value}, ${color.a.value})`;
|
||||
ctx.strokeStyle = `rgba(${color.r.value}, ${color.g.value}, ${color.b.value}, ${color.a.value / 255})`;
|
||||
ctx.moveTo((boundingBox.x.value + config.cornerRadius.bottomLeft.value + halfLineWidth) * scale, (boundingBox.y.value + boundingBox.height.value - halfLineWidth) * scale);
|
||||
ctx.lineTo((boundingBox.x.value + boundingBox.width.value - config.cornerRadius.bottomRight.value - halfLineWidth) * scale, (boundingBox.y.value + boundingBox.height.value - halfLineWidth) * scale);
|
||||
ctx.stroke();
|
||||
@ -408,7 +418,7 @@
|
||||
let halfLineWidth = lineWidth / 2;
|
||||
ctx.moveTo((boundingBox.x.value + config.cornerRadius.bottomLeft.value + halfLineWidth) * scale, (boundingBox.y.value + boundingBox.height.value - halfLineWidth) * scale);
|
||||
ctx.lineWidth = lineWidth * scale;
|
||||
ctx.strokeStyle = `rgba(${color.r.value}, ${color.g.value}, ${color.b.value}, ${color.a.value})`;
|
||||
ctx.strokeStyle = `rgba(${color.r.value}, ${color.g.value}, ${color.b.value}, ${color.a.value / 255})`;
|
||||
ctx.arcTo((boundingBox.x.value + halfLineWidth) * scale, (boundingBox.y.value + boundingBox.height.value - halfLineWidth) * scale, (boundingBox.x.value + halfLineWidth) * scale, (boundingBox.y.value + boundingBox.height.value - config.cornerRadius.bottomLeft.value - halfLineWidth) * scale, config.cornerRadius.bottomLeft.value * scale);
|
||||
ctx.stroke();
|
||||
}
|
||||
@ -418,7 +428,7 @@
|
||||
let lineWidth = config.left.width.value;
|
||||
let halfLineWidth = lineWidth / 2;
|
||||
ctx.lineWidth = lineWidth * scale;
|
||||
ctx.strokeStyle = `rgba(${color.r.value}, ${color.g.value}, ${color.b.value}, ${color.a.value})`;
|
||||
ctx.strokeStyle = `rgba(${color.r.value}, ${color.g.value}, ${color.b.value}, ${color.a.value / 255})`;
|
||||
ctx.moveTo((boundingBox.x.value + halfLineWidth) * scale, (boundingBox.y.value + boundingBox.height.value - config.cornerRadius.bottomLeft.value - halfLineWidth) * scale);
|
||||
ctx.lineTo((boundingBox.x.value + halfLineWidth) * scale, (boundingBox.y.value + config.cornerRadius.bottomRight.value + halfLineWidth) * scale);
|
||||
ctx.stroke();
|
||||
@ -434,14 +444,16 @@
|
||||
ctx.font = `${fontSize}px ${fontsById[config.fontId.value]}`;
|
||||
let color = config.textColor;
|
||||
ctx.textBaseline = 'middle';
|
||||
ctx.fillStyle = `rgba(${color.r.value}, ${color.g.value}, ${color.b.value}, ${color.a.value})`;
|
||||
ctx.fillStyle = `rgba(${color.r.value}, ${color.g.value}, ${color.b.value}, ${color.a.value / 255})`;
|
||||
ctx.fillText(textDecoder.decode(stringContents), boundingBox.x.value * scale, (boundingBox.y.value + boundingBox.height.value / 2 + 1) * scale);
|
||||
break;
|
||||
}
|
||||
case (CLAY_RENDER_COMMAND_TYPE_SCISSOR_START): {
|
||||
window.canvasContext.save();
|
||||
window.canvasContext.beginPath();
|
||||
window.canvasContext.rect(boundingBox.x.value * scale, boundingBox.y.value * scale, boundingBox.width.value * scale, boundingBox.height.value * scale);
|
||||
window.canvasContext.clip();
|
||||
window.canvasContext.closePath();
|
||||
break;
|
||||
}
|
||||
case (CLAY_RENDER_COMMAND_TYPE_SCISSOR_END): {
|
||||
|
@ -51,7 +51,7 @@
|
||||
|
||||
.text {
|
||||
pointer-events: all;
|
||||
white-space: nowrap;
|
||||
white-space: pre;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
@ -279,12 +279,13 @@
|
||||
|
||||
document.addEventListener("keydown", (event) => {
|
||||
if (event.key === "ArrowDown") {
|
||||
console.log("arrowdown");
|
||||
window.arrowKeyDownPressedThisFrame = true;
|
||||
}
|
||||
if (event.key === "ArrowUp") {
|
||||
console.log("arrowup");
|
||||
window.arrowKeyUpPressedThisFrame = true;
|
||||
}
|
||||
});
|
||||
|
||||
const importObject = {
|
||||
clay: {
|
||||
measureTextFunction: (addressOfDimensions, textToMeasure, addressOfConfig) => {
|
||||
@ -361,7 +362,7 @@
|
||||
let elementData = elementCache[renderCommand.id.value];
|
||||
element = elementData.element;
|
||||
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);
|
||||
} else {
|
||||
parentElement.element.childNodes[parentElement.nextElementIndex - 1].insertAdjacentElement('afterend', element);
|
||||
@ -390,7 +391,8 @@
|
||||
let config = readStructAtAddress(renderCommand.config.value, rectangleConfigDefinition);
|
||||
let configMemory = new Uint8Array(memoryDataView.buffer.slice(renderCommand.config.value, renderCommand.config.value + config.__size));
|
||||
let linkContents = config.link.length.value > 0 ? textDecoder.decode(new Uint8Array(memoryDataView.buffer.slice(config.link.chars.value, config.link.chars.value + config.link.length.value))) : 0;
|
||||
if (linkContents.length > 0 && (window.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;
|
||||
}
|
||||
if (!dirty && !MemoryIsDifferent(configMemory, elementData.previousMemoryConfig, config.__size)) {
|
||||
|
Loading…
Reference in New Issue
Block a user