Skip to content

Releases: nicbarker/clay

0.14 - Aspect Ratio Elements, Better Clipping

06 Jun 01:16

Choose a tag to compare

New Features

Non-image aspect ratio scaling elements, image stretching

Previously, only image elements supported aspect ratio scaling. The new .aspectRatio element configuration option allows you to specify a fixed width / height aspect ratio for any element. This also allows you to create image elements with no specified aspect ratio, allowing for stretched / distorted images with a different aspect ratio to their source dimensions. Different images rendering modes similar to the CSS concepts of contain and cover, as well as 9-slice support are scheduled for 0.15.

// Old
CLAY({
  .image = { .imageData = &myImage, .sourceDimensions = { 1024, 768 } }
});

// New
CLAY({
  .aspectRatio = 1024.0 / 768.0,
  .image = { .imageData = &myImage }
});

Improved .clip configuration option replaces .scroll

As part of our longer term effort to separate interaction handling from the core layout library, the .scroll configuration option has been replace with .clip. This new configuration options allows:

  • Cllipping of elements without enabling scrolling, similar to CSS's overflow:hidden
  • Immediate mode scroll handling, by providing scroll offset directly to .clip.childOffset.

To use Clay's internal scroll handling (i.e. emulate the old .scroll behaviour, you can use the new function, Clay_GetScrollOffset function.

// Old
CLAY({
  .scroll = { .vertical = true } // scrolling was automatically handled internally
});

// New, using clay's built in scroll handling
CLAY({
  .clip = {
    .vertical = true,
    .childOffset = Clay_GetScrollOffset() // This function is context dependent and will automatically track scrolling for this element across frames
  }
});

// New, providing your own scroll handling
Clay_Vector2 scrollOffset = { 0, 120 };

CLAY({
  .clip = {
    .vertical = true,
    .childOffset = scrollOffset // This will offset all children by the provided Vector2 this frame, so scrolling can be handled externally
  }
});

// New, clipping overflow without enabling scrolling
CLAY({
  .clip = { .vertical = true }
});

New Renderers

We now have a simple ANSI terminal renderer (thanks to @EmmanuelMess), a Playdate renderer (thanks to @mattahj), a Windows GDI renderer (thanks to @hexmaster111), and a Sokol renderer (thanks to @nkorth). All of them look great!

image
Terminal Renderer

download.mov

Playdate Renderer

image
Windows GDI renderer

Small Changes

  • Hashing of text contents for the text measurement cache is now the default behaviour, and has a reasonably performant SIMD implementation both for x64 and ARM. Using a frame arena or scratch storage for text element strings should now work much more reliably.
  • Layout calculations for some GROW edge cases, as well as aspect ratio scaling, have been improved.
  • A new function, Clay_GetPointerOverIds is now available, which will return a z-sorted list of IDs of elements that the cursor is currently over.

Migration Guide

  1. Convert any .scroll configuration usage into .clip, and add .childOffset = Clay_GetScrollOffset() to emulate existing behaviour
