[bindings/odin] Improve Odin bindings (#13)

This commit is contained in:
FourteenBrush 2024-09-01 05:13:28 +02:00 committed by GitHub
parent 3e7738bee5
commit c248914292
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 243 additions and 268 deletions

View File

@ -37,7 +37,7 @@ import clay "clay-odin"
2. Ask clay for how much static memory it needs using [clay.MinMemorySize()](https://github.com/nicbarker/clay/blob/main/README.md#clay_minmemorysize), create an Arena for it to use with [clay.CreateArenaWithCapacityAndMemory(minMemorySize, memory)](https://github.com/nicbarker/clay/blob/main/README.md#clay_createarenawithcapacityandmemory), and initialize it with [clay.Initialize(arena)](https://github.com/nicbarker/clay/blob/main/README.md#clay_initialize). 2. Ask clay for how much static memory it needs using [clay.MinMemorySize()](https://github.com/nicbarker/clay/blob/main/README.md#clay_minmemorysize), create an Arena for it to use with [clay.CreateArenaWithCapacityAndMemory(minMemorySize, memory)](https://github.com/nicbarker/clay/blob/main/README.md#clay_createarenawithcapacityandmemory), and initialize it with [clay.Initialize(arena)](https://github.com/nicbarker/clay/blob/main/README.md#clay_initialize).
```Odin ```Odin
minMemorySize: c.uint32_t = clay.MinMemorySize() minMemorySize: u32 = clay.MinMemorySize()
memory := make([^]u8, minMemorySize) memory := make([^]u8, minMemorySize)
arena: clay.Arena = clay.CreateArenaWithCapacityAndMemory(minMemorySize, memory) arena: clay.Arena = clay.CreateArenaWithCapacityAndMemory(minMemorySize, memory)
clay.Initialize(arena) clay.Initialize(arena)
@ -77,7 +77,7 @@ sidebarItemLayout := clay.LayoutConfig {
// Re-useable components are just normal functions // Re-useable components are just normal functions
SidebarItemComponent :: proc(index: u32) { SidebarItemComponent :: proc(index: u32) {
if clay.Rectangle(clay.IDI("SidebarBlob", index), &sidebarItemLayout, clay.RectangleConfig({color = COLOR_ORANGE})) {} if clay.Rectangle(clay.ID("SidebarBlob", index), &sidebarItemLayout, clay.RectangleConfig({color = COLOR_ORANGE})) {}
} }
// An example function to begin the "root" of your layout tree // An example function to begin the "root" of your layout tree
@ -106,11 +106,11 @@ CreateLayout :: proc() -> clay.ClayArray(clay.RenderCommand) {
clay.Layout({sizing = {width = clay.SizingFixed(60), height = clay.SizingFixed(60)}}), clay.Layout({sizing = {width = clay.SizingFixed(60), height = clay.SizingFixed(60)}}),
clay.ImageConfig({imageData = &profilePicture, sourceDimensions = {height = 60, width = 60}}), clay.ImageConfig({imageData = &profilePicture, sourceDimensions = {height = 60, width = 60}}),
) {} ) {}
clay.Text(clay.ID("ProfileTitle"), clay.MakeString("Clay - UI Library"), clay.TextConfig({fontSize = 24, textColor = {255, 255, 255, 255}})) clay.Text(clay.ID("ProfileTitle"), "Clay - UI Library", clay.TextConfig({fontSize = 24, textColor = {255, 255, 255, 255}}))
} }
// Standard Odin code like loops etc work inside components // Standard Odin code like loops etc work inside components
for i: u32 = 0; i < 10; i += 1 { for i in 0..<10 {
SidebarItemComponent(i) SidebarItemComponent(i)
} }
} }
@ -135,9 +135,7 @@ for i: u32 = 0; i < renderCommands.length; i += 1 {
switch renderCommand.commandType { switch renderCommand.commandType {
case .Rectangle: case .Rectangle:
{ DrawRectangle(renderCommand.boundingBox, renderCommand.config.rectangleElementConfig.color)
DrawRectangle(renderCommand.boundingBox, renderCommand.config.rectangleElementConfig.color)
}
// ... Implement handling of other command types // ... Implement handling of other command types
} }
} }

View File

