mirror of
				https://github.com/nicbarker/clay.git
				synced 2025-11-04 08:36:17 +00:00 
			
		
		
		
	Odin Bindings - First Pass (#5)
This commit is contained in:
		
							parent
							
								
									fd45138d57
								
							
						
					
					
						commit
						3f7005faae
					
				
							
								
								
									
										4
									
								
								bindings/odin/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								bindings/odin/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,4 @@
 | 
			
		|||
odin
 | 
			
		||||
odin.dSYM
 | 
			
		||||
.vscode
 | 
			
		||||
examples/clay-official-website/clay-official-website
 | 
			
		||||
							
								
								
									
										145
									
								
								bindings/odin/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										145
									
								
								bindings/odin/README.md
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,145 @@
 | 
			
		|||
### Odin Language Bindings
 | 
			
		||||
 | 
			
		||||
This directory contains bindings for the [Odin](odin-lang.org) programming language, as well as an example implementation of the [clay website](https://nicbarker.com/clay) in Odin.
 | 
			
		||||
 | 
			
		||||
If you haven't taken a look at the [full documentation for clay](https://github.com/nicbarker/clay/blob/main/README.md), it's recommended that you take a look there first to familiarise yourself with the general concepts. This README is abbreviated and applies to using clay in Odin specifically.
 | 
			
		||||
 | 
			
		||||
The **most notable difference** between the C API and the Odin bindings is the use of if statements to create the scope for declaring child elements. When using the equivalent of the [Element Macros](https://github.com/nicbarker/clay/blob/main/README.md#element-macros):
 | 
			
		||||
 | 
			
		||||
Special thanks to
 | 
			
		||||
 | 
			
		||||
- [laytan](https://github.com/laytan)
 | 
			
		||||
- [Dudejoe870](https://github.com/Dudejoe870)
 | 
			
		||||
- MrStevns from the Odin Discord server
 | 
			
		||||
 | 
			
		||||
```C
 | 
			
		||||
// C form of element macros
 | 
			
		||||
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}), CLAY_RECTANGLE_CONFIG(.color = COLOR_LIGHT), {
 | 
			
		||||
	// Child elements here
 | 
			
		||||
});
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
```Odin
 | 
			
		||||
// Odin form of element macros
 | 
			
		||||
if clay.Rectangle(clay.ID("SideBar"), clay.Layout({ layoutDirection = .TOP_TO_BOTTOM, sizing = { width = clay.SizingFixed(300), height = clay.SizingGrow({}) }, padding = {16, 16} }), clay.RectangleConfig({ color = COLOR_LIGHT })) {
 | 
			
		||||
	// Child elements here
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### Quick Start
 | 
			
		||||
 | 
			
		||||
1. Download the [clay-odin](link todo) directory and copy it into your project.
 | 
			
		||||
 | 
			
		||||
```Odin
 | 
			
		||||
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).
 | 
			
		||||
 | 
			
		||||
```Odin
 | 
			
		||||
minMemorySize: c.uint32_t = clay.MinMemorySize()
 | 
			
		||||
memory := make([^]u8, minMemorySize)
 | 
			
		||||
arena: clay.Arena = clay.CreateArenaWithCapacityAndMemory(minMemorySize, memory)
 | 
			
		||||
``` 
 | 
			
		||||
 | 
			
		||||
3. Provide a `measureText(text, config)` proc "c" with [clay.SetMeasureTextFunction(function)](https://github.com/nicbarker/clay/blob/main/README.md#clay_setmeasuretextfunction) so that clay can measure and wrap text.
 | 
			
		||||
 | 
			
		||||
```Odin
 | 
			
		||||
// Example measure text function
 | 
			
		||||
measureText :: proc "c" (text: ^clay.String, config: ^clay.TextElementConfig) -> clay.Dimensions {
 | 
			
		||||
    // clay.TextElementConfig contains members such as fontId, fontSize, letterSpacing etc
 | 
			
		||||
    // Note: clay.String->chars is not guaranteed to be null terminated
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Tell clay how to measure text
 | 
			
		||||
clay.SetMeasureTextFunction(measureText)
 | 
			
		||||
``` 
 | 
			
		||||
 | 
			
		||||
4. **Optional** - Call [clay.SetPointerPosition(pointerPosition)](https://github.com/nicbarker/clay/blob/main/README.md#clay_setpointerposition) if you want to use mouse interactions.
 | 
			
		||||
 | 
			
		||||
```Odin
 | 
			
		||||
// Update internal pointer position for handling mouseover / click / touch events
 | 
			
		||||
clay.SetPointerPosition(clay.Vector2{ mousePositionX, mousePositionY })
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
5. Call [clay.BeginLayout(screenWidth, screenHeight)](https://github.com/nicbarker/clay/blob/main/README.md#clay_beginlayout) and declare your layout using the provided macros.
 | 
			
		||||
 | 
			
		||||
```Odin
 | 
			
		||||
COLOR_LIGHT :: clay.Color{224, 215, 210, 255}
 | 
			
		||||
COLOR_RED :: clay.Color{168, 66, 28, 255}
 | 
			
		||||
COLOR_ORANGE :: clay.Color{225, 138, 50, 255}
 | 
			
		||||
 | 
			
		||||
// Layout config is just a struct that can be declared statically, or inline
 | 
			
		||||
sidebarItemLayout := clay.LayoutConfig {
 | 
			
		||||
    sizing = {width = clay.SizingGrow({}), height = clay.SizingFixed(50)},
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Re-useable components are just normal functions
 | 
			
		||||
SidebarItemComponent :: proc(index: u32) {
 | 
			
		||||
    if clay.Rectangle(clay.IDI("SidebarBlob", index), &sidebarItemLayout, clay.RectangleConfig({color = COLOR_ORANGE})) {}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// An example function to begin the "root" of your layout tree
 | 
			
		||||
CreateLayout :: proc() -> clay.ClayArray(clay.RenderCommand) {
 | 
			
		||||
    clay.BeginLayout(windowWidth, windowHeight)
 | 
			
		||||
 | 
			
		||||
    // An example of laying out a UI with a fixed width sidebar and flexible width main content
 | 
			
		||||
    // NOTE: To create a scope for child components, the Odin api uses `if` with components that have children
 | 
			
		||||
    if clay.Rectangle(
 | 
			
		||||
        clay.ID("OuterContainer"),
 | 
			
		||||
        clay.Layout({sizing = {clay.SizingGrow({}), clay.SizingGrow({})}, padding = {16, 16}, childGap = 16}),
 | 
			
		||||
        clay.RectangleConfig({color = {250, 250, 255, 255}}),
 | 
			
		||||
    ) {
 | 
			
		||||
        if clay.Rectangle(
 | 
			
		||||
            clay.ID("SideBar"),
 | 
			
		||||
            clay.Layout({layoutDirection = .TOP_TO_BOTTOM, sizing = {width = clay.SizingFixed(300), height = clay.SizingGrow({})}, padding = {16, 16}, childGap = 16}),
 | 
			
		||||
            clay.RectangleConfig({color = COLOR_LIGHT}),
 | 
			
		||||
        ) {
 | 
			
		||||
            if clay.Rectangle(
 | 
			
		||||
                clay.ID("ProfilePictureOuter"),
 | 
			
		||||
                clay.Layout({sizing = {width = clay.SizingGrow({})}, padding = {16, 16}, childGap = 16, childAlignment = {y = .CENTER}}),
 | 
			
		||||
                clay.RectangleConfig({color = COLOR_RED}),
 | 
			
		||||
            ) {
 | 
			
		||||
                if clay.Image(
 | 
			
		||||
                    clay.ID("ProfilePicture"),
 | 
			
		||||
                    clay.Layout({sizing = {width = clay.SizingFixed(60), height = clay.SizingFixed(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}}))
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Standard Odin code like loops etc work inside components
 | 
			
		||||
            for i: u32 = 0; i < 10; i += 1 {
 | 
			
		||||
                SidebarItemComponent(i)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if clay.Rectangle(
 | 
			
		||||
            clay.ID("MainContent"),
 | 
			
		||||
            clay.Layout({sizing = {width = clay.SizingGrow({}), height = clay.SizingGrow({})}}),
 | 
			
		||||
            clay.RectangleConfig({color = COLOR_LIGHT}),
 | 
			
		||||
        ) {}
 | 
			
		||||
    }
 | 
			
		||||
    // ...
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
6. Call [clay.EndLayout(screenWidth, screenHeight)](https://github.com/nicbarker/clay/blob/main/README.md#clay_endlayout) and process the resulting [clay.RenderCommandArray](https://github.com/nicbarker/clay/blob/main/README.md#clay_rendercommandarray) in your choice of renderer.
 | 
			
		||||
 | 
			
		||||
```Odin
 | 
			
		||||
renderCommands: clay.ClayArray(clay.RenderCommand) = clay.EndLayout(windowWidth, windowHeight)
 | 
			
		||||
 | 
			
		||||
for i: u32 = 0; i < renderCommands.length; i += 1 {
 | 
			
		||||
	renderCommand := clay.RenderCommandArray_Get(&renderCommands, cast(i32)i)
 | 
			
		||||
 | 
			
		||||
	switch renderCommand.commandType {
 | 
			
		||||
	case .Rectangle:
 | 
			
		||||
		{
 | 
			
		||||
			DrawRectangle(renderCommand.boundingBox, renderCommand.config.rectangleElementConfig.color)
 | 
			
		||||
		}
 | 
			
		||||
	// ... Implement handling of other command types
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Please see the [full C documentation for clay](https://github.com/nicbarker/clay/blob/main/README.md) for API details. All public C functions and Macros have Odin binding equivalents, generally of the form `CLAY_RECTANGLE` (C) -> `clay.Rectangle` (Odin)
 | 
			
		||||
							
								
								
									
										6
									
								
								bindings/odin/build-clay-lib.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										6
									
								
								bindings/odin/build-clay-lib.sh
									
									
									
									
									
										Executable file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,6 @@
 | 
			
		|||
cp ../../clay.h clay.c;
 | 
			
		||||
clang -c -o clay.o -static -target x86_64-apple-darwin clay.c -fPIC && ar r clay-odin/macos/clay.a clay.o;
 | 
			
		||||
clang -c -o clay.o -static clay.c -fPIC && ar r clay-odin/macos-arm64/clay.a clay.o;
 | 
			
		||||
clang -c -o clay-odin/windows/clay.lib -target x86_64-pc-windows-msvc -fuse-ld=llvm-lib -static clay.c;
 | 
			
		||||
rm clay.o;
 | 
			
		||||
rm clay.c;
 | 
			
		||||
							
								
								
									
										434
									
								
								bindings/odin/clay-odin/clay.odin
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										434
									
								
								bindings/odin/clay-odin/clay.odin
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,434 @@
 | 
			
		|||
package clay
 | 
			
		||||
 | 
			
		||||
import "core:c"
 | 
			
		||||
import "core:strings"
 | 
			
		||||
 | 
			
		||||
when ODIN_OS == .Windows {
 | 
			
		||||
    foreign import Clay "windows/clay.lib"
 | 
			
		||||
} else when ODIN_OS == .Linux {
 | 
			
		||||
    foreign import Clay "linux/libclay.a"
 | 
			
		||||
} else when ODIN_OS == .Darwin {
 | 
			
		||||
    when ODIN_ARCH == .arm64 {
 | 
			
		||||
        foreign import Clay "macos-arm64/clay.a"
 | 
			
		||||
    } else {
 | 
			
		||||
        foreign import Clay "macos/clay.a"
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
String :: struct {
 | 
			
		||||
    length: c.int,
 | 
			
		||||
    chars:  [^]c.char,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Vector2 :: [2]c.float
 | 
			
		||||
 | 
			
		||||
Dimensions :: struct {
 | 
			
		||||
    width:  c.float,
 | 
			
		||||
    height: c.float,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Arena :: struct {
 | 
			
		||||
    label:          String,
 | 
			
		||||
    nextAllocation: c.uint64_t,
 | 
			
		||||
    capacity:       c.uint64_t,
 | 
			
		||||
    memory:         [^]c.char,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
BoundingBox :: struct {
 | 
			
		||||
    x:      c.float,
 | 
			
		||||
    y:      c.float,
 | 
			
		||||
    width:  c.float,
 | 
			
		||||
    height: c.float,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Color :: [4]c.float
 | 
			
		||||
 | 
			
		||||
CornerRadius :: struct {
 | 
			
		||||
    topLeft:     c.float,
 | 
			
		||||
    topRight:    c.float,
 | 
			
		||||
    bottomLeft:  c.float,
 | 
			
		||||
    bottomRight: c.float,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
BorderData :: struct {
 | 
			
		||||
    width: c.uint32_t,
 | 
			
		||||
    color: Color,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
RenderCommandType :: enum u8 {
 | 
			
		||||
    None,
 | 
			
		||||
    Rectangle,
 | 
			
		||||
    Border,
 | 
			
		||||
    Text,
 | 
			
		||||
    Image,
 | 
			
		||||
    ScissorStart,
 | 
			
		||||
    ScissorEnd,
 | 
			
		||||
    Custom,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
RectangleElementConfig :: struct {
 | 
			
		||||
    color:        Color,
 | 
			
		||||
    cornerRadius: CornerRadius,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TextElementConfig :: struct {
 | 
			
		||||
    textColor:     Color,
 | 
			
		||||
    fontId:        c.uint16_t,
 | 
			
		||||
    fontSize:      c.uint16_t,
 | 
			
		||||
    letterSpacing: c.uint16_t,
 | 
			
		||||
    lineSpacing:   c.uint16_t,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ImageElementConfig :: struct {
 | 
			
		||||
    imageData:        rawptr,
 | 
			
		||||
    sourceDimensions: Dimensions,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
CustomElementConfig :: struct {
 | 
			
		||||
    customData: rawptr,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
BorderElementConfig :: struct {
 | 
			
		||||
    left:            BorderData,
 | 
			
		||||
    right:           BorderData,
 | 
			
		||||
    top:             BorderData,
 | 
			
		||||
    bottom:          BorderData,
 | 
			
		||||
    betweenChildren: BorderData,
 | 
			
		||||
    cornerRadius:    CornerRadius,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ScrollElementConfig :: struct {
 | 
			
		||||
    horizontal: c.bool,
 | 
			
		||||
    vertical:   c.bool,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
FloatingAttachPointType :: enum u8 {
 | 
			
		||||
    LEFT_TOP,
 | 
			
		||||
    LEFT_CENTER,
 | 
			
		||||
    LEFT_BOTTOM,
 | 
			
		||||
    CENTER_TOP,
 | 
			
		||||
    CENTER_CENTER,
 | 
			
		||||
    CENTER_BOTTOM,
 | 
			
		||||
    RIGHT_TOP,
 | 
			
		||||
    RIGHT_CENTER,
 | 
			
		||||
    RIGHT_BOTTOM,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
FloatingAttachPoints :: struct {
 | 
			
		||||
    element: FloatingAttachPointType,
 | 
			
		||||
    parent:  FloatingAttachPointType,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
FloatingElementConfig :: struct {
 | 
			
		||||
    offset:     Vector2,
 | 
			
		||||
    expand:     Dimensions,
 | 
			
		||||
    zIndex:     c.uint16_t,
 | 
			
		||||
    parentId:   c.uint32_t,
 | 
			
		||||
    attachment: FloatingAttachPoints,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ElementConfigUnion :: struct #raw_union {
 | 
			
		||||
    rectangleElementConfig: ^RectangleElementConfig,
 | 
			
		||||
    textElementConfig:      ^TextElementConfig,
 | 
			
		||||
    imageElementConfig:     ^ImageElementConfig,
 | 
			
		||||
    customElementConfig:    ^CustomElementConfig,
 | 
			
		||||
    borderElementConfig:    ^BorderElementConfig,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
RenderCommand :: struct {
 | 
			
		||||
    boundingBox: BoundingBox,
 | 
			
		||||
    config:      ElementConfigUnion,
 | 
			
		||||
    text:        String,
 | 
			
		||||
    id:          c.uint32_t,
 | 
			
		||||
    commandType: RenderCommandType,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ScrollContainerData :: struct {
 | 
			
		||||
    // Note: This is a pointer to the real internal scroll position, mutating it may cause a change in final layout.
 | 
			
		||||
    // Intended for use with external functionality that modifies scroll position, such as scroll bars or auto scrolling.
 | 
			
		||||
    scrollPosition:            ^Vector2,
 | 
			
		||||
    scrollContainerDimensions: Dimensions,
 | 
			
		||||
    contentDimensions:         Dimensions,
 | 
			
		||||
    config:                    ScrollElementConfig,
 | 
			
		||||
    // Indicates whether an actual scroll container matched the provided ID or if the default struct was returned.
 | 
			
		||||
    found:                     c.bool,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
SizingType :: enum u8 {
 | 
			
		||||
    FIT,
 | 
			
		||||
    GROW,
 | 
			
		||||
    PERCENT,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
SizingConstraintsMinMax :: struct {
 | 
			
		||||
    min: c.float,
 | 
			
		||||
    max: c.float,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
SizingConstraints :: struct #raw_union {
 | 
			
		||||
    sizeMinMax:  SizingConstraintsMinMax,
 | 
			
		||||
    sizePercent: c.float,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
SizingAxis :: struct {
 | 
			
		||||
    // Note: `min` is used for CLAY_SIZING_PERCENT, slightly different to clay.h due to lack of C anonymous unions
 | 
			
		||||
    constraints: SizingConstraints,
 | 
			
		||||
    type:        SizingType,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Sizing :: struct {
 | 
			
		||||
    width:  SizingAxis,
 | 
			
		||||
    height: SizingAxis,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Padding :: struct {
 | 
			
		||||
    x: c.uint16_t,
 | 
			
		||||
    y: c.uint16_t,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
LayoutDirection :: enum u8 {
 | 
			
		||||
    LEFT_TO_RIGHT,
 | 
			
		||||
    TOP_TO_BOTTOM,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
LayoutAlignmentX :: enum u8 {
 | 
			
		||||
    LEFT,
 | 
			
		||||
    RIGHT,
 | 
			
		||||
    CENTER,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
LayoutAlignmentY :: enum u8 {
 | 
			
		||||
    TOP,
 | 
			
		||||
    BOTTOM,
 | 
			
		||||
    CENTER,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ChildAlignment :: struct {
 | 
			
		||||
    x: LayoutAlignmentX,
 | 
			
		||||
    y: LayoutAlignmentY,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
LayoutConfig :: struct {
 | 
			
		||||
    sizing:          Sizing,
 | 
			
		||||
    padding:         Padding,
 | 
			
		||||
    childGap:        c.uint16_t,
 | 
			
		||||
    layoutDirection: LayoutDirection,
 | 
			
		||||
    childAlignment:  ChildAlignment,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ClayArray :: struct($type: typeid) {
 | 
			
		||||
    capacity:      c.uint32_t,
 | 
			
		||||
    length:        c.uint32_t,
 | 
			
		||||
    internalArray: [^]type,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@(link_prefix = "Clay_")
 | 
			
		||||
foreign Clay {
 | 
			
		||||
    MinMemorySize :: proc() -> c.uint32_t ---
 | 
			
		||||
    CreateArenaWithCapacityAndMemory :: proc(capacity: c.uint32_t, offset: [^]u8) -> Arena ---
 | 
			
		||||
    SetPointerPosition :: proc(position: Vector2) ---
 | 
			
		||||
    Initialize :: proc(arena: Arena) ---
 | 
			
		||||
    UpdateScrollContainers :: proc(isPointerActive: c.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: c.uint32_t) -> c.bool ---
 | 
			
		||||
    GetScrollContainerData :: proc(id: c.uint32_t) -> ScrollContainerData ---
 | 
			
		||||
    SetMeasureTextFunction :: proc(measureTextFunction: proc(text: ^String, config: ^TextElementConfig) -> Dimensions) ---
 | 
			
		||||
    RenderCommandArray_Get :: proc(array: ^ClayArray(RenderCommand), index: c.int32_t) -> ^RenderCommand ---
 | 
			
		||||
    @(private)
 | 
			
		||||
    _OpenContainerElement :: proc(id: c.uint32_t, layoutConfig: ^LayoutConfig) ---
 | 
			
		||||
    @(private)
 | 
			
		||||
    _OpenRectangleElement :: proc(id: c.uint32_t, layoutConfig: ^LayoutConfig, rectangleConfig: ^RectangleElementConfig) ---
 | 
			
		||||
    @(private)
 | 
			
		||||
    _OpenTextElement :: proc(id: c.uint32_t, text: String, textConfig: ^TextElementConfig) ---
 | 
			
		||||
    @(private)
 | 
			
		||||
    _OpenImageElement :: proc(id: c.uint32_t, layoutConfig: ^LayoutConfig, imageConfig: ^ImageElementConfig) ---
 | 
			
		||||
    @(private)
 | 
			
		||||
    _OpenScrollElement :: proc(id: c.uint32_t, layoutConfig: ^LayoutConfig, imageConfig: ^ScrollElementConfig) ---
 | 
			
		||||
    @(private)
 | 
			
		||||
    _OpenFloatingElement :: proc(id: c.uint32_t, layoutConfig: ^LayoutConfig, imageConfig: ^FloatingElementConfig) ---
 | 
			
		||||
    @(private)
 | 
			
		||||
    _OpenBorderElement :: proc(id: c.uint32_t, layoutConfig: ^LayoutConfig, imageConfig: ^BorderElementConfig) ---
 | 
			
		||||
    @(private)
 | 
			
		||||
    _OpenCustomElement :: proc(id: c.uint32_t, layoutConfig: ^LayoutConfig, imageConfig: ^CustomElementConfig) ---
 | 
			
		||||
    @(private)
 | 
			
		||||
    _CloseElementWithChildren :: proc() ---
 | 
			
		||||
    @(private)
 | 
			
		||||
    _CloseScrollElement :: proc() ---
 | 
			
		||||
    @(private)
 | 
			
		||||
    _CloseFloatingElement :: proc() ---
 | 
			
		||||
    @(private)
 | 
			
		||||
    _layoutConfigs: ClayArray(LayoutConfig)
 | 
			
		||||
    @(private)
 | 
			
		||||
    _LayoutConfigArray_Add :: proc(array: ^ClayArray(LayoutConfig), config: LayoutConfig) -> ^LayoutConfig ---
 | 
			
		||||
    @(private)
 | 
			
		||||
    _rectangleElementConfigs: ClayArray(RectangleElementConfig)
 | 
			
		||||
    @(private)
 | 
			
		||||
    _RectangleElementConfigArray_Add :: proc(array: ^ClayArray(RectangleElementConfig), config: RectangleElementConfig) -> ^RectangleElementConfig ---
 | 
			
		||||
    @(private)
 | 
			
		||||
    _textElementConfigs: ClayArray(TextElementConfig)
 | 
			
		||||
    @(private)
 | 
			
		||||
    _TextElementConfigArray_Add :: proc(array: ^ClayArray(TextElementConfig), config: TextElementConfig) -> ^TextElementConfig ---
 | 
			
		||||
    @(private)
 | 
			
		||||
    _imageElementConfigs: ClayArray(ImageElementConfig)
 | 
			
		||||
    @(private)
 | 
			
		||||
    _ImageElementConfigArray_Add :: proc(array: ^ClayArray(ImageElementConfig), config: ImageElementConfig) -> ^ImageElementConfig ---
 | 
			
		||||
    @(private)
 | 
			
		||||
    _floatingElementConfigs: ClayArray(FloatingElementConfig)
 | 
			
		||||
    @(private)
 | 
			
		||||
    _FloatingElementConfigArray_Add :: proc(array: ^ClayArray(FloatingElementConfig), config: FloatingElementConfig) -> ^FloatingElementConfig ---
 | 
			
		||||
    @(private)
 | 
			
		||||
    _customElementConfigs: ClayArray(CustomElementConfig)
 | 
			
		||||
    @(private)
 | 
			
		||||
    _CustomElementConfigArray_Add :: proc(array: ^ClayArray(CustomElementConfig), config: CustomElementConfig) -> ^CustomElementConfig ---
 | 
			
		||||
    @(private)
 | 
			
		||||
    _scrollElementConfigs: ClayArray(ScrollElementConfig)
 | 
			
		||||
    @(private)
 | 
			
		||||
    _ScrollElementConfigArray_Add :: proc(array: ^ClayArray(ScrollElementConfig), config: ScrollElementConfig) -> ^ScrollElementConfig ---
 | 
			
		||||
    @(private)
 | 
			
		||||
    _borderElementConfigs: ClayArray(BorderElementConfig)
 | 
			
		||||
    @(private)
 | 
			
		||||
    _BorderElementConfigArray_Add :: proc(array: ^ClayArray(BorderElementConfig), config: BorderElementConfig) -> ^BorderElementConfig ---
 | 
			
		||||
    @(private)
 | 
			
		||||
    _HashString :: proc(toHash: String, index: c.uint32_t) -> c.uint32_t ---
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@(require_results, deferred_none = _CloseElementWithChildren)
 | 
			
		||||
Container :: proc(id: c.uint32_t, layoutConfig: ^LayoutConfig) -> bool {
 | 
			
		||||
    _OpenContainerElement(id, layoutConfig)
 | 
			
		||||
    return true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@(require_results, deferred_none = _CloseElementWithChildren)
 | 
			
		||||
Rectangle :: proc(id: c.uint32_t, layoutConfig: ^LayoutConfig, rectangleConfig: ^RectangleElementConfig) -> bool {
 | 
			
		||||
    _OpenRectangleElement(id, layoutConfig, rectangleConfig)
 | 
			
		||||
    return true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Text :: proc(id: c.uint32_t, text: String, textConfig: ^TextElementConfig) -> bool {
 | 
			
		||||
    _OpenTextElement(id, text, textConfig)
 | 
			
		||||
    return true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@(require_results, deferred_none = _CloseElementWithChildren)
 | 
			
		||||
Image :: proc(id: c.uint32_t, layoutConfig: ^LayoutConfig, imageConfig: ^ImageElementConfig) -> bool {
 | 
			
		||||
    _OpenImageElement(id, layoutConfig, imageConfig)
 | 
			
		||||
    return true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@(require_results, deferred_none = _CloseScrollElement)
 | 
			
		||||
Scroll :: proc(id: c.uint32_t, layoutConfig: ^LayoutConfig, scrollConfig: ^ScrollElementConfig) -> bool {
 | 
			
		||||
    _OpenScrollElement(id, layoutConfig, scrollConfig)
 | 
			
		||||
    return true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@(require_results, deferred_none = _CloseFloatingElement)
 | 
			
		||||
Floating :: proc(id: c.uint32_t, layoutConfig: ^LayoutConfig, floatingConfig: ^FloatingElementConfig) -> bool {
 | 
			
		||||
    _OpenFloatingElement(id, layoutConfig, floatingConfig)
 | 
			
		||||
    return true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@(require_results, deferred_none = _CloseElementWithChildren)
 | 
			
		||||
Border :: proc(id: c.uint32_t, layoutConfig: ^LayoutConfig, borderConfig: ^BorderElementConfig) -> bool {
 | 
			
		||||
    _OpenBorderElement(id, layoutConfig, borderConfig)
 | 
			
		||||
    return true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@(require_results, deferred_none = _CloseElementWithChildren)
 | 
			
		||||
Custom :: proc(id: c.uint32_t, layoutConfig: ^LayoutConfig, customConfig: ^CustomElementConfig) -> bool {
 | 
			
		||||
    _OpenCustomElement(id, layoutConfig, customConfig)
 | 
			
		||||
    return true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Layout :: proc(config: LayoutConfig) -> ^LayoutConfig {
 | 
			
		||||
    return _LayoutConfigArray_Add(&_layoutConfigs, config)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
RectangleConfig :: proc(config: RectangleElementConfig) -> ^RectangleElementConfig {
 | 
			
		||||
    return _RectangleElementConfigArray_Add(&_rectangleElementConfigs, config)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TextConfig :: proc(config: TextElementConfig) -> ^TextElementConfig {
 | 
			
		||||
    return _TextElementConfigArray_Add(&_textElementConfigs, config)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ImageConfig :: proc(config: ImageElementConfig) -> ^ImageElementConfig {
 | 
			
		||||
    return _ImageElementConfigArray_Add(&_imageElementConfigs, config)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
FloatingConfig :: proc(config: FloatingElementConfig) -> ^FloatingElementConfig {
 | 
			
		||||
    return _FloatingElementConfigArray_Add(&_floatingElementConfigs, config)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Custom_elementConfig :: proc(config: CustomElementConfig) -> ^CustomElementConfig {
 | 
			
		||||
    return _CustomElementConfigArray_Add(&_customElementConfigs, config)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ScrollConfig :: proc(config: ScrollElementConfig) -> ^ScrollElementConfig {
 | 
			
		||||
    return _ScrollElementConfigArray_Add(&_scrollElementConfigs, config)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
BorderConfig :: proc(config: BorderElementConfig) -> ^BorderElementConfig {
 | 
			
		||||
    return _BorderElementConfigArray_Add(&_borderElementConfigs, config)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
BorderConfigOutside :: proc(outsideBorders: BorderData) -> ^BorderElementConfig {
 | 
			
		||||
    return _BorderElementConfigArray_Add(
 | 
			
		||||
        &_borderElementConfigs,
 | 
			
		||||
        (BorderElementConfig){left = outsideBorders, right = outsideBorders, top = outsideBorders, bottom = outsideBorders},
 | 
			
		||||
    )
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
BorderConfigOutsideRadius :: proc(outsideBorders: BorderData, radius: f32) -> ^BorderElementConfig {
 | 
			
		||||
    return _BorderElementConfigArray_Add(
 | 
			
		||||
        &_borderElementConfigs,
 | 
			
		||||
        (BorderElementConfig){left = outsideBorders, right = outsideBorders, top = outsideBorders, bottom = outsideBorders, cornerRadius = {radius, radius, radius, radius}},
 | 
			
		||||
    )
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
BorderConfigAll :: proc(allBorders: BorderData) -> ^BorderElementConfig {
 | 
			
		||||
    return _BorderElementConfigArray_Add(
 | 
			
		||||
        &_borderElementConfigs,
 | 
			
		||||
        (BorderElementConfig){left = allBorders, right = allBorders, top = allBorders, bottom = allBorders, betweenChildren = allBorders},
 | 
			
		||||
    )
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
BorderConfigAllRadius :: proc(allBorders: BorderData, radius: f32) -> ^BorderElementConfig {
 | 
			
		||||
    return _BorderElementConfigArray_Add(
 | 
			
		||||
        &_borderElementConfigs,
 | 
			
		||||
        (BorderElementConfig){left = allBorders, right = allBorders, top = allBorders, bottom = allBorders, cornerRadius = {radius, radius, radius, radius}},
 | 
			
		||||
    )
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
CornerRadiusAll :: proc(radius: f32) -> CornerRadius {
 | 
			
		||||
    return CornerRadius{radius, radius, radius, radius}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
SizingFit :: proc(sizeMinMax: SizingConstraintsMinMax) -> SizingAxis {
 | 
			
		||||
    return SizingAxis{type = SizingType.FIT, constraints = {sizeMinMax = sizeMinMax}}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
SizingGrow :: proc(sizeMinMax: SizingConstraintsMinMax) -> SizingAxis {
 | 
			
		||||
    return SizingAxis{type = SizingType.GROW, constraints = {sizeMinMax = sizeMinMax}}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
SizingFixed :: proc(size: c.float) -> SizingAxis {
 | 
			
		||||
    return SizingAxis{type = SizingType.FIT, constraints = {sizeMinMax = {size, size}}}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
SizingPercent :: proc(sizePercent: c.float) -> SizingAxis {
 | 
			
		||||
    return SizingAxis{type = SizingType.PERCENT, constraints = {sizePercent = sizePercent}}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
MakeString :: proc(label: string) -> String {
 | 
			
		||||
    return String{chars = raw_data(label), length = cast(c.int)len(label)}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ID :: proc(label: string) -> c.uint32_t {
 | 
			
		||||
    return _HashString(MakeString(label), 0)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
IDI :: proc(label: string, index: u32) -> c.uint32_t {
 | 
			
		||||
    return _HashString(MakeString(label), index)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								bindings/odin/clay-odin/macos-arm64/clay.a
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								bindings/odin/clay-odin/macos-arm64/clay.a
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								bindings/odin/clay-odin/macos/clay.a
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								bindings/odin/clay-odin/macos/clay.a
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								bindings/odin/clay-odin/windows/clay.lib
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								bindings/odin/clay-odin/windows/clay.lib
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
						 | 
				
			
			@ -0,0 +1,554 @@
 | 
			
		|||
package main
 | 
			
		||||
 | 
			
		||||
import clay "../../clay-odin"
 | 
			
		||||
import "core:c"
 | 
			
		||||
import "core:fmt"
 | 
			
		||||
import "vendor:raylib"
 | 
			
		||||
 | 
			
		||||
windowWidth: i32 = 1024
 | 
			
		||||
windowHeight: i32 = 768
 | 
			
		||||
 | 
			
		||||
syntaxImage: raylib.Texture2D = {}
 | 
			
		||||
checkImage1: raylib.Texture2D = {}
 | 
			
		||||
checkImage2: raylib.Texture2D = {}
 | 
			
		||||
checkImage3: raylib.Texture2D = {}
 | 
			
		||||
checkImage4: raylib.Texture2D = {}
 | 
			
		||||
checkImage5: raylib.Texture2D = {}
 | 
			
		||||
 | 
			
		||||
FONT_ID_TITLE_56 :: 0
 | 
			
		||||
FONT_ID_TITLE_52 :: 1
 | 
			
		||||
FONT_ID_TITLE_48 :: 2
 | 
			
		||||
FONT_ID_TITLE_36 :: 3
 | 
			
		||||
FONT_ID_TITLE_32 :: 4
 | 
			
		||||
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}
 | 
			
		||||
COLOR_BUTTON_HOVER :: clay.Color{238, 227, 225, 255}
 | 
			
		||||
COLOR_BROWN :: clay.Color{61, 26, 5, 255}
 | 
			
		||||
//COLOR_RED :: clay.Color {252, 67, 27, 255}
 | 
			
		||||
COLOR_RED :: clay.Color{168, 66, 28, 255}
 | 
			
		||||
COLOR_RED_HOVER :: clay.Color{148, 46, 8, 255}
 | 
			
		||||
COLOR_ORANGE :: clay.Color{225, 138, 50, 255}
 | 
			
		||||
COLOR_BLUE :: clay.Color{111, 173, 162, 255}
 | 
			
		||||
COLOR_TEAL :: clay.Color{111, 173, 162, 255}
 | 
			
		||||
COLOR_BLUE_DARK :: clay.Color{2, 32, 82, 255}
 | 
			
		||||
 | 
			
		||||
// Colors for top stripe
 | 
			
		||||
COLOR_TOP_BORDER_1 :: clay.Color{168, 66, 28, 255}
 | 
			
		||||
COLOR_TOP_BORDER_2 :: clay.Color{223, 110, 44, 255}
 | 
			
		||||
COLOR_TOP_BORDER_3 :: clay.Color{225, 138, 50, 255}
 | 
			
		||||
COLOR_TOP_BORDER_4 :: clay.Color{236, 189, 80, 255}
 | 
			
		||||
COLOR_TOP_BORDER_5 :: clay.Color{240, 213, 137, 255}
 | 
			
		||||
 | 
			
		||||
COLOR_BLOB_BORDER_1 :: clay.Color{168, 66, 28, 255}
 | 
			
		||||
COLOR_BLOB_BORDER_2 :: clay.Color{203, 100, 44, 255}
 | 
			
		||||
COLOR_BLOB_BORDER_3 :: clay.Color{225, 138, 50, 255}
 | 
			
		||||
COLOR_BLOB_BORDER_4 :: clay.Color{236, 159, 70, 255}
 | 
			
		||||
COLOR_BLOB_BORDER_5 :: clay.Color{240, 189, 100, 255}
 | 
			
		||||
 | 
			
		||||
headerTextConfig := clay.TextElementConfig {
 | 
			
		||||
    fontId    = FONT_ID_BODY_24,
 | 
			
		||||
    fontSize  = 24,
 | 
			
		||||
    textColor = {61, 26, 5, 255},
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
LandingPageBlob :: proc(index: u32, fontSize: u16, fontId: u16, color: clay.Color, text: clay.String, image: ^raylib.Texture2D) {
 | 
			
		||||
    if clay.Border(
 | 
			
		||||
        clay.IDI("HeroBlob", index),
 | 
			
		||||
        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),
 | 
			
		||||
    ) {
 | 
			
		||||
        if clay.Image(
 | 
			
		||||
            clay.IDI("CheckImage", index),
 | 
			
		||||
            clay.Layout({sizing = {width = clay.SizingFixed(32)}}),
 | 
			
		||||
            clay.ImageConfig({imageData = image, sourceDimensions = {128, 128}}),
 | 
			
		||||
        ) {}
 | 
			
		||||
        clay.Text(clay.IDI("HeroBlobText", index), text, clay.TextConfig({fontSize = fontSize, fontId = fontId, textColor = color}))
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
LandingPageDesktop :: proc() {
 | 
			
		||||
    if clay.Container(
 | 
			
		||||
        clay.ID("LandingPage1Desktop"),
 | 
			
		||||
        clay.Layout({sizing = {width = clay.SizingGrow({}), height = clay.SizingFit({min = cast(f32)windowHeight - 70})}, childAlignment = {y = .CENTER}, padding = {x = 50}}),
 | 
			
		||||
    ) {
 | 
			
		||||
        if clay.Border(
 | 
			
		||||
            clay.ID("LandingPage1"),
 | 
			
		||||
            clay.Layout({sizing = {clay.SizingGrow({}), clay.SizingGrow({})}, childAlignment = {y = .CENTER}, padding = {32, 32}, childGap = 32}),
 | 
			
		||||
            clay.BorderConfig({left = {2, COLOR_RED}, right = {2, COLOR_RED}}),
 | 
			
		||||
        ) {
 | 
			
		||||
            if clay.Container(clay.ID("LeftText"), clay.Layout({sizing = {width = clay.SizingPercent(0.55)}, layoutDirection = .TOP_TO_BOTTOM, childGap = 8})) {
 | 
			
		||||
                clay.Text(
 | 
			
		||||
                    clay.ID("LeftTextTitle"),
 | 
			
		||||
                    clay.MakeString("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}),
 | 
			
		||||
                )
 | 
			
		||||
                if clay.Container(clay.ID("Spacer"), clay.Layout({sizing = {width = clay.SizingGrow({}), height = clay.SizingFixed(32)}})) {}
 | 
			
		||||
                clay.Text(
 | 
			
		||||
                    clay.ID("LeftTextTagline"),
 | 
			
		||||
                    clay.MakeString("Clay is laying out this webpage right now!"),
 | 
			
		||||
                    clay.TextConfig({fontSize = 36, fontId = FONT_ID_TITLE_36, textColor = COLOR_ORANGE}),
 | 
			
		||||
                )
 | 
			
		||||
            }
 | 
			
		||||
            if clay.Container(
 | 
			
		||||
                clay.ID("HeroImageOuter"),
 | 
			
		||||
                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(2, 30, FONT_ID_BODY_30, COLOR_BLOB_BORDER_4, clay.MakeString("Flexbox-style responsive layout"), &checkImage4)
 | 
			
		||||
                LandingPageBlob(3, 30, FONT_ID_BODY_30, COLOR_BLOB_BORDER_3, clay.MakeString("Declarative syntax"), &checkImage3)
 | 
			
		||||
                LandingPageBlob(4, 30, FONT_ID_BODY_30, COLOR_BLOB_BORDER_2, clay.MakeString("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)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
LandingPageMobile :: proc() {
 | 
			
		||||
    if clay.Container(
 | 
			
		||||
        clay.ID("LandingPage1Mobile"),
 | 
			
		||||
        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(
 | 
			
		||||
                clay.ID("LeftTextTitle"),
 | 
			
		||||
                clay.MakeString("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}),
 | 
			
		||||
            )
 | 
			
		||||
            if clay.Container(clay.ID("Spacer"), clay.Layout({sizing = {width = clay.SizingGrow({}), height = clay.SizingFixed(32)}})) {}
 | 
			
		||||
            clay.Text(
 | 
			
		||||
                clay.ID("LeftTextTagline"),
 | 
			
		||||
                clay.MakeString("Clay is laying out this webpage right now!"),
 | 
			
		||||
                clay.TextConfig({fontSize = 32, fontId = FONT_ID_TITLE_32, textColor = COLOR_ORANGE}),
 | 
			
		||||
            )
 | 
			
		||||
        }
 | 
			
		||||
        if clay.Container(
 | 
			
		||||
            clay.ID("HeroImageOuter"),
 | 
			
		||||
            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(2, 24, FONT_ID_BODY_24, COLOR_BLOB_BORDER_4, clay.MakeString("Flexbox-style responsive layout"), &checkImage4)
 | 
			
		||||
            LandingPageBlob(3, 24, FONT_ID_BODY_24, COLOR_BLOB_BORDER_3, clay.MakeString("Declarative syntax"), &checkImage3)
 | 
			
		||||
            LandingPageBlob(4, 24, FONT_ID_BODY_24, COLOR_BLOB_BORDER_2, clay.MakeString("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)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
FeatureBlocks :: proc(widthSizing: clay.SizingAxis, outerPadding: u16) {
 | 
			
		||||
    textConfig := clay.TextConfig({fontSize = 24, fontId = FONT_ID_BODY_24, textColor = COLOR_RED})
 | 
			
		||||
    if clay.Container(
 | 
			
		||||
        clay.ID("HFileBoxOuter"),
 | 
			
		||||
        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)})) {
 | 
			
		||||
            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("HFileSecondLine"), clay.MakeString("~2000 lines of C99."), textConfig)
 | 
			
		||||
        clay.Text(clay.IDI("HFileBoxText", 5), clay.MakeString("Zero dependencies, including no C standard library."), textConfig)
 | 
			
		||||
    }
 | 
			
		||||
    if clay.Container(
 | 
			
		||||
        clay.ID("BringYourOwnRendererOuter"),
 | 
			
		||||
        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.IDI("ZeroDependenciesText", 2), clay.MakeString("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)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
FeatureBlocksDesktop :: proc() {
 | 
			
		||||
    if clay.Container(clay.ID("FeatureBlocksOuter"), clay.Layout({sizing = {width = clay.SizingGrow({})}})) {
 | 
			
		||||
        if clay.Border(
 | 
			
		||||
            clay.ID("FeatureBlocksInner"),
 | 
			
		||||
            clay.Layout({sizing = {width = clay.SizingGrow({})}, childAlignment = {y = .CENTER}}),
 | 
			
		||||
            clay.BorderConfig({betweenChildren = {width = 2, color = COLOR_RED}}),
 | 
			
		||||
        ) {
 | 
			
		||||
            FeatureBlocks(clay.SizingPercent(0.5), 50)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
FeatureBlocksMobile :: proc() {
 | 
			
		||||
    if clay.Border(
 | 
			
		||||
        clay.ID("FeatureBlocksInner"),
 | 
			
		||||
        clay.Layout({layoutDirection = .TOP_TO_BOTTOM, sizing = {width = clay.SizingGrow({})}}),
 | 
			
		||||
        clay.BorderConfig({betweenChildren = {width = 2, color = COLOR_RED}}),
 | 
			
		||||
    ) {
 | 
			
		||||
        FeatureBlocks(clay.SizingGrow({}), 16)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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})) {
 | 
			
		||||
        clay.Text(clay.ID("SyntaxPageTextTitle"), clay.MakeString("Declarative Syntax"), clay.TextConfig(titleTextConfig))
 | 
			
		||||
        if clay.Container(clay.ID("SyntaxSpacer"), clay.Layout({sizing = {width = clay.SizingGrow({max = 16})}})) {}
 | 
			
		||||
        clay.Text(
 | 
			
		||||
            clay.ID("SyntaxPageTextSubTitle1"),
 | 
			
		||||
            clay.MakeString("Flexible and readable declarative syntax with nested UI element hierarchies."),
 | 
			
		||||
            clay.TextConfig({fontSize = 28, fontId = FONT_ID_BODY_28, textColor = COLOR_RED}),
 | 
			
		||||
        )
 | 
			
		||||
        clay.Text(
 | 
			
		||||
            clay.ID("SyntaxPageTextSubTitle2"),
 | 
			
		||||
            clay.MakeString("Mix elements with standard C code like loops, conditionals and functions."),
 | 
			
		||||
            clay.TextConfig({fontSize = 28, fontId = FONT_ID_BODY_28, textColor = COLOR_RED}),
 | 
			
		||||
        )
 | 
			
		||||
        clay.Text(
 | 
			
		||||
            clay.ID("SyntaxPageTextSubTitle3"),
 | 
			
		||||
            clay.MakeString("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}),
 | 
			
		||||
        )
 | 
			
		||||
    }
 | 
			
		||||
    if clay.Container(clay.ID("SyntaxPageRightImage"), clay.Layout({sizing = {width = widthSizing}, childAlignment = {x = .CENTER}})) {
 | 
			
		||||
        if clay.Image(
 | 
			
		||||
            clay.ID("SyntaxPageRightImage"),
 | 
			
		||||
            clay.Layout({sizing = {width = clay.SizingGrow({max = 568})}}),
 | 
			
		||||
            clay.ImageConfig({imageData = &syntaxImage, sourceDimensions = {1136, 1194}}),
 | 
			
		||||
        ) {}
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DeclarativeSyntaxPageDesktop :: proc() {
 | 
			
		||||
    if clay.Container(
 | 
			
		||||
        clay.ID("SyntaxPageDesktop"),
 | 
			
		||||
        clay.Layout({sizing = {clay.SizingGrow({}), clay.SizingFit({min = cast(f32)windowHeight - 50})}, childAlignment = {y = .CENTER}, padding = {x = 50}}),
 | 
			
		||||
    ) {
 | 
			
		||||
        if clay.Border(
 | 
			
		||||
            clay.ID("SyntaxPage"),
 | 
			
		||||
            clay.Layout({sizing = {clay.SizingGrow({}), clay.SizingGrow({})}, childAlignment = {y = .CENTER}, padding = {32, 32}, childGap = 32}),
 | 
			
		||||
            clay.BorderConfig({left = {2, COLOR_RED}, right = {2, COLOR_RED}}),
 | 
			
		||||
        ) {
 | 
			
		||||
            DeclarativeSyntaxPage({fontSize = 48, fontId = FONT_ID_TITLE_48, textColor = COLOR_LIGHT}, clay.SizingGrow({}))
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DeclarativeSyntaxPageMobile :: proc() {
 | 
			
		||||
    if clay.Container(
 | 
			
		||||
        clay.ID("SyntaxPageDesktop"),
 | 
			
		||||
        clay.Layout(
 | 
			
		||||
            {
 | 
			
		||||
                layoutDirection = .TOP_TO_BOTTOM,
 | 
			
		||||
                sizing = {clay.SizingGrow({}), clay.SizingFit({min = cast(f32)windowHeight - 50})},
 | 
			
		||||
                childAlignment = {x = .CENTER, y = .CENTER},
 | 
			
		||||
                padding = {16, 32},
 | 
			
		||||
                childGap = 16,
 | 
			
		||||
            },
 | 
			
		||||
        ),
 | 
			
		||||
    ) {
 | 
			
		||||
        DeclarativeSyntaxPage({fontSize = 52, fontId = FONT_ID_TITLE_52, textColor = COLOR_LIGHT}, clay.SizingGrow({}))
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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.")
 | 
			
		||||
 | 
			
		||||
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})) {
 | 
			
		||||
        clay.Text(clay.ID("PerformanceTextTitle"), clay.MakeString("High Performance"), clay.TextConfig(titleTextConfig))
 | 
			
		||||
        if clay.Container(clay.ID("SyntaxSpacer"), clay.Layout({sizing = {width = clay.SizingGrow({max = 16})}})) {}
 | 
			
		||||
        clay.Text(
 | 
			
		||||
            clay.IDI("PerformanceTextSubTitle", 1),
 | 
			
		||||
            clay.MakeString("Fast enough to recompute your entire UI every frame."),
 | 
			
		||||
            clay.TextConfig({fontSize = 28, fontId = FONT_ID_BODY_36, textColor = COLOR_LIGHT}),
 | 
			
		||||
        )
 | 
			
		||||
        clay.Text(
 | 
			
		||||
            clay.IDI("PerformanceTextSubTitle", 2),
 | 
			
		||||
            clay.MakeString("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.Text(
 | 
			
		||||
            clay.IDI("PerformanceTextSubTitle", 3),
 | 
			
		||||
            clay.MakeString("Simplify animations and reactive UI design by avoiding the standard performance hacks."),
 | 
			
		||||
            clay.TextConfig({fontSize = 28, fontId = FONT_ID_BODY_36, textColor = COLOR_LIGHT}),
 | 
			
		||||
        )
 | 
			
		||||
    }
 | 
			
		||||
    if clay.Container(clay.ID("PerformanceRightImageOuter"), clay.Layout({sizing = {width = widthSizing}, childAlignment = {x = .CENTER}})) {
 | 
			
		||||
        if clay.Border(
 | 
			
		||||
            clay.ID("PerformanceRightBorder"),
 | 
			
		||||
            clay.Layout({sizing = {clay.SizingGrow({}), clay.SizingFixed(400)}}),
 | 
			
		||||
            clay.BorderConfigAll({width = 2, color = COLOR_LIGHT}),
 | 
			
		||||
        ) {
 | 
			
		||||
            if clay.Rectangle(
 | 
			
		||||
                clay.ID("AnimationDemoContainerLeft"),
 | 
			
		||||
                clay.Layout({sizing = {clay.SizingPercent(0.35 + 0.3 * lerpValue), clay.SizingGrow({})}, childAlignment = {y = .CENTER}, padding = {16, 16}}),
 | 
			
		||||
                clay.RectangleConfig({color = ColorLerp(COLOR_RED, COLOR_ORANGE, lerpValue)}),
 | 
			
		||||
            ) {
 | 
			
		||||
                clay.Text(clay.ID("AnimationDemoTextLeft"), LOREM_IPSUM_TEXT, clay.TextConfig({fontSize = 16, fontId = FONT_ID_BODY_16, textColor = COLOR_LIGHT}))
 | 
			
		||||
            }
 | 
			
		||||
            if clay.Rectangle(
 | 
			
		||||
                clay.ID("AnimationDemoContainerRight"),
 | 
			
		||||
                clay.Layout({sizing = {clay.SizingGrow({}), clay.SizingGrow({})}, childAlignment = {y = .CENTER}, padding = {16, 16}}),
 | 
			
		||||
                clay.RectangleConfig({color = ColorLerp(COLOR_ORANGE, COLOR_RED, lerpValue)}),
 | 
			
		||||
            ) {
 | 
			
		||||
                clay.Text(clay.ID("AnimationDemoTextRight"), LOREM_IPSUM_TEXT, clay.TextConfig({fontSize = 16, fontId = FONT_ID_BODY_16, textColor = COLOR_LIGHT}))
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
HighPerformancePageDesktop :: proc(lerpValue: f32) {
 | 
			
		||||
    if clay.Rectangle(
 | 
			
		||||
        clay.ID("PerformanceDesktop"),
 | 
			
		||||
        clay.Layout(
 | 
			
		||||
            {sizing = {clay.SizingGrow({}), clay.SizingFit({min = cast(f32)windowHeight - 50})}, childAlignment = {y = .CENTER}, padding = {x = 82, y = 32}, childGap = 64},
 | 
			
		||||
        ),
 | 
			
		||||
        clay.RectangleConfig({color = COLOR_RED}),
 | 
			
		||||
    ) {
 | 
			
		||||
        HighPerformancePage(lerpValue, {fontSize = 52, fontId = FONT_ID_TITLE_52, textColor = COLOR_LIGHT}, clay.SizingPercent(0.5))
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
HighPerformancePageMobile :: proc(lerpValue: f32) {
 | 
			
		||||
    if clay.Rectangle(
 | 
			
		||||
        clay.ID("PerformanceMobile"),
 | 
			
		||||
        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_RED}),
 | 
			
		||||
    ) {
 | 
			
		||||
        HighPerformancePage(lerpValue, {fontSize = 48, fontId = FONT_ID_TITLE_48, textColor = COLOR_LIGHT}, clay.SizingGrow({}))
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
RendererButtonActive :: proc(id: u32, index: i32, text: clay.String) {
 | 
			
		||||
    if clay.Rectangle(
 | 
			
		||||
        id,
 | 
			
		||||
        clay.Layout({sizing = {width = clay.SizingFixed(300)}, padding = {16, 16}}),
 | 
			
		||||
        clay.RectangleConfig({color = clay.PointerOver(id) ? COLOR_RED_HOVER : COLOR_RED, cornerRadius = clay.CornerRadiusAll(10)}),
 | 
			
		||||
    ) {
 | 
			
		||||
        clay.Text(clay.ID("RendererButtonActiveText"), text, clay.TextConfig({fontSize = 28, fontId = FONT_ID_BODY_28, textColor = COLOR_LIGHT}))
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
RendererButtonInactive :: proc(id: u32, index: u32, text: clay.String) {
 | 
			
		||||
    if clay.Border(id, clay.Layout({}), clay.BorderConfigOutsideRadius({2, COLOR_RED}, 10)) {
 | 
			
		||||
        if clay.Rectangle(
 | 
			
		||||
            clay.IDI("RendererButtonInactiveInner", index),
 | 
			
		||||
            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.Text(clay.IDI("RendererButtonInactiveText", index), text, clay.TextConfig({fontSize = 28, fontId = FONT_ID_BODY_28, textColor = COLOR_RED}))
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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})) {
 | 
			
		||||
        clay.Text(clay.ID("RendererTextTitle"), clay.MakeString("Renderer & Platform Agnostic"), clay.TextConfig(titleTextConfig))
 | 
			
		||||
        if clay.Container(clay.ID("Spacer"), clay.Layout({sizing = {width = clay.SizingGrow({max = 16})}})) {}
 | 
			
		||||
        clay.Text(
 | 
			
		||||
            clay.IDI("RendererTextSubTitle", 1),
 | 
			
		||||
            clay.MakeString("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.Text(
 | 
			
		||||
            clay.IDI("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."),
 | 
			
		||||
            clay.TextConfig({fontSize = 28, fontId = FONT_ID_BODY_36, textColor = COLOR_RED}),
 | 
			
		||||
        )
 | 
			
		||||
        clay.Text(
 | 
			
		||||
            clay.IDI("RendererTextSubTitle", 3),
 | 
			
		||||
            clay.MakeString("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}),
 | 
			
		||||
        )
 | 
			
		||||
    }
 | 
			
		||||
    if clay.Container(
 | 
			
		||||
        clay.ID("RendererRightText"),
 | 
			
		||||
        clay.Layout({sizing = {width = widthSizing}, childAlignment = {x = .CENTER}, layoutDirection = .TOP_TO_BOTTOM, childGap = 16}),
 | 
			
		||||
    ) {
 | 
			
		||||
        clay.Text(
 | 
			
		||||
            clay.ID("RendererTextRightTitle"),
 | 
			
		||||
            clay.MakeString("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.IDI("RendererSelectButtonActive", 0), 0, clay.MakeString("Raylib Renderer"))
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
RendererPageDesktop :: proc() {
 | 
			
		||||
    if clay.Container(
 | 
			
		||||
        clay.ID("RendererPageDesktop"),
 | 
			
		||||
        clay.Layout({sizing = {clay.SizingGrow({}), clay.SizingFit({min = cast(f32)windowHeight - 50})}, childAlignment = {y = .CENTER}, padding = {x = 50}}),
 | 
			
		||||
    ) {
 | 
			
		||||
        if clay.Border(
 | 
			
		||||
            clay.ID("RendererPage"),
 | 
			
		||||
            clay.Layout({sizing = {clay.SizingGrow({}), clay.SizingGrow({})}, childAlignment = {y = .CENTER}, padding = {32, 32}, childGap = 32}),
 | 
			
		||||
            clay.BorderConfig({left = {2, COLOR_RED}, right = {2, COLOR_RED}}),
 | 
			
		||||
        ) {
 | 
			
		||||
            RendererPage({fontSize = 52, fontId = FONT_ID_TITLE_52, textColor = COLOR_RED}, clay.SizingPercent(0.5))
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
RendererPageMobile :: proc() {
 | 
			
		||||
    if clay.Rectangle(
 | 
			
		||||
        clay.ID("RendererMobile"),
 | 
			
		||||
        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({}))
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ScrollbarData :: struct {
 | 
			
		||||
    clickOrigin:    clay.Vector2,
 | 
			
		||||
    positionOrigin: clay.Vector2,
 | 
			
		||||
    mouseDown:      bool,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
scrollbarData: ScrollbarData = ScrollbarData{}
 | 
			
		||||
animationLerpValue: f32 = -1.0
 | 
			
		||||
 | 
			
		||||
createLayout :: proc(lerpValue: f32) -> clay.ClayArray(clay.RenderCommand) {
 | 
			
		||||
    mobileScreen := windowWidth < 750
 | 
			
		||||
    clay.BeginLayout(windowWidth, windowHeight)
 | 
			
		||||
    if clay.Rectangle(
 | 
			
		||||
        clay.ID("OuterContainer"),
 | 
			
		||||
        clay.Layout({layoutDirection = .TOP_TO_BOTTOM, sizing = {clay.SizingGrow({}), clay.SizingGrow({})}}),
 | 
			
		||||
        clay.RectangleConfig({color = COLOR_LIGHT}),
 | 
			
		||||
    ) {
 | 
			
		||||
        if clay.Container(
 | 
			
		||||
            clay.ID("Header"),
 | 
			
		||||
            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)
 | 
			
		||||
            if clay.Container(clay.ID("Spacer"), clay.Layout({sizing = {width = clay.SizingGrow({})}})) {}
 | 
			
		||||
 | 
			
		||||
            if (!mobileScreen) {
 | 
			
		||||
                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}}))
 | 
			
		||||
                }
 | 
			
		||||
                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}}))
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            githubButtonId: u32 = clay.ID("HeaderButtonGithub")
 | 
			
		||||
            if clay.Border(clay.ID("LinkGithubOuter"), clay.Layout({}), clay.BorderConfigOutsideRadius({2, COLOR_RED}, 10)) {
 | 
			
		||||
                if clay.Rectangle(
 | 
			
		||||
                    githubButtonId,
 | 
			
		||||
                    clay.Layout({padding = {16, 6}}),
 | 
			
		||||
                    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}}))
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        if clay.Rectangle(clay.ID("TopBorder1"), clay.Layout({sizing = {clay.SizingGrow({}), clay.SizingFixed(4)}}), clay.RectangleConfig({color = COLOR_TOP_BORDER_5})) {}
 | 
			
		||||
        if clay.Rectangle(clay.ID("TopBorder2"), clay.Layout({sizing = {clay.SizingGrow({}), clay.SizingFixed(4)}}), clay.RectangleConfig({color = COLOR_TOP_BORDER_4})) {}
 | 
			
		||||
        if clay.Rectangle(clay.ID("TopBorder3"), clay.Layout({sizing = {clay.SizingGrow({}), clay.SizingFixed(4)}}), clay.RectangleConfig({color = COLOR_TOP_BORDER_3})) {}
 | 
			
		||||
        if clay.Rectangle(clay.ID("TopBorder4"), clay.Layout({sizing = {clay.SizingGrow({}), clay.SizingFixed(4)}}), clay.RectangleConfig({color = COLOR_TOP_BORDER_2})) {}
 | 
			
		||||
        if clay.Rectangle(clay.ID("TopBorder5"), clay.Layout({sizing = {clay.SizingGrow({}), clay.SizingFixed(4)}}), clay.RectangleConfig({color = COLOR_TOP_BORDER_1})) {}
 | 
			
		||||
        if clay.Rectangle(
 | 
			
		||||
            clay.ID("ScrollContainerBackgroundRectangle"),
 | 
			
		||||
            clay.Layout({sizing = {clay.SizingGrow({}), clay.SizingGrow({})}}),
 | 
			
		||||
            clay.RectangleConfig({color = COLOR_LIGHT}),
 | 
			
		||||
        ) {
 | 
			
		||||
            if clay.Scroll(clay.ID("OuterScrollContainer"), clay.Layout({sizing = {clay.SizingGrow({}), clay.SizingGrow({})}}), clay.ScrollConfig({vertical = true})) {
 | 
			
		||||
                if clay.Border(
 | 
			
		||||
                    clay.ID("ScrollContainerInner"),
 | 
			
		||||
                    clay.Layout({layoutDirection = .TOP_TO_BOTTOM, sizing = {width = clay.SizingGrow({})}}),
 | 
			
		||||
                    clay.BorderConfig({betweenChildren = {2, COLOR_RED}}),
 | 
			
		||||
                ) {
 | 
			
		||||
                    if (!mobileScreen) {
 | 
			
		||||
                        LandingPageDesktop()
 | 
			
		||||
                        FeatureBlocksDesktop()
 | 
			
		||||
                        DeclarativeSyntaxPageDesktop()
 | 
			
		||||
                        HighPerformancePageDesktop(lerpValue)
 | 
			
		||||
                        RendererPageDesktop()
 | 
			
		||||
                    } else {
 | 
			
		||||
                        LandingPageMobile()
 | 
			
		||||
                        FeatureBlocksMobile()
 | 
			
		||||
                        DeclarativeSyntaxPageMobile()
 | 
			
		||||
                        HighPerformancePageMobile(lerpValue)
 | 
			
		||||
                        RendererPageMobile()
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return clay.EndLayout(windowWidth, windowHeight)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
loadFont :: proc(fontId: u16, fontSize: u16, path: cstring) {
 | 
			
		||||
    raylibFonts[fontId] = RaylibFont {
 | 
			
		||||
        font   = raylib.LoadFontEx(path, cast(i32)fontSize * 2, nil, 0),
 | 
			
		||||
        fontId = cast(u16)fontId,
 | 
			
		||||
    }
 | 
			
		||||
    raylib.SetTextureFilter(raylibFonts[fontId].font.texture, raylib.TextureFilter.TRILINEAR)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
main :: proc() {
 | 
			
		||||
    minMemorySize: c.uint32_t = clay.MinMemorySize()
 | 
			
		||||
    memory := make([^]u8, minMemorySize)
 | 
			
		||||
    arena: clay.Arena = clay.CreateArenaWithCapacityAndMemory(minMemorySize, memory)
 | 
			
		||||
    clay.SetMeasureTextFunction(measureText)
 | 
			
		||||
    clay.Initialize(arena)
 | 
			
		||||
 | 
			
		||||
    raylib.SetConfigFlags({.VSYNC_HINT, .WINDOW_RESIZABLE, .WINDOW_HIGHDPI, .MSAA_4X_HINT})
 | 
			
		||||
    raylib.InitWindow(windowWidth, windowHeight, "Raylib Odin Example")
 | 
			
		||||
    raylib.SetTargetFPS(raylib.GetMonitorRefreshRate(0))
 | 
			
		||||
    loadFont(FONT_ID_TITLE_56, 56, "resources/Calistoga-Regular.ttf")
 | 
			
		||||
    loadFont(FONT_ID_TITLE_52, 52, "resources/Calistoga-Regular.ttf")
 | 
			
		||||
    loadFont(FONT_ID_TITLE_48, 48, "resources/Calistoga-Regular.ttf")
 | 
			
		||||
    loadFont(FONT_ID_TITLE_36, 36, "resources/Calistoga-Regular.ttf")
 | 
			
		||||
    loadFont(FONT_ID_TITLE_32, 32, "resources/Calistoga-Regular.ttf")
 | 
			
		||||
    loadFont(FONT_ID_BODY_36, 36, "resources/Quicksand-Semibold.ttf")
 | 
			
		||||
    loadFont(FONT_ID_BODY_30, 30, "resources/Quicksand-Semibold.ttf")
 | 
			
		||||
    loadFont(FONT_ID_BODY_28, 28, "resources/Quicksand-Semibold.ttf")
 | 
			
		||||
    loadFont(FONT_ID_BODY_24, 24, "resources/Quicksand-Semibold.ttf")
 | 
			
		||||
    loadFont(FONT_ID_BODY_16, 16, "resources/Quicksand-Semibold.ttf")
 | 
			
		||||
 | 
			
		||||
    syntaxImage = raylib.LoadTextureFromImage(raylib.LoadImage("resources/declarative.png"))
 | 
			
		||||
    checkImage1 = raylib.LoadTextureFromImage(raylib.LoadImage("resources/check_1.png"))
 | 
			
		||||
    checkImage2 = raylib.LoadTextureFromImage(raylib.LoadImage("resources/check_2.png"))
 | 
			
		||||
    checkImage3 = raylib.LoadTextureFromImage(raylib.LoadImage("resources/check_3.png"))
 | 
			
		||||
    checkImage4 = raylib.LoadTextureFromImage(raylib.LoadImage("resources/check_4.png"))
 | 
			
		||||
    checkImage5 = raylib.LoadTextureFromImage(raylib.LoadImage("resources/check_5.png"))
 | 
			
		||||
 | 
			
		||||
    for !raylib.WindowShouldClose() {
 | 
			
		||||
        animationLerpValue += raylib.GetFrameTime()
 | 
			
		||||
        if animationLerpValue > 1 {
 | 
			
		||||
            animationLerpValue = animationLerpValue - 2
 | 
			
		||||
        }
 | 
			
		||||
        windowWidth = raylib.GetScreenWidth()
 | 
			
		||||
        windowHeight = raylib.GetScreenHeight()
 | 
			
		||||
        clay.SetPointerPosition(transmute(clay.Vector2)raylib.GetMousePosition())
 | 
			
		||||
        clay.UpdateScrollContainers(false, transmute(clay.Vector2)raylib.GetMouseWheelMoveV(), raylib.GetFrameTime())
 | 
			
		||||
        renderCommands: clay.ClayArray(clay.RenderCommand) = createLayout(animationLerpValue < 0 ? (animationLerpValue + 1) : (1 - animationLerpValue))
 | 
			
		||||
        raylib.BeginDrawing()
 | 
			
		||||
        clayRaylibRender(&renderCommands)
 | 
			
		||||
        raylib.EndDrawing()
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,215 @@
 | 
			
		|||
package main
 | 
			
		||||
 | 
			
		||||
import clay "../../clay-odin"
 | 
			
		||||
import "core:math"
 | 
			
		||||
import "vendor:raylib"
 | 
			
		||||
 | 
			
		||||
RaylibFont :: struct {
 | 
			
		||||
    fontId: u16,
 | 
			
		||||
    font:   raylib.Font,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
clayColorToRaylibColor :: proc(color: clay.Color) -> raylib.Color {
 | 
			
		||||
    return raylib.Color{cast(u8)color.r, cast(u8)color.g, cast(u8)color.b, cast(u8)color.a}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
raylibFonts := [10]RaylibFont{}
 | 
			
		||||
 | 
			
		||||
measureText :: proc "c" (text: ^clay.String, config: ^clay.TextElementConfig) -> clay.Dimensions {
 | 
			
		||||
    // Measure string size for Font
 | 
			
		||||
    textSize: clay.Dimensions = {0, 0}
 | 
			
		||||
 | 
			
		||||
    maxTextWidth: f32 = 0
 | 
			
		||||
    lineTextWidth: f32 = 0
 | 
			
		||||
 | 
			
		||||
    textHeight: f32 = cast(f32)config.fontSize
 | 
			
		||||
    fontToUse := raylibFonts[config.fontId].font
 | 
			
		||||
 | 
			
		||||
    for i := 0; i < cast(int)text.length; i += 1 {
 | 
			
		||||
        if (text.chars[i] == '\n') {
 | 
			
		||||
            maxTextWidth = math.max(maxTextWidth, lineTextWidth)
 | 
			
		||||
            lineTextWidth = 0
 | 
			
		||||
            continue
 | 
			
		||||
        }
 | 
			
		||||
        index: i32 = cast(i32)text.chars[i] - 32
 | 
			
		||||
        if (fontToUse.glyphs[index].advanceX != 0) {
 | 
			
		||||
            lineTextWidth += cast(f32)fontToUse.glyphs[index].advanceX
 | 
			
		||||
        } else {
 | 
			
		||||
            lineTextWidth += (fontToUse.recs[index].width + cast(f32)fontToUse.glyphs[index].offsetX)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    maxTextWidth = math.max(maxTextWidth, lineTextWidth)
 | 
			
		||||
 | 
			
		||||
    textSize.width = maxTextWidth / 2
 | 
			
		||||
    textSize.height = textHeight
 | 
			
		||||
 | 
			
		||||
    return textSize
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
clayRaylibRender :: proc(renderCommands: ^clay.ClayArray(clay.RenderCommand)) {
 | 
			
		||||
    for i := 0; i < cast(int)renderCommands.length; i += 1 {
 | 
			
		||||
        renderCommand := clay.RenderCommandArray_Get(renderCommands, cast(i32)i)
 | 
			
		||||
        boundingBox := renderCommand.boundingBox
 | 
			
		||||
        switch (renderCommand.commandType) 
 | 
			
		||||
        {
 | 
			
		||||
        case clay.RenderCommandType.None:
 | 
			
		||||
            {}
 | 
			
		||||
        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
 | 
			
		||||
                text := renderCommand.text
 | 
			
		||||
                cloned := make([]u8, text.length + 1, context.temp_allocator)
 | 
			
		||||
                copy(cloned[0:text.length], text.chars[0:text.length])
 | 
			
		||||
                cloned[text.length] = 0
 | 
			
		||||
                fontToUse: raylib.Font = raylibFonts[renderCommand.config.textElementConfig.fontId].font
 | 
			
		||||
                raylib.DrawTextEx(
 | 
			
		||||
                    fontToUse,
 | 
			
		||||
                    cstring(raw_data(cloned)),
 | 
			
		||||
                    raylib.Vector2{boundingBox.x, boundingBox.y},
 | 
			
		||||
                    cast(f32)renderCommand.config.textElementConfig.fontSize,
 | 
			
		||||
                    cast(f32)renderCommand.config.textElementConfig.letterSpacing,
 | 
			
		||||
                    clayColorToRaylibColor(renderCommand.config.textElementConfig.textColor),
 | 
			
		||||
                )
 | 
			
		||||
            }
 | 
			
		||||
        case clay.RenderCommandType.Image:
 | 
			
		||||
            {
 | 
			
		||||
                // TODO image handling
 | 
			
		||||
                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)
 | 
			
		||||
            }
 | 
			
		||||
        case clay.RenderCommandType.ScissorStart:
 | 
			
		||||
            {
 | 
			
		||||
                raylib.BeginScissorMode(
 | 
			
		||||
                    cast(i32)math.round(boundingBox.x),
 | 
			
		||||
                    cast(i32)math.round(boundingBox.y),
 | 
			
		||||
                    cast(i32)math.round(boundingBox.width),
 | 
			
		||||
                    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) / (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:
 | 
			
		||||
            {
 | 
			
		||||
                config := renderCommand.config.borderElementConfig
 | 
			
		||||
                // Left border
 | 
			
		||||
                if (config.left.width > 0) {
 | 
			
		||||
                    raylib.DrawRectangle(
 | 
			
		||||
                        cast(i32)math.round(boundingBox.x),
 | 
			
		||||
                        cast(i32)math.round(boundingBox.y + config.cornerRadius.topLeft),
 | 
			
		||||
                        cast(i32)config.left.width,
 | 
			
		||||
                        cast(i32)math.round(boundingBox.height - config.cornerRadius.topLeft - config.cornerRadius.bottomLeft),
 | 
			
		||||
                        clayColorToRaylibColor(config.left.color),
 | 
			
		||||
                    )
 | 
			
		||||
                }
 | 
			
		||||
                // Right border
 | 
			
		||||
                if (config.right.width > 0) {
 | 
			
		||||
                    raylib.DrawRectangle(
 | 
			
		||||
                        cast(i32)math.round(boundingBox.x + boundingBox.width - cast(f32)config.right.width),
 | 
			
		||||
                        cast(i32)math.round(boundingBox.y + config.cornerRadius.topRight),
 | 
			
		||||
                        cast(i32)config.right.width,
 | 
			
		||||
                        cast(i32)math.round(boundingBox.height - config.cornerRadius.topRight - config.cornerRadius.bottomRight),
 | 
			
		||||
                        clayColorToRaylibColor(config.right.color),
 | 
			
		||||
                    )
 | 
			
		||||
                }
 | 
			
		||||
                // Top border
 | 
			
		||||
                if (config.top.width > 0) {
 | 
			
		||||
                    raylib.DrawRectangle(
 | 
			
		||||
                        cast(i32)math.round(boundingBox.x + config.cornerRadius.topLeft),
 | 
			
		||||
                        cast(i32)math.round(boundingBox.y),
 | 
			
		||||
                        cast(i32)math.round(boundingBox.width - config.cornerRadius.topLeft - config.cornerRadius.topRight),
 | 
			
		||||
                        cast(i32)config.top.width,
 | 
			
		||||
                        clayColorToRaylibColor(config.top.color),
 | 
			
		||||
                    )
 | 
			
		||||
                }
 | 
			
		||||
                // Bottom border
 | 
			
		||||
                if (config.bottom.width > 0) {
 | 
			
		||||
                    raylib.DrawRectangle(
 | 
			
		||||
                        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.width - config.cornerRadius.bottomLeft - config.cornerRadius.bottomRight),
 | 
			
		||||
                        cast(i32)config.bottom.width,
 | 
			
		||||
                        clayColorToRaylibColor(config.bottom.color),
 | 
			
		||||
                    )
 | 
			
		||||
                }
 | 
			
		||||
                if (config.cornerRadius.topLeft > 0) {
 | 
			
		||||
                    raylib.DrawRing(
 | 
			
		||||
                        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),
 | 
			
		||||
                        config.cornerRadius.topLeft,
 | 
			
		||||
                        180,
 | 
			
		||||
                        270,
 | 
			
		||||
                        10,
 | 
			
		||||
                        clayColorToRaylibColor(config.top.color),
 | 
			
		||||
                    )
 | 
			
		||||
                }
 | 
			
		||||
                if (config.cornerRadius.topRight > 0) {
 | 
			
		||||
                    raylib.DrawRing(
 | 
			
		||||
                        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),
 | 
			
		||||
                        config.cornerRadius.topRight,
 | 
			
		||||
                        270,
 | 
			
		||||
                        360,
 | 
			
		||||
                        10,
 | 
			
		||||
                        clayColorToRaylibColor(config.top.color),
 | 
			
		||||
                    )
 | 
			
		||||
                }
 | 
			
		||||
                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),
 | 
			
		||||
                        },
 | 
			
		||||
                        math.round(config.cornerRadius.bottomLeft - cast(f32)config.top.width),
 | 
			
		||||
                        config.cornerRadius.bottomLeft,
 | 
			
		||||
                        90,
 | 
			
		||||
                        180,
 | 
			
		||||
                        10,
 | 
			
		||||
                        clayColorToRaylibColor(config.bottom.color),
 | 
			
		||||
                    )
 | 
			
		||||
                }
 | 
			
		||||
                if (config.cornerRadius.bottomRight > 0) {
 | 
			
		||||
                    raylib.DrawRing(
 | 
			
		||||
                        raylib.Vector2 {
 | 
			
		||||
                            math.round(boundingBox.x + boundingBox.width - config.cornerRadius.bottomRight),
 | 
			
		||||
                            math.round(boundingBox.y + boundingBox.height - config.cornerRadius.bottomRight),
 | 
			
		||||
                        },
 | 
			
		||||
                        math.round(config.cornerRadius.bottomRight - cast(f32)config.bottom.width),
 | 
			
		||||
                        config.cornerRadius.bottomRight,
 | 
			
		||||
                        0.1,
 | 
			
		||||
                        90,
 | 
			
		||||
                        10,
 | 
			
		||||
                        clayColorToRaylibColor(config.bottom.color),
 | 
			
		||||
                    )
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        case clay.RenderCommandType.Custom:
 | 
			
		||||
            {
 | 
			
		||||
                // Implement custom element rendering here
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 1.5 KiB  | 
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 1.5 KiB  | 
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 1.5 KiB  | 
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 1.5 KiB  | 
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 1.5 KiB  | 
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 193 KiB  | 
							
								
								
									
										6
									
								
								bindings/odin/odinfmt.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								bindings/odin/odinfmt.json
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,6 @@
 | 
			
		|||
{
 | 
			
		||||
	"$schema": "https://raw.githubusercontent.com/DanielGavin/ols/master/misc/odinfmt.schema.json",
 | 
			
		||||
	"character_width": 180,
 | 
			
		||||
	"sort_imports": true,
 | 
			
		||||
	"tabs": false
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										6
									
								
								bindings/odin/ols.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								bindings/odin/ols.json
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,6 @@
 | 
			
		|||
{
 | 
			
		||||
    "$schema": "https://raw.githubusercontent.com/DanielGavin/ols/master/misc/ols.schema.json",
 | 
			
		||||
    "enable_document_symbols": true,
 | 
			
		||||
    "enable_hover": true,
 | 
			
		||||
    "enable_snippets": true
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
		Reference in a new issue