CLAY({
-  .scroll = {
+  .clip = {
    .vertical = true,
+  .childOffset = Clay_GetScrollOffset()
  }
})
  1. Split any .image configuration into .image and .aspectRatio
CLAY({
  .image = {
    .imageData = &myImage,
-   .sourceDimensions = { 1024, 768 }
  },
+ .aspectRatio = { 1024.0 / 768.0 }
})
  1. Remove any references to .hashStringContents in CLAY_TEXT_CONFIG, this is now the default behaviour and no longer needed.
CLAY_TEXT(CLAY_STRING("hello"), CLAY_TEXT_CONFIG({
-  .hashStringContents = true
}));

Changelist

  • [Renderers/SDL3] Use text engine to render text on the SDL3 renderer by @ernestoyaquello in #256
  • [Renderers/SDL3] Add image rendering and scissor support to SDL3 renderer by @steviegt6 in #246
  • [Renderers/SDL2] add rounded corner borders and fixed maximum radius issues. by @TimothyHoytBSME in #258
  • [Renderers/SDL3] Enable sdl3 alpha blending by @irfan-zahir in #261
  • [Renderers/SDL2] Make SDL_RenderCornerBorder static by @TimothyHoytBSME in #263
  • [Renderers/Raylib] Convert Image usage to Texture by @CrackedPixel in #266
  • [Examples/SDL2] opengl, antialiasing, vsync, alpha blending by @TimothyHoytBSME in #264
  • [Bindings/Odin] add missing bindings, fix binding, improve ergonomics of userdata, conform to stricter style flags by @laytan in #270
  • Make Clay_MinMemorySize accurate based on word cache count by @alecks in #269
  • Fix inverted condition for setting booleanWarnings.maxTextMeasureCacheExceeded by @mizmar in #275
  • [Documentation] Update README.md for Odin bindings to reflect the latest API changes. by @benjamindblock in #281
  • [Compilers] Added DLL macro to support .dll building by @Orcolom in #278
  • [Macros] Add versions of the CLAY_ID macros that take Clay_String by @FintasticMan in #285
  • [Core] Improve & streamline grow / shrink handling by @nicbarker in #296
  • [Bindings/Odin] fix CreateArenaWithCapacityAndMemory capacity type by @laytan in #306
  • [Renderers/Raylib] Use RayLib Default font if user font failed to load or was not specified. by @hexmaster111 in #305
  • [Documentation] fix example in README by @RicoP in #307
  • [Documentation] Fix typo in "vertiically" by @bowbahdoe in #315
  • [Core] Add a userData pointer to Clay_TextElementConfig by @mikejsavage in #274
  • [Compilers] Fixed SIMD related compile error on some ARM compilers by @emoon in #316
  • [Core] Support passing declaration by pointer as well by @emoon in #319
  • [Documentation] Update README.md: it's gotten bigger by @joshuahhh in #300
  • [Renderers/SDL2] Enable live resizing of layout during window resize in SDL2 by @shakkar23 in #320
  • [Renderers\win32_gdi] Create initial WinGDI renderer by @hexmaster111 in #322
  • [Compilers] Fix integer truncation warnings with explicit casts by @Nelarius in #317
  • [Renderers/Raylib] Reuse memory in raylib renderer for temporary string allocations by @hexmaster111 in #298
  • [Renderers/SDL2] Fix rounded corner border index by @mizmar in #295
  • [Renderers/SDL2] Added explicit include of math.h in SDL2 renderer by @Emerald-Ruby in #327
  • [Bindings/Odin] expose _OpenElement and _CloseElement by @lzurbriggen in #301
  • [Core] Switch text content hashing to default behaviour by @nicbarker in #335
  • [Core] Guard against hashmap item null dereference by @igadmg in #338
  • [Bindings/Odin] Remove field hashStringContents in odin bindings by @ellie-but-backwards in #350
  • [Core] Fix CLAY__ELEMENT_DEFINITION_LATCH overflow in CLAY macro if 256 loops end at the same time by @PiggybankStudios in #349
  • [Cmake] Basic CMake support for easier import into CMake projects by @Qualadia in #345
  • [Renderers/WinGDI] Working on Win32 GDI renderer and example by @Philosoph228 in #344
  • [Renderers/Sokol] Sokol renderer & examples by @nkorth in #373
  • [Renderers/Raylib] Add explicit type cast for malloc by @boringlily in #379
  • [Renderers/Raylib] fix bottom left corner radius of border by @timlueg in #378
  • [Documentation] Fix Clay_String definition in README.md file. by @Oglo12 in #374
  • [Core] Fix a string hash bug with single characters by @nicbarker in #384
  • [Core] Replace .scroll config with .clip by @nicbarker in #376
  • [Bindings/Odin] Odin Raylib renderer rewrite by @rats159 in #395
  • [Bindings/Odin] Updated odin bindings with new clip config by @A1029384756 in #397
  • [Renderers/SDL3] Use SDL_Texture instead of SDL_Surface for images by @linkdd in #402
  • [Debug] Update Clay__RenderDebugLayoutSizing to handle more sizing types. by @tritao in #392
  • Fix README: use correct anchor to Clay_CustomElementConfig by @dgellow in htt...
Read more

0.13 - Simplified Config, Multi Instance Support

12 Feb 00:26

Choose a tag to compare

New Features

Replace Element Macros with a Single Configuration Struct

We've removed the majority of the configuration macros in favour of a large config struct that you pass to CLAY.
You can find exhaustive documentation of this struct and its fields in the README.

// Before - macros
CLAY(
    CLAY_ID("FloatingContainer"),
    CLAY_LAYOUT({
        .sizing = {
            .width = CLAY_SIZING_FIXED(300),
            .height = CLAY_SIZING_FIXED(300)
        },
        .padding = { 16, 16, 16, 16 }
    }),
    CLAY_FLOATING({
        .zIndex = 1,
        .attachment = {
            CLAY_ATTACH_POINT_CENTER_TOP,
            CLAY_ATTACH_POINT_CENTER_TOP
        },
        .offset = { 0, 0 }
    }),
    CLAY_BORDER_OUTSIDE({ .color = {80, 80, 80, 255}, .width = 2 }),
    CLAY_RECTANGLE({ .color = {140,80, 200, 200 }}
) {
    // children
}
// After - single struct
CLAY({
    .id = CLAY_ID("FloatingContainer"),
    .layout = {
        .sizing = {
            .width = CLAY_SIZING_FIXED(300),
            .height = CLAY_SIZING_FIXED(300)
        },
        .padding = { 16, 16, 16, 16 }
    },
    .backgroundColor = { 140, 80, 200, 200 },
    .floating = {
        .attachTo = CLAY_ATTACH_TO_PARENT,
        .zIndex = 1,
        .attachPoints = {
            CLAY_ATTACH_POINT_CENTER_TOP,
            CLAY_ATTACH_POINT_CENTER_TOP
        },
        .offset = { 0, 0 }
    },
    .border = {
        .width = { 2, 2, 2, 2 },
        .color = { 80, 80, 80, 255 }
    },
}) {
    // children
}

The two main benefits we get from this approach are:

  1. The available configuration options are naturally discoverable for those using intellisense just by pressing . inside CLAY({ }), whereas previously you had to look up the macros in the documentation.
  2. You can define the configuration for an entire element and save it as a struct:
Clay_ElementDeclaration buttonStyle = (Clay_ElementDeclaration) {
    .layout = { .padding = { .left = 16, .right = 16 } },
    .backgroundColor = COLOR_RED,
    .cornerRadius = { 16, 16, 16, 16 }
}

// later
CLAY(buttonStyle) {
    // button contents
}

// Or return a declaration from a function
Clay_ElementDeclaration GetButtonStyle(bool hovered) {
    return (Clay_ElementDeclaration) {
        .layout = { ... },
        .backgroundColor = hovered ? BLUE : RED
    };
}

// Generate element style from template
CLAY(GetButtonStyle(Clay_Hovered())) {
    // button contents
}

"Context" support (i.e. Multiple independent Clay instances & groundwork for multithreading support)

Thanks to some great discussions in the Clay discord and great work by @monodop here: #174 Clay now supports creation and management of multiple "instances" which are separate from one another. This is not only useful for systems with separate internal "windows" requiring different layout trees, but also paves the way for us to support running these instances on separate threads.

Screenshot 2025-02-12 at 9 35 56β€―am
An example of the same layout rendered twice by two separate Clay instances

For more information, see the Multi Context Example

Error Handler

Clay now requires that you bind an error handler callback function when calling Clay_Initialize. This allows us to catch and report some common mistakes such as forgetting to bind a text measurement function with Clay_SetMeasureText.

image

Clay_GetElementData for querying bounding box data

A new function, Clay_GetElementData(Clay_ElementId id) is available for directly looking up the final calculated bounding box of an element by ID.

.textAlignment support for CLAY_TEXT_CONFIG

Wrapped text can now be aligned to LEFT, CENTER or RIGHT using the .textAlignment field of CLAY_TEXT_CONFIG.

Screenshot 2025-02-12 at 10 49 19β€―am

MSVC Support & C99 Compliance

Thanks to some tireless work from @FintasticMan, Clay can now be compiled using MSVC with C11, 17, and 23, has much closer strict C99 compliance, and compiles with -Wextra and -Wpedantic.

New Renderers

Thanks to some hard work from our contributors, there are a number of new example renderers in 0.13, including:

  • SDL2
  • SDL3
  • Cairo

New Language Bindings

Thanks to some hard work from our contributors, there are a number of new language bindings in 0.13, including:

Zig
https://codeberg.org/Zettexe/clay-zig
https://github.com/johan0A/clay-zig-bindings

Rust
https://github.com/clay-ui-rs/clay
https://crates.io/crates/clay-layout

C#
https://github.com/Orcolom/clay-cs

C++
https://github.com/TimothyHoytBSME/ClayMan

Deprecations

The preprocessor defines used for adding additional fields to element configuration structs such as CLAY_EXTEND_CONFIG_RECTANGLE have been removed in favour of the new .userData pointer field of Clay_ElementDeclaration. This was out of necessity and can be explained in more detail upon request πŸ˜…

Migration Guide

  1. Wrap the inside of the CLAY(...) macro in braces for the new form CLAY({ ... })
- CLAY(
+ CLAY({
    CLAY_ID(...),
    CLAY_RECTANGLE({ ... }),
    CLAY_BORDER({ ... }),
    CLAY_FLOATING({ ... })
- )
+ })
  1. Mass rename the following macros:
  • CLAY_BORDER({ ... })
  • CLAY_IMAGE({ ... })
  • CLAY_SCROLL({ ... })
  • CLAY_FLOATING({ ... })
  • CLAY_CUSTOM({ ... })

into struct fields of the form .border = { ... }, .floating = { ... } etc

CLAY({
    CLAY_ID(...),
    CLAY_RECTANGLE({ ... }),
-   CLAY_BORDER({ ... }),
+   .border = { ... },
-   CLAY_FLOATING({ ... })
+   .floating = { ... },
})
  1. Replace the CLAY_ID macro with the struct field .id = CLAY_ID
CLAY({
-   CLAY_ID(...),
+   .id = CLAY_ID(...),
    CLAY_RECTANGLE({ ... }),
    .border = { ... },
    .floating = { ... }
})
  1. Replace CLAY_RECTANGLE macros with two struct fields, .backgroundColor and .cornerRadius

Previous, fields like .cornerRadius would need to be repeated for rectangle, image, and border configuration macros. .backgroundColor and .cornerRadius are now shared fields that affect multiple render commands, and are declared once at the top level.

CLAY({
    .id = CLAY_ID(...),
-   CLAY_RECTANGLE({ .color = COLOR_RED, .cornerRadius = { 10, 10, 10, 10 } }),
+   .backgroundColor = COLOR_RED,
+   .cornerRadius = { 10, 10, 10, 10 },
    .border = { ... },
    .floating = { ... }
})
  1. Padding is now represented by four values, not just two

Padding in 0.12 was represented as a mirrored .x, .y pair. It's been changed in 0.13 to a more standard .left, .right, .top, .bottom.
You'll need to update your padding to match the new structure.

- CLAY({ .layout = { .padding = { 8, 12 } });
+ CLAY({ .layout = { .padding = { 8, 8, 12, 12 } });

// Designated initializers
- CLAY({ .layout = { .padding = { .x = 8, .y = 12 } });
+ CLAY({ .layout = { .padding = { .left = 8, .right = 8, .top = 12, .bottom = 12 } });
  1. Depending on your language and compiler, CLAY_SIZING_GROW might need to be passed 0 when you don't specify min and max size:
- CLAY({ .layout = { .width = CLAY_SIZING_GROW() } });
+ CLAY({ .layout = { .width = CLAY_SIZING_GROW(0) } });
  1. Update border declarations

Borders now share a single color, and use the shared .cornerRadius from the outer declaration.

- CLAY_BORDER({ .left = { 20, COLOR_BLUE }, .right = { 20, COLOR_BLUE }, .bottom = { 20, COLOR_BLUE }, .cornerRadius = { 10, 10, 10, 10 } })
+ .cornerRadius = { 10, 10, 10, 10 },
+ .border = { .width = { .left = 20, .right = 20, .bottom = 20 }, .color = COLOR_BLUE }
  1. Changes to Floating Elements

Replacing CLAY_FLOATING, The .floating config of the declaration struct now has a new field, .attachTo, which can be one of several values:

CLAY_ATTACH_TO_NONE (default)
CLAY_ATTACH_TO_PARENT
CLAY_ATTACH_TO_ELEMENT_ID
CLAY_ATTACH_TO_ROOT

Unlike previously where just calling CLAY_FLOATING was enough to switch an element to floating mode, now .attachTo has to be set to some value other than the default NONE. CLAY_ATTACH_TO_PARENT is the old default behaviour, CLAY_ATTACH_TO_ELEMENT_ID requires that you set a parentId to attach the floating element to, and the new CLAY_ATTACH_TO_ROOT option allows you to position the element relative to the root of the layout (i.e. the entire screen), by using the .offset field.

// Attach to parent
- CLAY_FLOATING({ .offset = { 12, 12 } });
+ .floating = { .attachTo = CLAY_ATTACH_TO_PARENT,  .offset = { 12, 12 } };

// Attach to specific ID
- CLAY_FLOATING({ .parentId = CLAY_ID("targetElement") });
+ .floating = { .attachTo = CLAY_ATTACH_TO_ELEMENT_ID,  .parentId = CLAY_ID("targetElement") };
  1. Clay_SetMeasureTextFunction must now be called after Clay_Initialize

  2. Clay_Initialize now requires an error handler callback.

void HandleClayErrors(Clay_ErrorData errorData) {
    // See the Clay_ErrorData struct for more information
    printf("%s", errorData.errorText.chars);
    switch(errorData.errorType) {
        // etc
    }
}

- Clay_Initialize(arena, (Clay_Dimensions) { screenWidth, screenHeight });
+ Clay_Initialize(arena, (Clay_Dimensions) { screenWidth, screenHeight }, (Clay_ErrorHandler) { HandleCl...
Read more

0.12 - Multi type elements, performance improvements

22 Oct 23:44

Choose a tag to compare

Clay v0.12 - Multi type elements, performance improvements

Changelog

New Feature: Multi-Type Elements

carbon(91)(1)

Clay's element API has been refactored to allow for significantly better flexibility and modularity. Instead of elements having a single specific type, all elements use the generic CLAY() macro for definition, and then can be configured using any combination of types. The above screenshot demonstrates the significant reduction in boilerplate when defining a multi-type element such as "A scrolling container with a border and background".

New Feature: Clay_Hovered() and Clay_OnHover() functions

Two new functions have been added that can be called during element configuration and layout construction, provided a convenient mechanism for handing hover and click interactions.

See the documentation for Clay_Hovered and Clay_OnHover for details.

void HandleHeaderButtonInteraction(Clay_ElementId elementId, Clay_PointerData pointerData, intptr_t userData) {
    if (pointerData.state == CLAY_POINTER_DATA_PRESSED_THIS_FRAME) {
        // Do some click handling
    }
}

void HeaderButton(Clay_String text) {
    CLAY(CLAY_LAYOUT({ .padding = { 16, 8 } }),
        // When this element is hovered, change the background color from orange to blue
        CLAY_RECTANGLE({ .color = Clay_Hovered() ? COLOR_BLUE : COLOR_ORANGE }),
        // When this element is hovered, call the function HandleHeaderButtonInteraction with the userData = `1`.
        Clay_OnHover(HandleHeaderButtonInteraction, 1)
    ) {
        CLAY_TEXT(text, CLAY_TEXT_CONFIG(headerTextConfig));
    }
}

Improvements: Significantly faster text handling

The internal algorithm for wrapping text and caching text measurements has been rewritten from scratch, resulting in a ballpark 2-4x performance improvement of layout calculation. As a result, reasonably complex layouts now sit in the <100 microseconds range.

Screenshot 2024-10-23 at 11 18 58 AM(1)

New Contributors

Full Changelog: v0.11...v0.12

Migration Guide (C/C++)

This release contains significant breaking changes that are detailed below. For a smooth migration process, please follow the below steps in order.

Step 1. Rename Element Macros -> CLAY()

The following element macros:

  • CLAY_CONTAINER()
  • CLAY_RECTANGLE()
  • CLAY_IMAGE()
  • CLAY_BORDER_CONTAINER()
  • CLAY_SCROLL_CONTAINER()
  • CLAY_FLOATING_CONTAINER()
  • CLAY_CUSTOM_ELEMENT()

Can all be mass renamed to just CLAY(). For example:

- CLAY_RECTANGLE(...) {
+ CLAY(...) {
-     CLAY_CONTAINER(...) {
+     CLAY(...) {
         // ... etc
    }
}

Step 2. Rename CLAY_X_CONFIG() -> CLAY_X()

The following element configuration macros:

  • CLAY_RECTANGLE_CONFIG()
  • CLAY_IMAGE_CONFIG()
  • CLAY_BORDER_CONFIG()
  • CLAY_SCROLL_CONFIG()
  • CLAY_FLOATING_CONFIG()
  • CLAY_CUSTOM_CONFIG()

Can all be mass renamed to remove the _CONFIG. For example:

- CLAY(id, layout, CLAY_RECTANGLE_CONFIG(...)) {
+ CLAY(id, layout, CLAY_RECTANGLE(...)) {
-     CLAY(id, layout, CLAY_BORDER_CONFIG_OUTSIDE(...)) {
+     CLAY(id, layout, CLAY_BORDER_OUTSIDE(...)) {
         // ... etc
    }
}

Step 3. Wrap macro contents in { }

All macros that previously accepted designated initializer syntax in the form of:

CLAY_RECTANGLE(.color = RED)

Now require that their contents are wrapped in braces {}.

CLAY_RECTANGLE({ .color = RED })

This is primarily for C++ syntax compatibility.

- CLAY(id, layout, CLAY_RECTANGLE(.color = RED)) {
+ CLAY(id, layout, CLAY_RECTANGLE({ .color = RED })) {
-     CLAY(id, CLAY_LAYOUT(.layoutDirection = CLAY_TOP_TO_BOTTOM), CLAY_BORDER_OUTSIDE(.width = 2, .color = RED)) {
+     CLAY(id, CLAY_LAYOUT({ .layoutDirection = CLAY_TOP_TO_BOTTOM }), CLAY_BORDER_OUTSIDE({ .width = 2, .color = RED })) {
         // ... etc
    }
}

Step 4. Swap any non layout calls to CLAY_ID for Clay_GetElementId

CLAY_ID is now used exclusively for attaching IDs to elements during layout creation, and does not return a value. If you are using CLAY_ID to retrieve element information at other times (for example, mouse or scroll container handling) it can be swapped for the new public function Clay_GetElementId.

- Clay_ScrollContainerData scrollData = Clay_GetScrollContainerData(CLAY_ID("MainContent"));
+ Clay_ScrollContainerData scrollData = Clay_GetScrollContainerData(Clay_GetElementId(CLAY_STRING("MainContent")));

Step 5. Remove all IDs from CLAY_TEXT()

CLAY_TEXT() elements no longer accept an ID as the first argument, and instead rely on an auto generated internal ID. The primary reasoning behind this is that various capabilities provided by IDs - such as attaching floating containers to an element - don't make sense when combined with text that can arbitrarily wrap, especially as the result can end up being non rectangular.

If you need to attach a tooltip or similar to CLAY_TEXT, simply wrap the text in a container.

- CLAY_TEXT(CLAY_ID("HFileSecondLine"), CLAY_STRING("~2000 lines of C99."), textConfig);
+ CLAY_TEXT(CLAY_STRING("~2000 lines of C99."), textConfig);

Step 6 (Optional) Remove all empty calls to CLAY_LAYOUT() or references to CLAY_LAYOUT_DEFAULT

Both IDs and calls to CLAY_LAYOUT() are now optional when declaring layouts. As a result, any empty calls to CLAY_LAYOUT or references to &CLAY_LAYOUT_DEFAULT simply to satisfy the compiler can be removed.

- CLAY(CLAY_ID("Button"), CLAY_LAYOUT(), CLAY_RECTANGLE({ .color = RED })) {}
+ CLAY(CLAY_ID("Button"), CLAY_RECTANGLE({ .color = RED })) {}

Migration Guide (Odin)

Step 1. Rename Element Functions -> clay.UI()

The following element functions:

  • clay.Container()
  • clay.Rectangle()
  • clay.Image()
  • clay.Border()
  • clay.Scroll()
  • clay.Floating()
  • clay.Custom()

Should all be renamed to just Clay.UI().

- if (clay.Container(
+ if (clay.UI(
        clay.ID("Button"),
        clay.Layout({ childAlignment = {y = .CENTER}, padding = {x = 50} }),
    ) { // etc
)

Step 2. Rename clay.xConfig() -> clay.x()

The following element config functions:

  • clay.RectangleConfig()
  • clay.ImageConfig()
  • clay.BorderConfig()
  • clay.ScrollConfig()
  • clay.FloatingConfig()
  • clay.CustomConfig()

Should all be renamed to just Clay.__name__().

if (clay.UI(
        clay.ID("Button"),
-      clay.RectangleConfig({ color = COLOR_RED }),
+      clay.Rectangle({ color = COLOR_RED }),
    ) { // etc
)

Step 3. Remove the first ID argument from clay.Text

clay.Text no longer supports IDs, and instead uses an auto generated internal ID.

- clay.Text(clay.ID("HeroBlobText", index), text, clay.TextConfig({fontSize = fontSize, fontId = fontId, textColor = color}))
+ clay.Text(text, clay.TextConfig({fontSize = fontSize, fontId = fontId, textColor = color}))

v0.11

17 Sep 23:55

Choose a tag to compare

Clay 0.11

Changelog

  • New Feature: Visual Debug Tools. Similar to the inspector in Chrome or Firefox. Browse your layout hierarchy, inspect bounding boxes and config, and view any warnings output during layout. To activate the debug tools, call the new function Clay_SetDebugModeEnabled. See the README for more details.
Screenshot 2024-09-12 at 12 54 03 PM
  • New Feature: Text Wrap Modes. A new feature of TEXT_CONFIG, this allows you to choose between three modes:
  • CLAY_TEXT_WRAP_WORDS - Text will wrap on whitespace characters as container width shrinks.
  • CLAY_TEXT_WRAP_NEWLINES - Text will only wrap when encountering newline characters
  • CLAY_TEXT_WRAP_NONE - Text will never wrap even if its container is compressed beyond the text measured width.

I am considering a wrap mode which will wrap on individual characters in future but haven't decided on an implementation yet.

  • Improved performance of text layout when wrap is disabled or no wrapping needs to occur.
  • Fixed a bug that occurred when multiple nested floating containers were used.
  • Fixed a bug where the text measurement cache would not be used correctly.
  • Fixed a bug in the HTML renderer where text could be measured and cached before custom fonts had loaded.
  • Fixed a bug in the HTML renderer where alpha wasn't correctly respected.

Upgrade Guide

Unfortunately, this release contains some small breaking changes to the public API.

While I do my best to avoid breaking changes, Clay is still in alpha and the API is subject to change.

  • Element's uint32_t id has changed to a struct, Clay_ElementId. CLAY_ID and CLAY_IDI now return this struct, so layout definitions that use macros should not require migration. There are several cases where you might need to change the type of variables.
// Before
uint32_t id = CLAY_ID("Button");
// After
Clay_ElementId id = CLAY_ID("Button");

While functions that previously took uint32_t id as an argument have been updated, the parentId field of CLAY_FLOATING_CONFIG is still uint32_t. You can access the .id field of the Clay_ElementId struct in this case:

CLAY_FLOATING_CONTAINER(CLAY_ID("ScrollBar"), CLAY_LAYOUT(), CLAY_FLOATING_CONFIG(.parentId = CLAY_ID("OuterScrollContainer").id), {
  • Clay_BeginLayout and Clay_EndLayout now take no arguments, and there is a seperate function Clay_SetLayoutDimensions which is used to update the layout dimensions before the current frame. See the README for more details.
  • Clay_Initialize now expects Clay_Dimensions to set the initial layout dimensions. See the README for more details.
  • Clay_SetPointerPosition has been renamed to Clay_SetPointerState, and now expects a second argument isPointerDown representing whether or not the main mouse button / touch is currently held down.

v0.10

23 Aug 04:09

Choose a tag to compare

First release of clay.h