@ -31,8 +31,8 @@ Dimensions :: struct {
Arena :: struct { Arena :: struct {
label: String, label: String,
nextAllocation: c.uint64_t, nextAllocation: u64,
capacity: c.uint64_t, capacity: u64,
memory: [^]c.char, memory: [^]c.char,
} }
@ -53,7 +53,7 @@ CornerRadius :: struct {
} }
BorderData :: struct { BorderData :: struct {
width: c.uint32_t, width: u32,
color: Color, color: Color,
} }
@ -81,10 +81,10 @@ RectangleElementConfig :: struct {
TextElementConfig :: struct { TextElementConfig :: struct {
textColor: Color, textColor: Color,
fontId: c.uint16_t, fontId: u16,
fontSize: c.uint16_t, fontSize: u16,
letterSpacing: c.uint16_t, letterSpacing: u16,
lineSpacing: c.uint16_t, lineSpacing: u16,
} }
ImageElementConfig :: struct { ImageElementConfig :: struct {
@ -106,8 +106,8 @@ BorderElementConfig :: struct {
} }
ScrollElementConfig :: struct { ScrollElementConfig :: struct {
horizontal: c.bool, horizontal: bool,
vertical: c.bool, vertical: bool,
} }
FloatingAttachPointType :: enum EnumBackingType { FloatingAttachPointType :: enum EnumBackingType {
@ -130,8 +130,8 @@ FloatingAttachPoints :: struct {
FloatingElementConfig :: struct { FloatingElementConfig :: struct {
offset: Vector2, offset: Vector2,
expand: Dimensions, expand: Dimensions,
zIndex: c.uint16_t, zIndex: u16,
parentId: c.uint32_t, parentId: u32,
attachment: FloatingAttachPoints, attachment: FloatingAttachPoints,
} }
@ -147,7 +147,7 @@ RenderCommand :: struct {
boundingBox: BoundingBox, boundingBox: BoundingBox,
config: ElementConfigUnion, config: ElementConfigUnion,
text: String, text: String,
id: c.uint32_t, id: u32,
commandType: RenderCommandType, commandType: RenderCommandType,
} }
@ -159,7 +159,7 @@ ScrollContainerData :: struct {
contentDimensions: Dimensions, contentDimensions: Dimensions,
config: ScrollElementConfig, config: ScrollElementConfig,
// Indicates whether an actual scroll container matched the provided ID or if the default struct was returned. // Indicates whether an actual scroll container matched the provided ID or if the default struct was returned.
found: c.bool, found: bool,
} }
SizingType :: enum EnumBackingType { SizingType :: enum EnumBackingType {
@ -190,8 +190,8 @@ Sizing :: struct {
} }
Padding :: struct { Padding :: struct {
x: c.uint16_t, x: u16,
y: c.uint16_t, y: u16,
} }
LayoutDirection :: enum EnumBackingType { LayoutDirection :: enum EnumBackingType {
@ -219,30 +219,30 @@ ChildAlignment :: struct {
LayoutConfig :: struct { LayoutConfig :: struct {
sizing: Sizing, sizing: Sizing,
padding: Padding, padding: Padding,
childGap: c.uint16_t, childGap: u16,
layoutDirection: LayoutDirection, layoutDirection: LayoutDirection,
childAlignment: ChildAlignment, childAlignment: ChildAlignment,
} }
ClayArray :: struct($type: typeid) { ClayArray :: struct($type: typeid) {
capacity: c.uint32_t, capacity: u32,
length: c.uint32_t, length: u32,
internalArray: [^]type, internalArray: [^]type,
} }
@(link_prefix = "Clay_", default_calling_convention = "c") @(link_prefix = "Clay_", default_calling_convention = "c")
foreign Clay { foreign Clay {
MinMemorySize :: proc() -> c.uint32_t --- MinMemorySize :: proc() -> u32 ---
CreateArenaWithCapacityAndMemory :: proc(capacity: c.uint32_t, offset: [^]u8) -> Arena --- CreateArenaWithCapacityAndMemory :: proc(capacity: u32, offset: [^]u8) -> Arena ---
SetPointerPosition :: proc(position: Vector2) --- SetPointerPosition :: proc(position: Vector2) ---
Initialize :: proc(arena: Arena) --- Initialize :: proc(arena: Arena) ---
UpdateScrollContainers :: proc(isPointerActive: c.bool, scrollDelta: Vector2, deltaTime: c.float) --- UpdateScrollContainers :: proc(isPointerActive: bool, scrollDelta: Vector2, deltaTime: c.float) ---
BeginLayout :: proc(screenWidth: c.int, screenHeight: c.int) --- BeginLayout :: proc(screenWidth: c.int, screenHeight: c.int) ---
EndLayout :: proc(screenWidth: c.int, screenHeight: c.int) -> ClayArray(RenderCommand) --- EndLayout :: proc(screenWidth: c.int, screenHeight: c.int) -> ClayArray(RenderCommand) ---
PointerOver :: proc(id: c.uint32_t) -> c.bool --- PointerOver :: proc(id: u32) -> bool ---
GetScrollContainerData :: proc(id: c.uint32_t) -> ScrollContainerData --- GetScrollContainerData :: proc(id: u32) -> ScrollContainerData ---
SetMeasureTextFunction :: proc(measureTextFunction: proc(text: ^String, config: ^TextElementConfig) -> Dimensions) --- SetMeasureTextFunction :: proc(measureTextFunction: proc(text: ^String, config: ^TextElementConfig) -> Dimensions) ---
RenderCommandArray_Get :: proc(array: ^ClayArray(RenderCommand), index: c.int32_t) -> ^RenderCommand --- RenderCommandArray_Get :: proc(array: ^ClayArray(RenderCommand), index: i32) -> ^RenderCommand ---
} }
@(private, link_prefix = "Clay_", default_calling_convention = "c") @(private, link_prefix = "Clay_", default_calling_convention = "c")
@ -259,14 +259,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: c.uint32_t, layoutConfig: ^LayoutConfig) --- _OpenContainerElement :: proc(id: u32, layoutConfig: ^LayoutConfig) ---
_OpenRectangleElement :: proc(id: c.uint32_t, layoutConfig: ^LayoutConfig, rectangleConfig: ^RectangleElementConfig) --- _OpenRectangleElement :: proc(id: u32, layoutConfig: ^LayoutConfig, rectangleConfig: ^RectangleElementConfig) ---
_OpenTextElement :: proc(id: c.uint32_t, text: String, textConfig: ^TextElementConfig) --- _OpenTextElement :: proc(id: u32, text: String, textConfig: ^TextElementConfig) ---
_OpenImageElement :: proc(id: c.uint32_t, layoutConfig: ^LayoutConfig, imageConfig: ^ImageElementConfig) --- _OpenImageElement :: proc(id: u32, layoutConfig: ^LayoutConfig, imageConfig: ^ImageElementConfig) ---
_OpenScrollElement :: proc(id: c.uint32_t, layoutConfig: ^LayoutConfig, imageConfig: ^ScrollElementConfig) --- _OpenScrollElement :: proc(id: u32, layoutConfig: ^LayoutConfig, imageConfig: ^ScrollElementConfig) ---
_OpenFloatingElement :: proc(id: c.uint32_t, layoutConfig: ^LayoutConfig, imageConfig: ^FloatingElementConfig) --- _OpenFloatingElement :: proc(id: u32, layoutConfig: ^LayoutConfig, imageConfig: ^FloatingElementConfig) ---
_OpenBorderElement :: proc(id: c.uint32_t, layoutConfig: ^LayoutConfig, imageConfig: ^BorderElementConfig) --- _OpenBorderElement :: proc(id: u32, layoutConfig: ^LayoutConfig, imageConfig: ^BorderElementConfig) ---
_OpenCustomElement :: proc(id: c.uint32_t, layoutConfig: ^LayoutConfig, imageConfig: ^CustomElementConfig) --- _OpenCustomElement :: proc(id: u32, layoutConfig: ^LayoutConfig, imageConfig: ^CustomElementConfig) ---
_CloseElementWithChildren :: proc() --- _CloseElementWithChildren :: proc() ---
_CloseScrollElement :: proc() --- _CloseScrollElement :: proc() ---
_CloseFloatingElement :: proc() --- _CloseFloatingElement :: proc() ---
@ -278,52 +278,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: c.uint32_t) -> c.uint32_t --- _HashString :: proc(toHash: String, index: u32) -> u32 ---
} }
@(require_results, deferred_none = _CloseElementWithChildren) @(require_results, deferred_none = _CloseElementWithChildren)
Container :: proc(id: c.uint32_t, layoutConfig: ^LayoutConfig) -> bool { Container :: proc(id: u32, 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: c.uint32_t, layoutConfig: ^LayoutConfig, rectangleConfig: ^RectangleElementConfig) -> bool { Rectangle :: proc(id: u32, layoutConfig: ^LayoutConfig, rectangleConfig: ^RectangleElementConfig) -> bool {
_OpenRectangleElement(id, layoutConfig, rectangleConfig) _OpenRectangleElement(id, layoutConfig, rectangleConfig)
return true return true
} }
Text :: proc(id: c.uint32_t, text: String, textConfig: ^TextElementConfig) -> bool { Text :: proc(id: u32, text: string, textConfig: ^TextElementConfig) -> bool {
_OpenTextElement(id, text, textConfig) _OpenTextElement(id, MakeString(text), textConfig)
return true return true
} }
@(require_results, deferred_none = _CloseElementWithChildren) @(require_results, deferred_none = _CloseElementWithChildren)
Image :: proc(id: c.uint32_t, layoutConfig: ^LayoutConfig, imageConfig: ^ImageElementConfig) -> bool { Image :: proc(id: u32, 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: c.uint32_t, layoutConfig: ^LayoutConfig, scrollConfig: ^ScrollElementConfig) -> bool { Scroll :: proc(id: u32, 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: c.uint32_t, layoutConfig: ^LayoutConfig, floatingConfig: ^FloatingElementConfig) -> bool { Floating :: proc(id: u32, 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: c.uint32_t, layoutConfig: ^LayoutConfig, borderConfig: ^BorderElementConfig) -> bool { Border :: proc(id: u32, 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: c.uint32_t, layoutConfig: ^LayoutConfig, customConfig: ^CustomElementConfig) -> bool { Custom :: proc(id: u32, layoutConfig: ^LayoutConfig, customConfig: ^CustomElementConfig) -> bool {
_OpenCustomElement(id, layoutConfig, customConfig) _OpenCustomElement(id, layoutConfig, customConfig)
return true return true
} }
@ -412,10 +412,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) -> c.uint32_t { ID :: proc(label: string, index: u32 = 0) -> u32 {
return _HashString(MakeString(label), 0)
}
IDI :: proc(label: string, index: u32) -> c.uint32_t {
return _HashString(MakeString(label), index) return _HashString(MakeString(label), index)
} }

View File

@ -57,18 +57,18 @@ headerTextConfig := clay.TextElementConfig {
textColor = {61, 26, 5, 255}, textColor = {61, 26, 5, 255},
} }
LandingPageBlob :: proc(index: u32, fontSize: u16, fontId: u16, color: clay.Color, text: clay.String, image: ^raylib.Texture2D) { LandingPageBlob :: proc(index: u32, fontSize: u16, fontId: u16, color: clay.Color, text: string, image: ^raylib.Texture2D) {
if clay.Border( if clay.Border(
clay.IDI("HeroBlob", index), clay.ID("HeroBlob", index),
clay.Layout({sizing = {width = clay.SizingGrow({max = 480})}, padding = clay.Padding{16, 16}, childGap = 16, childAlignment = clay.ChildAlignment{y = .CENTER}}), clay.Layout({sizing = {width = clay.SizingGrow({max = 480})}, padding = clay.Padding{16, 16}, childGap = 16, childAlignment = clay.ChildAlignment{y = .CENTER}}),
clay.BorderConfigOutsideRadius({2, color}, 10), clay.BorderConfigOutsideRadius({2, color}, 10),
) { ) {
if clay.Image( if clay.Image(
clay.IDI("CheckImage", index), clay.ID("CheckImage", index),
clay.Layout({sizing = {width = clay.SizingFixed(32)}}), clay.Layout({sizing = {width = clay.SizingFixed(32)}}),
clay.ImageConfig({imageData = image, sourceDimensions = {128, 128}}), clay.ImageConfig({imageData = image, sourceDimensions = {128, 128}}),
) {} ) {}
clay.Text(clay.IDI("HeroBlobText", index), text, clay.TextConfig({fontSize = fontSize, fontId = fontId, textColor = color})) clay.Text(clay.ID("HeroBlobText", index), text, clay.TextConfig({fontSize = fontSize, fontId = fontId, textColor = color}))
} }
} }
@ -85,13 +85,13 @@ LandingPageDesktop :: proc() {
if clay.Container(clay.ID("LeftText"), clay.Layout({sizing = {width = clay.SizingPercent(0.55)}, layoutDirection = .TOP_TO_BOTTOM, childGap = 8})) { if clay.Container(clay.ID("LeftText"), clay.Layout({sizing = {width = clay.SizingPercent(0.55)}, layoutDirection = .TOP_TO_BOTTOM, childGap = 8})) {
clay.Text( clay.Text(
clay.ID("LeftTextTitle"), clay.ID("LeftTextTitle"),
clay.MakeString("Clay is a flex-box style UI auto layout library in C, with declarative syntax and microsecond performance."), "Clay is a flex-box style UI auto layout library in C, with declarative syntax and microsecond performance.",
clay.TextConfig({fontSize = 56, fontId = FONT_ID_TITLE_56, textColor = COLOR_RED}), clay.TextConfig({fontSize = 56, fontId = FONT_ID_TITLE_56, textColor = COLOR_RED}),
) )
if clay.Container(clay.ID("Spacer"), clay.Layout({sizing = {width = clay.SizingGrow({}), height = clay.SizingFixed(32)}})) {} if clay.Container(clay.ID("Spacer"), clay.Layout({sizing = {width = clay.SizingGrow({}), height = clay.SizingFixed(32)}})) {}
clay.Text( clay.Text(
clay.ID("LeftTextTagline"), clay.ID("LeftTextTagline"),
clay.MakeString("Clay is laying out this webpage right now!"), "Clay is laying out this webpage right now!",
clay.TextConfig({fontSize = 36, fontId = FONT_ID_TITLE_36, textColor = COLOR_ORANGE}), clay.TextConfig({fontSize = 36, fontId = FONT_ID_TITLE_36, textColor = COLOR_ORANGE}),
) )
} }
@ -99,11 +99,11 @@ LandingPageDesktop :: proc() {
clay.ID("HeroImageOuter"), clay.ID("HeroImageOuter"),
clay.Layout({layoutDirection = .TOP_TO_BOTTOM, sizing = {width = clay.SizingPercent(0.45)}, childAlignment = {x = .CENTER}, childGap = 16}), clay.Layout({layoutDirection = .TOP_TO_BOTTOM, sizing = {width = clay.SizingPercent(0.45)}, childAlignment = {x = .CENTER}, childGap = 16}),
) { ) {
LandingPageBlob(1, 30, FONT_ID_BODY_30, COLOR_BLOB_BORDER_5, clay.MakeString("High performance"), &checkImage5) LandingPageBlob(1, 30, FONT_ID_BODY_30, COLOR_BLOB_BORDER_5, "High performance", &checkImage5)
LandingPageBlob(2, 30, FONT_ID_BODY_30, COLOR_BLOB_BORDER_4, clay.MakeString("Flexbox-style responsive layout"), &checkImage4) LandingPageBlob(2, 30, FONT_ID_BODY_30, COLOR_BLOB_BORDER_4, "Flexbox-style responsive layout", &checkImage4)
LandingPageBlob(3, 30, FONT_ID_BODY_30, COLOR_BLOB_BORDER_3, clay.MakeString("Declarative syntax"), &checkImage3) LandingPageBlob(3, 30, FONT_ID_BODY_30, COLOR_BLOB_BORDER_3, "Declarative syntax", &checkImage3)
LandingPageBlob(4, 30, FONT_ID_BODY_30, COLOR_BLOB_BORDER_2, clay.MakeString("Single .h file for C/C++"), &checkImage2) LandingPageBlob(4, 30, FONT_ID_BODY_30, COLOR_BLOB_BORDER_2, "Single .h file for C/C++", &checkImage2)
LandingPageBlob(5, 30, FONT_ID_BODY_30, COLOR_BLOB_BORDER_1, clay.MakeString("Compile to 15kb .wasm"), &checkImage1) LandingPageBlob(5, 30, FONT_ID_BODY_30, COLOR_BLOB_BORDER_1, "Compile to 15kb .wasm", &checkImage1)
} }
} }
} }
@ -112,26 +112,24 @@ 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,
layoutDirection = .TOP_TO_BOTTOM, sizing = {width = clay.SizingGrow({}), height = clay.SizingFit({min = cast(f32)windowHeight - 70})},
sizing = {width = clay.SizingGrow({}), height = clay.SizingFit({min = cast(f32)windowHeight - 70})}, childAlignment = {x = .CENTER, y = .CENTER},
childAlignment = {x = .CENTER, y = .CENTER}, padding = {16, 32},
padding = {16, 32}, childGap = 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(
clay.ID("LeftTextTitle"), clay.ID("LeftTextTitle"),
clay.MakeString("Clay is a flex-box style UI auto layout library in C, with declarative syntax and microsecond performance."), "Clay is a flex-box style UI auto layout library in C, with declarative syntax and microsecond performance.",
clay.TextConfig({fontSize = 48, fontId = FONT_ID_TITLE_48, textColor = COLOR_RED}), clay.TextConfig({fontSize = 48, fontId = FONT_ID_TITLE_48, textColor = COLOR_RED}),
) )
if clay.Container(clay.ID("Spacer"), clay.Layout({sizing = {width = clay.SizingGrow({}), height = clay.SizingFixed(32)}})) {} if clay.Container(clay.ID("Spacer"), clay.Layout({sizing = {width = clay.SizingGrow({}), height = clay.SizingFixed(32)}})) {}
clay.Text( clay.Text(
clay.ID("LeftTextTagline"), clay.ID("LeftTextTagline"),
clay.MakeString("Clay is laying out this webpage right now!"), "Clay is laying out this webpage right now!",
clay.TextConfig({fontSize = 32, fontId = FONT_ID_TITLE_32, textColor = COLOR_ORANGE}), clay.TextConfig({fontSize = 32, fontId = FONT_ID_TITLE_32, textColor = COLOR_ORANGE}),
) )
} }
@ -139,11 +137,11 @@ LandingPageMobile :: proc() {
clay.ID("HeroImageOuter"), clay.ID("HeroImageOuter"),
clay.Layout({layoutDirection = .TOP_TO_BOTTOM, sizing = {width = clay.SizingGrow({})}, childAlignment = {x = .CENTER}, childGap = 16}), clay.Layout({layoutDirection = .TOP_TO_BOTTOM, sizing = {width = clay.SizingGrow({})}, childAlignment = {x = .CENTER}, childGap = 16}),
) { ) {
LandingPageBlob(1, 24, FONT_ID_BODY_24, COLOR_BLOB_BORDER_5, clay.MakeString("High performance"), &checkImage5) LandingPageBlob(1, 24, FONT_ID_BODY_24, COLOR_BLOB_BORDER_5, "High performance", &checkImage5)
LandingPageBlob(2, 24, FONT_ID_BODY_24, COLOR_BLOB_BORDER_4, clay.MakeString("Flexbox-style responsive layout"), &checkImage4) LandingPageBlob(2, 24, FONT_ID_BODY_24, COLOR_BLOB_BORDER_4, "Flexbox-style responsive layout", &checkImage4)
LandingPageBlob(3, 24, FONT_ID_BODY_24, COLOR_BLOB_BORDER_3, clay.MakeString("Declarative syntax"), &checkImage3) LandingPageBlob(3, 24, FONT_ID_BODY_24, COLOR_BLOB_BORDER_3, "Declarative syntax", &checkImage3)
LandingPageBlob(4, 24, FONT_ID_BODY_24, COLOR_BLOB_BORDER_2, clay.MakeString("Single .h file for C/C++"), &checkImage2) LandingPageBlob(4, 24, FONT_ID_BODY_24, COLOR_BLOB_BORDER_2, "Single .h file for C/C++", &checkImage2)
LandingPageBlob(5, 24, FONT_ID_BODY_24, COLOR_BLOB_BORDER_1, clay.MakeString("Compile to 15kb .wasm"), &checkImage1) LandingPageBlob(5, 24, FONT_ID_BODY_24, COLOR_BLOB_BORDER_1, "Compile to 15kb .wasm", &checkImage1)
} }
} }
} }
@ -155,18 +153,18 @@ FeatureBlocks :: proc(widthSizing: clay.SizingAxis, outerPadding: u16) {
clay.Layout({layoutDirection = .TOP_TO_BOTTOM, sizing = {width = widthSizing}, childAlignment = {y = .CENTER}, padding = {outerPadding, 32}, childGap = 8}), clay.Layout({layoutDirection = .TOP_TO_BOTTOM, sizing = {width = widthSizing}, childAlignment = {y = .CENTER}, padding = {outerPadding, 32}, childGap = 8}),
) { ) {
if clay.Rectangle(clay.ID("HFileIncludeOuter"), clay.Layout({padding = {8, 4}}), clay.RectangleConfig({color = COLOR_RED, cornerRadius = clay.CornerRadiusAll(8)})) { if clay.Rectangle(clay.ID("HFileIncludeOuter"), clay.Layout({padding = {8, 4}}), clay.RectangleConfig({color = COLOR_RED, cornerRadius = clay.CornerRadiusAll(8)})) {
clay.Text(clay.IDI("HFileBoxText", 2), clay.MakeString("#include clay.h"), clay.TextConfig({fontSize = 24, fontId = FONT_ID_BODY_24, textColor = COLOR_LIGHT})) clay.Text(clay.ID("HFileBoxText", 2), "#include clay.h", clay.TextConfig({fontSize = 24, fontId = FONT_ID_BODY_24, textColor = COLOR_LIGHT}))
} }
clay.Text(clay.ID("HFileSecondLine"), clay.MakeString("~2000 lines of C99."), textConfig) clay.Text(clay.ID("HFileSecondLine"), "~2000 lines of C99.", textConfig)
clay.Text(clay.IDI("HFileBoxText", 5), clay.MakeString("Zero dependencies, including no C standard library."), textConfig) clay.Text(clay.ID("HFileBoxText", 5), "Zero dependencies, including no C standard library.", textConfig)
} }
if clay.Container( if clay.Container(
clay.ID("BringYourOwnRendererOuter"), clay.ID("BringYourOwnRendererOuter"),
clay.Layout({layoutDirection = .TOP_TO_BOTTOM, sizing = {width = widthSizing}, childAlignment = {y = .CENTER}, padding = {x = outerPadding, y = 32}, childGap = 8}), clay.Layout({layoutDirection = .TOP_TO_BOTTOM, sizing = {width = widthSizing}, childAlignment = {y = .CENTER}, padding = {x = outerPadding, y = 32}, childGap = 8}),
) { ) {
clay.Text(clay.IDI("ZeroDependenciesText", 1), clay.MakeString("Renderer agnostic."), clay.TextConfig({fontId = FONT_ID_BODY_24, fontSize = 24, textColor = COLOR_ORANGE})) clay.Text(clay.ID("ZeroDependenciesText", 1), "Renderer agnostic.", clay.TextConfig({fontId = FONT_ID_BODY_24, fontSize = 24, textColor = COLOR_ORANGE}))
clay.Text(clay.IDI("ZeroDependenciesText", 2), clay.MakeString("Layout with clay, then render with Raylib, WebGL Canvas or even as HTML."), textConfig) clay.Text(clay.ID("ZeroDependenciesText", 2), "Layout with clay, then render with Raylib, WebGL Canvas or even as HTML.", textConfig)
clay.Text(clay.IDI("ZeroDependenciesText", 3), clay.MakeString("Flexible output for easy compositing in your custom engine or environment."), textConfig) clay.Text(clay.ID("ZeroDependenciesText", 3), "Flexible output for easy compositing in your custom engine or environment.", textConfig)
} }
} }
@ -194,21 +192,21 @@ FeatureBlocksMobile :: proc() {
DeclarativeSyntaxPage :: proc(titleTextConfig: clay.TextElementConfig, widthSizing: clay.SizingAxis) { DeclarativeSyntaxPage :: proc(titleTextConfig: clay.TextElementConfig, widthSizing: clay.SizingAxis) {
if clay.Container(clay.ID("SyntaxPageLeftText"), clay.Layout({sizing = {width = widthSizing}, layoutDirection = .TOP_TO_BOTTOM, childGap = 8})) { if clay.Container(clay.ID("SyntaxPageLeftText"), clay.Layout({sizing = {width = widthSizing}, layoutDirection = .TOP_TO_BOTTOM, childGap = 8})) {
clay.Text(clay.ID("SyntaxPageTextTitle"), clay.MakeString("Declarative Syntax"), clay.TextConfig(titleTextConfig)) clay.Text(clay.ID("SyntaxPageTextTitle"), "Declarative Syntax", clay.TextConfig(titleTextConfig))
if clay.Container(clay.ID("SyntaxSpacer"), clay.Layout({sizing = {width = clay.SizingGrow({max = 16})}})) {} if clay.Container(clay.ID("SyntaxSpacer"), clay.Layout({sizing = {width = clay.SizingGrow({max = 16})}})) {}
clay.Text( clay.Text(
clay.ID("SyntaxPageTextSubTitle1"), clay.ID("SyntaxPageTextSubTitle1"),
clay.MakeString("Flexible and readable declarative syntax with nested UI element hierarchies."), "Flexible and readable declarative syntax with nested UI element hierarchies.",
clay.TextConfig({fontSize = 28, fontId = FONT_ID_BODY_28, textColor = COLOR_RED}), clay.TextConfig({fontSize = 28, fontId = FONT_ID_BODY_28, textColor = COLOR_RED}),
) )
clay.Text( clay.Text(
clay.ID("SyntaxPageTextSubTitle2"), clay.ID("SyntaxPageTextSubTitle2"),
clay.MakeString("Mix elements with standard C code like loops, conditionals and functions."), "Mix elements with standard C code like loops, conditionals and functions.",
clay.TextConfig({fontSize = 28, fontId = FONT_ID_BODY_28, textColor = COLOR_RED}), clay.TextConfig({fontSize = 28, fontId = FONT_ID_BODY_28, textColor = COLOR_RED}),
) )
clay.Text( clay.Text(
clay.ID("SyntaxPageTextSubTitle3"), clay.ID("SyntaxPageTextSubTitle3"),
clay.MakeString("Create your own library of re-usable components from UI primitives like text, images and rectangles."), "Create your own library of re-usable components from UI primitives like text, images and rectangles.",
clay.TextConfig({fontSize = 28, fontId = FONT_ID_BODY_28, textColor = COLOR_RED}), clay.TextConfig({fontSize = 28, fontId = FONT_ID_BODY_28, textColor = COLOR_RED}),
) )
} }
@ -257,25 +255,25 @@ ColorLerp :: proc(a: clay.Color, b: clay.Color, amount: f32) -> clay.Color {
return clay.Color{a.r + (b.r - a.r) * amount, a.g + (b.g - a.g) * amount, a.b + (b.b - a.b) * amount, a.a + (b.a - a.a) * amount} return clay.Color{a.r + (b.r - a.r) * amount, a.g + (b.g - a.g) * amount, a.b + (b.b - a.b) * amount, a.a + (b.a - a.a) * amount}
} }
LOREM_IPSUM_TEXT: clay.String = clay.MakeString("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.") LOREM_IPSUM_TEXT := "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
HighPerformancePage :: proc(lerpValue: f32, titleTextConfig: clay.TextElementConfig, widthSizing: clay.SizingAxis) { HighPerformancePage :: proc(lerpValue: f32, titleTextConfig: clay.TextElementConfig, widthSizing: clay.SizingAxis) {
if clay.Container(clay.ID("PerformanceLeftText"), clay.Layout({sizing = {width = widthSizing}, layoutDirection = .TOP_TO_BOTTOM, childGap = 8})) { if clay.Container(clay.ID("PerformanceLeftText"), clay.Layout({sizing = {width = widthSizing}, layoutDirection = .TOP_TO_BOTTOM, childGap = 8})) {
clay.Text(clay.ID("PerformanceTextTitle"), clay.MakeString("High Performance"), clay.TextConfig(titleTextConfig)) clay.Text(clay.ID("PerformanceTextTitle"), "High Performance", clay.TextConfig(titleTextConfig))
if clay.Container(clay.ID("SyntaxSpacer"), clay.Layout({sizing = {width = clay.SizingGrow({max = 16})}})) {} if clay.Container(clay.ID("SyntaxSpacer"), clay.Layout({sizing = {width = clay.SizingGrow({max = 16})}})) {}
clay.Text( clay.Text(
clay.IDI("PerformanceTextSubTitle", 1), clay.ID("PerformanceTextSubTitle", 1),
clay.MakeString("Fast enough to recompute your entire UI every frame."), "Fast enough to recompute your entire UI every frame.",
clay.TextConfig({fontSize = 28, fontId = FONT_ID_BODY_36, textColor = COLOR_LIGHT}), clay.TextConfig({fontSize = 28, fontId = FONT_ID_BODY_36, textColor = COLOR_LIGHT}),
) )
clay.Text( clay.Text(
clay.IDI("PerformanceTextSubTitle", 2), clay.ID("PerformanceTextSubTitle", 2),
clay.MakeString("Small memory footprint (3.5mb default) with static allocation & reuse. No malloc / free."), "Small memory footprint (3.5mb default) with static allocation & reuse. No malloc / free.",
clay.TextConfig({fontSize = 28, fontId = FONT_ID_BODY_36, textColor = COLOR_LIGHT}), clay.TextConfig({fontSize = 28, fontId = FONT_ID_BODY_36, textColor = COLOR_LIGHT}),
) )
clay.Text( clay.Text(
clay.IDI("PerformanceTextSubTitle", 3), clay.ID("PerformanceTextSubTitle", 3),
clay.MakeString("Simplify animations and reactive UI design by avoiding the standard performance hacks."), "Simplify animations and reactive UI design by avoiding the standard performance hacks.",
clay.TextConfig({fontSize = 28, fontId = FONT_ID_BODY_36, textColor = COLOR_LIGHT}), clay.TextConfig({fontSize = 28, fontId = FONT_ID_BODY_36, textColor = COLOR_LIGHT}),
) )
} }
@ -333,7 +331,7 @@ HighPerformancePageMobile :: proc(lerpValue: f32) {
} }
} }
RendererButtonActive :: proc(id: u32, index: i32, text: clay.String) { RendererButtonActive :: proc(id: u32, 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}}),
@ -343,35 +341,35 @@ RendererButtonActive :: proc(id: u32, index: i32, text: clay.String) {
} }
} }
RendererButtonInactive :: proc(id: u32, index: u32, text: clay.String) { RendererButtonInactive :: proc(id: u32, 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.IDI("RendererButtonInactiveInner", index), clay.ID("RendererButtonInactiveInner", index),
clay.Layout({sizing = {width = clay.SizingFixed(300)}, padding = {16, 16}}), clay.Layout({sizing = {width = clay.SizingFixed(300)}, padding = {16, 16}}),
clay.RectangleConfig({color = clay.PointerOver(id) ? COLOR_LIGHT_HOVER : COLOR_LIGHT, cornerRadius = clay.CornerRadiusAll(10)}), clay.RectangleConfig({color = clay.PointerOver(id) ? COLOR_LIGHT_HOVER : COLOR_LIGHT, cornerRadius = clay.CornerRadiusAll(10)}),
) { ) {
clay.Text(clay.IDI("RendererButtonInactiveText", index), text, clay.TextConfig({fontSize = 28, fontId = FONT_ID_BODY_28, textColor = COLOR_RED})) clay.Text(clay.ID("RendererButtonInactiveText", index), text, clay.TextConfig({fontSize = 28, fontId = FONT_ID_BODY_28, textColor = COLOR_RED}))
} }
} }
} }
RendererPage :: proc(titleTextConfig: clay.TextElementConfig, widthSizing: clay.SizingAxis) { RendererPage :: proc(titleTextConfig: clay.TextElementConfig, widthSizing: clay.SizingAxis) {
if clay.Container(clay.ID("RendererLeftText"), clay.Layout({sizing = {width = widthSizing}, layoutDirection = .TOP_TO_BOTTOM, childGap = 8})) { if clay.Container(clay.ID("RendererLeftText"), clay.Layout({sizing = {width = widthSizing}, layoutDirection = .TOP_TO_BOTTOM, childGap = 8})) {
clay.Text(clay.ID("RendererTextTitle"), clay.MakeString("Renderer & Platform Agnostic"), clay.TextConfig(titleTextConfig)) clay.Text(clay.ID("RendererTextTitle"), "Renderer & Platform Agnostic", clay.TextConfig(titleTextConfig))
if clay.Container(clay.ID("Spacer"), clay.Layout({sizing = {width = clay.SizingGrow({max = 16})}})) {} if clay.Container(clay.ID("Spacer"), clay.Layout({sizing = {width = clay.SizingGrow({max = 16})}})) {}
clay.Text( clay.Text(
clay.IDI("RendererTextSubTitle", 1), clay.ID("RendererTextSubTitle", 1),
clay.MakeString("Clay outputs a sorted array of primitive render commands, such as RECTANGLE, TEXT or IMAGE."), "Clay outputs a sorted array of primitive render commands, such as RECTANGLE, TEXT or IMAGE.",
clay.TextConfig({fontSize = 28, fontId = FONT_ID_BODY_36, textColor = COLOR_RED}), clay.TextConfig({fontSize = 28, fontId = FONT_ID_BODY_36, textColor = COLOR_RED}),
) )
clay.Text( clay.Text(
clay.IDI("RendererTextSubTitle", 2), clay.ID("RendererTextSubTitle", 2),
clay.MakeString("Write your own renderer in a few hundred lines of code, or use the provided examples for Raylib, WebGL canvas and more."), "Write your own renderer in a few hundred lines of code, or use the provided examples for Raylib, WebGL canvas and more.",
clay.TextConfig({fontSize = 28, fontId = FONT_ID_BODY_36, textColor = COLOR_RED}), clay.TextConfig({fontSize = 28, fontId = FONT_ID_BODY_36, textColor = COLOR_RED}),
) )
clay.Text( clay.Text(
clay.IDI("RendererTextSubTitle", 3), clay.ID("RendererTextSubTitle", 3),
clay.MakeString("There's even an HTML renderer - you're looking at it right now!"), "There's even an HTML renderer - you're looking at it right now!",
clay.TextConfig({fontSize = 28, fontId = FONT_ID_BODY_36, textColor = COLOR_RED}), clay.TextConfig({fontSize = 28, fontId = FONT_ID_BODY_36, textColor = COLOR_RED}),
) )
} }
@ -381,11 +379,11 @@ RendererPage :: proc(titleTextConfig: clay.TextElementConfig, widthSizing: clay.
) { ) {
clay.Text( clay.Text(
clay.ID("RendererTextRightTitle"), clay.ID("RendererTextRightTitle"),
clay.MakeString("Try changing renderer!"), "Try changing renderer!",
clay.TextConfig({fontSize = 36, fontId = FONT_ID_BODY_36, textColor = COLOR_ORANGE}), 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.IDI("RendererSelectButtonActive", 0), 0, clay.MakeString("Raylib Renderer")) RendererButtonActive(clay.ID("RendererSelectButtonActive", 0), 0, "Raylib Renderer")
} }
} }
@ -407,15 +405,13 @@ 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,
layoutDirection = .TOP_TO_BOTTOM, sizing = {clay.SizingGrow({}), clay.SizingFit({min = cast(f32)windowHeight - 50})},
sizing = {clay.SizingGrow({}), clay.SizingFit({min = cast(f32)windowHeight - 50})}, childAlignment = {x = .CENTER, y = .CENTER},
childAlignment = {x = .CENTER, y = .CENTER}, padding = {x = 16, y = 32},
padding = {x = 16, y = 32}, childGap = 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({}))
@ -428,7 +424,7 @@ ScrollbarData :: struct {
mouseDown: bool, mouseDown: bool,
} }
scrollbarData: ScrollbarData = ScrollbarData{} scrollbarData := ScrollbarData{}
animationLerpValue: f32 = -1.0 animationLerpValue: f32 = -1.0
createLayout :: proc(lerpValue: f32) -> clay.ClayArray(clay.RenderCommand) { createLayout :: proc(lerpValue: f32) -> clay.ClayArray(clay.RenderCommand) {
@ -443,15 +439,15 @@ createLayout :: proc(lerpValue: f32) -> clay.ClayArray(clay.RenderCommand) {
clay.ID("Header"), clay.ID("Header"),
clay.Layout({sizing = {clay.SizingGrow({}), clay.SizingFixed(50)}, childAlignment = {y = .CENTER}, childGap = 24, padding = {x = 32}}), clay.Layout({sizing = {clay.SizingGrow({}), clay.SizingFixed(50)}, childAlignment = {y = .CENTER}, childGap = 24, padding = {x = 32}}),
) { ) {
clay.Text(clay.ID("Logo"), clay.MakeString("Clay"), &headerTextConfig) clay.Text(clay.ID("Logo"), "Clay", &headerTextConfig)
if clay.Container(clay.ID("Spacer"), clay.Layout({sizing = {width = clay.SizingGrow({})}})) {} if clay.Container(clay.ID("Spacer"), clay.Layout({sizing = {width = clay.SizingGrow({})}})) {}
if (!mobileScreen) { if (!mobileScreen) {
if clay.Rectangle(clay.ID("LinkExamplesOuter"), clay.Layout({}), clay.RectangleConfig({color = {0, 0, 0, 0}})) { if clay.Rectangle(clay.ID("LinkExamplesOuter"), clay.Layout({}), clay.RectangleConfig({color = {0, 0, 0, 0}})) {
clay.Text(clay.ID("LinkExamplesText"), clay.MakeString("Examples"), clay.TextConfig({fontId = FONT_ID_BODY_24, fontSize = 24, textColor = {61, 26, 5, 255}})) clay.Text(clay.ID("LinkExamplesText"), "Examples", clay.TextConfig({fontId = FONT_ID_BODY_24, fontSize = 24, textColor = {61, 26, 5, 255}}))
} }
if clay.Rectangle(clay.ID("LinkDocsOuter"), clay.Layout({}), clay.RectangleConfig({color = {0, 0, 0, 0}})) { if clay.Rectangle(clay.ID("LinkDocsOuter"), clay.Layout({}), clay.RectangleConfig({color = {0, 0, 0, 0}})) {
clay.Text(clay.ID("LinkDocsText"), clay.MakeString("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: u32 = clay.ID("HeaderButtonGithub")
@ -461,7 +457,7 @@ createLayout :: proc(lerpValue: f32) -> clay.ClayArray(clay.RenderCommand) {
clay.Layout({padding = {16, 6}}), clay.Layout({padding = {16, 6}}),
clay.RectangleConfig({cornerRadius = clay.CornerRadiusAll(10), color = clay.PointerOver(githubButtonId) ? COLOR_LIGHT_HOVER : COLOR_LIGHT}), clay.RectangleConfig({cornerRadius = clay.CornerRadiusAll(10), color = clay.PointerOver(githubButtonId) ? COLOR_LIGHT_HOVER : COLOR_LIGHT}),
) { ) {
clay.Text(clay.ID("LinkGithubText"), clay.MakeString("Github"), clay.TextConfig({fontId = FONT_ID_BODY_24, fontSize = 24, textColor = {61, 26, 5, 255}})) clay.Text(clay.ID("LinkGithubText"), "Github", clay.TextConfig({fontId = FONT_ID_BODY_24, fontSize = 24, textColor = {61, 26, 5, 255}}))
} }
} }
} }
@ -510,7 +506,7 @@ loadFont :: proc(fontId: u16, fontSize: u16, path: cstring) {
} }
main :: proc() { main :: proc() {
minMemorySize: c.uint32_t = clay.MinMemorySize() minMemorySize: u32 = clay.MinMemorySize()
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)

View File

@ -23,16 +23,16 @@ measureText :: proc "c" (text: ^clay.String, config: ^clay.TextElementConfig) ->
maxTextWidth: f32 = 0 maxTextWidth: f32 = 0
lineTextWidth: f32 = 0 lineTextWidth: f32 = 0
textHeight: f32 = cast(f32)config.fontSize textHeight := cast(f32)config.fontSize
fontToUse := raylibFonts[config.fontId].font fontToUse := raylibFonts[config.fontId].font
for i := 0; i < cast(int)text.length; i += 1 { for i in 0..<int(text.length) {
if (text.chars[i] == '\n') { if (text.chars[i] == '\n') {
maxTextWidth = math.max(maxTextWidth, lineTextWidth) maxTextWidth = max(maxTextWidth, lineTextWidth)
lineTextWidth = 0 lineTextWidth = 0
continue continue
} }
index: i32 = cast(i32)text.chars[i] - 32 index := cast(i32)text.chars[i] - 32
if (fontToUse.glyphs[index].advanceX != 0) { if (fontToUse.glyphs[index].advanceX != 0) {
lineTextWidth += cast(f32)fontToUse.glyphs[index].advanceX lineTextWidth += cast(f32)fontToUse.glyphs[index].advanceX
} else { } else {
@ -40,7 +40,7 @@ measureText :: proc "c" (text: ^clay.String, config: ^clay.TextElementConfig) ->
} }
} }
maxTextWidth = math.max(maxTextWidth, lineTextWidth) maxTextWidth = max(maxTextWidth, lineTextWidth)
textSize.width = maxTextWidth / 2 textSize.width = maxTextWidth / 2
textSize.height = textHeight textSize.height = textHeight
@ -49,15 +49,13 @@ 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 := 0; i < cast(int)renderCommands.length; i += 1 { 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)
@ -70,145 +68,132 @@ clayRaylibRender :: proc(renderCommands: ^clay.ClayArray(clay.RenderCommand), al
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 raylib.DrawTextureEx(imageTexture^, raylib.Vector2{boundingBox.x, boundingBox.y}, 0, boundingBox.width / cast(f32)imageTexture.width, raylib.WHITE)
raylib.DrawTextureEx(imageTexture^, raylib.Vector2{boundingBox.x, boundingBox.y}, 0, boundingBox.width / cast(f32)imageTexture.width, raylib.WHITE)
}
case clay.RenderCommandType.ScissorStart: case clay.RenderCommandType.ScissorStart:
{ raylib.BeginScissorMode(
raylib.BeginScissorMode( cast(i32)math.round(boundingBox.x),
cast(i32)math.round(boundingBox.x), cast(i32)math.round(boundingBox.y),
cast(i32)math.round(boundingBox.y), cast(i32)math.round(boundingBox.width),
cast(i32)math.round(boundingBox.width), cast(i32)math.round(boundingBox.height),
cast(i32)math.round(boundingBox.height), )
case clay.RenderCommandType.ScissorEnd:
raylib.EndScissorMode()
case clay.RenderCommandType.Rectangle:
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),
)
} else {
raylib.DrawRectangle(
cast(i32)boundingBox.x,
cast(i32)boundingBox.y,
cast(i32)boundingBox.width,
cast(i32)boundingBox.height,
clayColorToRaylibColor(config.color),
) )
} }
case clay.RenderCommandType.ScissorEnd:
{
raylib.EndScissorMode()
}
case clay.RenderCommandType.Rectangle:
{
config: ^clay.RectangleElementConfig = renderCommand.config.rectangleElementConfig
if (config.cornerRadius.topLeft > 0) {
radius: f32 = (config.cornerRadius.topLeft * 2) / (boundingBox.width > boundingBox.height ? boundingBox.height : boundingBox.width)
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),
)
}
}
case clay.RenderCommandType.Border: case clay.RenderCommandType.Border:
{ config := renderCommand.config.borderElementConfig
config := renderCommand.config.borderElementConfig // Left border
// Left border if (config.left.width > 0) {
if (config.left.width > 0) { raylib.DrawRectangle(
raylib.DrawRectangle( cast(i32)math.round(boundingBox.x),
cast(i32)math.round(boundingBox.x), cast(i32)math.round(boundingBox.y + config.cornerRadius.topLeft),
cast(i32)math.round(boundingBox.y + config.cornerRadius.topLeft), cast(i32)config.left.width,
cast(i32)config.left.width, cast(i32)math.round(boundingBox.height - config.cornerRadius.topLeft - config.cornerRadius.bottomLeft),
cast(i32)math.round(boundingBox.height - config.cornerRadius.topLeft - config.cornerRadius.bottomLeft), clayColorToRaylibColor(config.left.color),
clayColorToRaylibColor(config.left.color), )
) }
} // Right border
// Right border if (config.right.width > 0) {
if (config.right.width > 0) { raylib.DrawRectangle(
raylib.DrawRectangle( cast(i32)math.round(boundingBox.x + boundingBox.width - cast(f32)config.right.width),
cast(i32)math.round(boundingBox.x + boundingBox.width - cast(f32)config.right.width), cast(i32)math.round(boundingBox.y + config.cornerRadius.topRight),
cast(i32)math.round(boundingBox.y + config.cornerRadius.topRight), cast(i32)config.right.width,
cast(i32)config.right.width, cast(i32)math.round(boundingBox.height - config.cornerRadius.topRight - config.cornerRadius.bottomRight),
cast(i32)math.round(boundingBox.height - config.cornerRadius.topRight - config.cornerRadius.bottomRight), clayColorToRaylibColor(config.right.color),
clayColorToRaylibColor(config.right.color), )
) }
} // Top border
// Top border if (config.top.width > 0) {
if (config.top.width > 0) { raylib.DrawRectangle(
raylib.DrawRectangle( cast(i32)math.round(boundingBox.x + config.cornerRadius.topLeft),
cast(i32)math.round(boundingBox.x + config.cornerRadius.topLeft), cast(i32)math.round(boundingBox.y),
cast(i32)math.round(boundingBox.y), cast(i32)math.round(boundingBox.width - config.cornerRadius.topLeft - config.cornerRadius.topRight),
cast(i32)math.round(boundingBox.width - config.cornerRadius.topLeft - config.cornerRadius.topRight), cast(i32)config.top.width,
cast(i32)config.top.width, clayColorToRaylibColor(config.top.color),
clayColorToRaylibColor(config.top.color), )
) }
} // Bottom border
// Bottom border if (config.bottom.width > 0) {
if (config.bottom.width > 0) { raylib.DrawRectangle(
raylib.DrawRectangle( cast(i32)math.round(boundingBox.x + config.cornerRadius.bottomLeft),
cast(i32)math.round(boundingBox.x + config.cornerRadius.bottomLeft), cast(i32)math.round(boundingBox.y + boundingBox.height - cast(f32)config.bottom.width),
cast(i32)math.round(boundingBox.y + boundingBox.height - cast(f32)config.bottom.width), cast(i32)math.round(boundingBox.width - config.cornerRadius.bottomLeft - config.cornerRadius.bottomRight),
cast(i32)math.round(boundingBox.width - config.cornerRadius.bottomLeft - config.cornerRadius.bottomRight), cast(i32)config.bottom.width,
cast(i32)config.bottom.width, clayColorToRaylibColor(config.bottom.color),
clayColorToRaylibColor(config.bottom.color), )
) }
} if (config.cornerRadius.topLeft > 0) {
if (config.cornerRadius.topLeft > 0) { raylib.DrawRing(
raylib.DrawRing( raylib.Vector2{math.round(boundingBox.x + config.cornerRadius.topLeft), math.round(boundingBox.y + config.cornerRadius.topLeft)},
raylib.Vector2{math.round(boundingBox.x + config.cornerRadius.topLeft), math.round(boundingBox.y + config.cornerRadius.topLeft)}, math.round(config.cornerRadius.topLeft - cast(f32)config.top.width),
math.round(config.cornerRadius.topLeft - cast(f32)config.top.width), config.cornerRadius.topLeft,
config.cornerRadius.topLeft, 180,
180, 270,
270, 10,
10, clayColorToRaylibColor(config.top.color),
clayColorToRaylibColor(config.top.color), )
) }
} if (config.cornerRadius.topRight > 0) {
if (config.cornerRadius.topRight > 0) { raylib.DrawRing(
raylib.DrawRing( raylib.Vector2{math.round(boundingBox.x + boundingBox.width - config.cornerRadius.topRight), math.round(boundingBox.y + config.cornerRadius.topRight)},
raylib.Vector2{math.round(boundingBox.x + boundingBox.width - config.cornerRadius.topRight), math.round(boundingBox.y + config.cornerRadius.topRight)}, math.round(config.cornerRadius.topRight - cast(f32)config.top.width),
math.round(config.cornerRadius.topRight - cast(f32)config.top.width), config.cornerRadius.topRight,
config.cornerRadius.topRight, 270,
270, 360,
360, 10,
10, clayColorToRaylibColor(config.top.color),
clayColorToRaylibColor(config.top.color), )
) }
} 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.x + config.cornerRadius.bottomLeft), math.round(boundingBox.y + boundingBox.height - 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, 180,
180, 10,
10, clayColorToRaylibColor(config.bottom.color),
clayColorToRaylibColor(config.bottom.color), )
) }
} if (config.cornerRadius.bottomRight > 0) {
if (config.cornerRadius.bottomRight > 0) { raylib.DrawRing(
raylib.DrawRing( raylib.Vector2 {
raylib.Vector2 { math.round(boundingBox.x + boundingBox.width - config.cornerRadius.bottomRight),
math.round(boundingBox.x + boundingBox.width - config.cornerRadius.bottomRight), math.round(boundingBox.y + boundingBox.height - config.cornerRadius.bottomRight),
math.round(boundingBox.y + boundingBox.height - config.cornerRadius.bottomRight), },
}, math.round(config.cornerRadius.bottomRight - cast(f32)config.bottom.width),
math.round(config.cornerRadius.bottomRight - cast(f32)config.bottom.width), config.cornerRadius.bottomRight,
config.cornerRadius.bottomRight, 0.1,
0.1, 90,
90, 10,
10, clayColorToRaylibColor(config.bottom.color),
clayColorToRaylibColor(config.bottom.color), )
)
}
} }
case clay.RenderCommandType.Custom: case clay.RenderCommandType.Custom:
{ // Implement custom element rendering here
// Implement custom element rendering here
}
} }
} }
} }