mirror of
https://github.com/nicbarker/clay.git
synced 2025-09-18 12:36:17 +00:00
Merge branch 'main' into HEAD
For image-related changes
This commit is contained in:
commit
d487d5990b
142
README.md
142
README.md
|
@ -92,7 +92,7 @@ int main() {
|
||||||
.backgroundColor = COLOR_LIGHT
|
.backgroundColor = COLOR_LIGHT
|
||||||
}) {
|
}) {
|
||||||
CLAY({ .id = CLAY_ID("ProfilePictureOuter"), .layout = { .sizing = { .width = CLAY_SIZING_GROW(0) }, .padding = CLAY_PADDING_ALL(16), .childGap = 16, .childAlignment = { .y = CLAY_ALIGN_Y_CENTER } }, .backgroundColor = COLOR_RED }) {
|
CLAY({ .id = CLAY_ID("ProfilePictureOuter"), .layout = { .sizing = { .width = CLAY_SIZING_GROW(0) }, .padding = CLAY_PADDING_ALL(16), .childGap = 16, .childAlignment = { .y = CLAY_ALIGN_Y_CENTER } }, .backgroundColor = COLOR_RED }) {
|
||||||
CLAY({ .id = CLAY_ID("ProfilePicture"), .layout = { .sizing = { .width = CLAY_SIZING_FIXED(60), .height = CLAY_SIZING_FIXED(60) }}, .image = { .imageData = &profilePicture, .sourceDimensions = {60, 60} } }) {}
|
CLAY({ .id = CLAY_ID("ProfilePicture"), .layout = { .sizing = { .width = CLAY_SIZING_FIXED(60), .height = CLAY_SIZING_FIXED(60) }}, .image = { .imageData = &profilePicture } }) {}
|
||||||
CLAY_TEXT(CLAY_STRING("Clay - UI Library"), CLAY_TEXT_CONFIG({ .fontSize = 24, .textColor = {255, 255, 255, 255} }));
|
CLAY_TEXT(CLAY_STRING("Clay - UI Library"), CLAY_TEXT_CONFIG({ .fontSize = 24, .textColor = {255, 255, 255, 255} }));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,8 +161,8 @@ For help starting out or to discuss clay, considering joining [the discord serve
|
||||||
- [Clay_MinMemorySize](#clay_minmemorysize)
|
- [Clay_MinMemorySize](#clay_minmemorysize)
|
||||||
- [Clay_CreateArenaWithCapacityAndMemory](#clay_createarenawithcapacityandmemory)
|
- [Clay_CreateArenaWithCapacityAndMemory](#clay_createarenawithcapacityandmemory)
|
||||||
- [Clay_SetMeasureTextFunction](#clay_setmeasuretextfunction)
|
- [Clay_SetMeasureTextFunction](#clay_setmeasuretextfunction)
|
||||||
- [Clay_ResetMeasureTextCache](#clau_resetmeasuretextcache)
|
- [Clay_ResetMeasureTextCache](#clay_resetmeasuretextcache)
|
||||||
- [Clay_SetMaxElementCount](clay_setmaxelementcount)
|
- [Clay_SetMaxElementCount](#clay_setmaxelementcount)
|
||||||
- [Clay_SetMaxMeasureTextCacheWordCount](#clay_setmaxmeasuretextcachewordcount)
|
- [Clay_SetMaxMeasureTextCacheWordCount](#clay_setmaxmeasuretextcachewordcount)
|
||||||
- [Clay_Initialize](#clay_initialize)
|
- [Clay_Initialize](#clay_initialize)
|
||||||
- [Clay_GetCurrentContext](#clay_getcurrentcontext)
|
- [Clay_GetCurrentContext](#clay_getcurrentcontext)
|
||||||
|
@ -360,11 +360,11 @@ Clay_UpdateScrollContainers(
|
||||||
);
|
);
|
||||||
// ...
|
// ...
|
||||||
// Clay internally tracks the scroll containers offset, and Clay_GetScrollOffset returns the x,y offset of the currently open element
|
// Clay internally tracks the scroll containers offset, and Clay_GetScrollOffset returns the x,y offset of the currently open element
|
||||||
CLAY({ .clip = vertical, .childOffset = Clay_GetScrollOffset() }) {
|
CLAY({ .clip = { .vertical = true, .childOffset = Clay_GetScrollOffset() } }) {
|
||||||
// Scrolling contents
|
// Scrolling contents
|
||||||
}
|
}
|
||||||
// .childOffset can be provided directly if you would prefer to manage scrolling outside of clay
|
// .childOffset can be provided directly if you would prefer to manage scrolling outside of clay
|
||||||
CLAY({ .clip = vertical, .childOffset = myData.scrollContainer.offset }) {
|
CLAY({ .clip = { .vertical = true, .childOffset = myData.scrollContainer.offset } }) {
|
||||||
// Scrolling contents
|
// Scrolling contents
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -839,7 +839,6 @@ Clay_TextElementConfig {
|
||||||
CLAY_TEXT_WRAP_NEWLINES,
|
CLAY_TEXT_WRAP_NEWLINES,
|
||||||
CLAY_TEXT_WRAP_NONE,
|
CLAY_TEXT_WRAP_NONE,
|
||||||
};
|
};
|
||||||
bool hashStringContents
|
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -899,14 +898,6 @@ Available options are:
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**`.hashStringContents`**
|
|
||||||
|
|
||||||
`CLAY_TEXT_CONFIG(.hashStringContents = true)`
|
|
||||||
|
|
||||||
By default, clay will cache the dimensions of text measured by [the provided MeasureText function](#clay_setmeasuretextfunction) based on the string's pointer and length. Setting `.hashStringContents = true` will cause Clay to hash the entire string contents. Used to fix incorrect measurements caused by re-use of string memory, disabled by default as it will incur significant performance overhead for very large bodies of text.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**Examples**
|
**Examples**
|
||||||
|
|
||||||
```C
|
```C
|
||||||
|
@ -1062,6 +1053,7 @@ typedef struct {
|
||||||
Clay_LayoutConfig layout;
|
Clay_LayoutConfig layout;
|
||||||
Clay_Color backgroundColor;
|
Clay_Color backgroundColor;
|
||||||
Clay_CornerRadius cornerRadius;
|
Clay_CornerRadius cornerRadius;
|
||||||
|
Clay_AspectRatioElementConfig aspectRatio;
|
||||||
Clay_ImageElementConfig image;
|
Clay_ImageElementConfig image;
|
||||||
Clay_FloatingElementConfig floating;
|
Clay_FloatingElementConfig floating;
|
||||||
Clay_CustomElementConfig custom;
|
Clay_CustomElementConfig custom;
|
||||||
|
@ -1108,9 +1100,17 @@ Note that the `CLAY_CORNER_RADIUS(radius)` function-like macro is available to p
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
**`.aspectRatio`** - `Clay_AspectRatioElementConfig`
|
||||||
|
|
||||||
|
`CLAY({ .aspectRatio = 1 })`
|
||||||
|
|
||||||
|
Uses [Clay_AspectRatioElementConfig](#clay_aspectratioelementconfig). Configures the element as an aspect ratio scaling element. Especially useful for rendering images, but can also be used to enforce a fixed width / height ratio of other elements.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
**`.image`** - `Clay_ImageElementConfig`
|
**`.image`** - `Clay_ImageElementConfig`
|
||||||
|
|
||||||
`CLAY({ .image = { .imageData = &myImage, .sourceDimensions = { 640, 480 } } })`
|
`CLAY({ .image = { .imageData = &myImage } })`
|
||||||
|
|
||||||
Uses [Clay_ImageElementConfig](#clay_imageelementconfig). Configures the element as an image element. Causes a render command with type `IMAGE` to be emitted.
|
Uses [Clay_ImageElementConfig](#clay_imageelementconfig). Configures the element as an image element. Causes a render command with type `IMAGE` to be emitted.
|
||||||
|
|
||||||
|
@ -1294,23 +1294,12 @@ CLAY({ .id = CLAY_ID("Button"), .layout = { .layoutDirection = CLAY_TOP_TO_BOTTO
|
||||||
|
|
||||||
```C
|
```C
|
||||||
Clay_ImageElementConfig {
|
Clay_ImageElementConfig {
|
||||||
Clay_Dimensions sourceDimensions {
|
|
||||||
float width; float height;
|
|
||||||
};
|
|
||||||
void * imageData;
|
void * imageData;
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
**Fields**
|
**Fields**
|
||||||
|
|
||||||
**`.sourceDimensions`** - `Clay_Dimensions`
|
|
||||||
|
|
||||||
`CLAY({ .image = { .sourceDimensions = { 1024, 768 } } }) {}`
|
|
||||||
|
|
||||||
Used to perform **aspect ratio scaling** on the image element. As of this version of clay, aspect ratio scaling only applies to the `height` of an image (i.e. image height will scale with width growth and limitations, but width will not scale with height growth and limitations)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**`.imageData`** - `void *`
|
**`.imageData`** - `void *`
|
||||||
|
|
||||||
`CLAY({ .image = { .imageData = &myImage } }) {}`
|
`CLAY({ .image = { .imageData = &myImage } }) {}`
|
||||||
|
@ -1321,7 +1310,7 @@ Used to perform **aspect ratio scaling** on the image element. As of this versio
|
||||||
// Load an image somewhere in your code
|
// Load an image somewhere in your code
|
||||||
YourImage profilePicture = LoadYourImage("profilePicture.png");
|
YourImage profilePicture = LoadYourImage("profilePicture.png");
|
||||||
// Note that when rendering, .imageData will be void* type.
|
// Note that when rendering, .imageData will be void* type.
|
||||||
CLAY({ .image = { .imageData = &profilePicture, .sourceDimensions = { 60, 60 } } }) {}
|
CLAY({ .image = { .imageData = &profilePicture } }) {}
|
||||||
```
|
```
|
||||||
|
|
||||||
**Examples**
|
**Examples**
|
||||||
|
@ -1330,11 +1319,105 @@ CLAY({ .image = { .imageData = &profilePicture, .sourceDimensions = { 60, 60 } }
|
||||||
// Load an image somewhere in your code
|
// Load an image somewhere in your code
|
||||||
YourImage profilePicture = LoadYourImage("profilePicture.png");
|
YourImage profilePicture = LoadYourImage("profilePicture.png");
|
||||||
// Declare a reusable image config
|
// Declare a reusable image config
|
||||||
Clay_ImageElementConfig imageConfig = (Clay_ImageElementConfig) { .imageData = &profilePicture, .sourceDimensions = {60, 60} };
|
Clay_ImageElementConfig imageConfig = (Clay_ImageElementConfig) { .imageData = &profilePicture };
|
||||||
// Declare an image element using a reusable config
|
// Declare an image element using a reusable config
|
||||||
CLAY({ .image = imageConfig }) {}
|
CLAY({ .image = imageConfig }) {}
|
||||||
// Declare an image element using an inline config
|
// Declare an image element using an inline config
|
||||||
CLAY({ .image = { .imageData = &profilePicture, .sourceDimensions = {60, 60} } }) {}
|
CLAY({ .image = { .imageData = &profilePicture }, .aspectRatio = 16.0 / 9.0 }) {}
|
||||||
|
// Rendering example
|
||||||
|
YourImage *imageToRender = renderCommand->elementConfig.imageElementConfig->imageData;
|
||||||
|
```
|
||||||
|
|
||||||
|
**Rendering**
|
||||||
|
|
||||||
|
Element is subject to [culling](#visibility-culling). Otherwise, a single `Clay_RenderCommand`s with `commandType = CLAY_RENDER_COMMAND_TYPE_IMAGE` will be created. The user will need to access `renderCommand->renderData.image->imageData` to retrieve image data referenced during layout creation. It's also up to the user to decide how / if they wish to blend `renderCommand->renderData.image->backgroundColor` with the image.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Clay_AspectRatioElementConfig
|
||||||
|
|
||||||
|
**Usage**
|
||||||
|
|
||||||
|
`CLAY({ .aspectRatio = 16.0 / 9.0 }) {}`
|
||||||
|
|
||||||
|
**Clay_AspectRatioElementConfig** configures a clay element to enforce a fixed width / height ratio in its final dimensions. Mostly used for image elements, but can also be used for non image elements.
|
||||||
|
|
||||||
|
**Struct API (Pseudocode)**
|
||||||
|
|
||||||
|
```C
|
||||||
|
Clay_AspectRatioElementConfig {
|
||||||
|
float aspectRatio;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
**Fields**
|
||||||
|
|
||||||
|
**`.aspectRatio`** - `float`
|
||||||
|
|
||||||
|
`CLAY({ .aspectRatio = { .aspectRatio = 16.0 / 9.0 } }) {}`
|
||||||
|
|
||||||
|
or alternatively, as C will automatically pass the value to the first nested struct field:
|
||||||
|
|
||||||
|
`CLAY({ .aspectRatio = 16.0 / 9.0 }) {}`
|
||||||
|
|
||||||
|
**Examples**
|
||||||
|
|
||||||
|
```C
|
||||||
|
// Load an image somewhere in your code
|
||||||
|
YourImage profilePicture = LoadYourImage("profilePicture.png");
|
||||||
|
// Declare an image element that will grow along the X axis while maintaining its original aspect ratio
|
||||||
|
CLAY({
|
||||||
|
.layout = { .width = CLAY_SIZING_GROW() },
|
||||||
|
.aspectRatio = profilePicture.width / profilePicture.height,
|
||||||
|
.image = { .imageData = &profilePicture },
|
||||||
|
}) {}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Clay_ImageElementConfig
|
||||||
|
**Usage**
|
||||||
|
|
||||||
|
`CLAY({ .image = { ...image config } }) {}`
|
||||||
|
|
||||||
|
**Clay_ImageElementConfig** configures a clay element to render an image as its background.
|
||||||
|
|
||||||
|
**Struct API (Pseudocode)**
|
||||||
|
|
||||||
|
```C
|
||||||
|
Clay_ImageElementConfig {
|
||||||
|
void * imageData;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
**Fields**
|
||||||
|
|
||||||
|
**`.imageData`** - `void *`
|
||||||
|
|
||||||
|
`CLAY({ .image = { .imageData = &myImage } }) {}`
|
||||||
|
|
||||||
|
`.imageData` is a generic void pointer that can be used to pass through image data to the renderer.
|
||||||
|
|
||||||
|
```C
|
||||||
|
// Load an image somewhere in your code
|
||||||
|
YourImage profilePicture = LoadYourImage("profilePicture.png");
|
||||||
|
// Note that when rendering, .imageData will be void* type.
|
||||||
|
CLAY({ .image = { .imageData = &profilePicture } }) {}
|
||||||
|
```
|
||||||
|
|
||||||
|
Note: for an image to maintain its original aspect ratio when using dynamic scaling, the [.aspectRatio](#clay_aspectratioelementconfig) config option must be used.
|
||||||
|
|
||||||
|
**Examples**
|
||||||
|
|
||||||
|
```C
|
||||||
|
// Load an image somewhere in your code
|
||||||
|
YourImage profilePicture = LoadYourImage("profilePicture.png");
|
||||||
|
// Declare a reusable image config
|
||||||
|
Clay_ImageElementConfig imageConfig = (Clay_ImageElementConfig) { .imageData = &profilePicture };
|
||||||
|
// Declare an image element using a reusable config
|
||||||
|
CLAY({ .image = imageConfig }) {}
|
||||||
|
// Declare an image element using an inline config
|
||||||
|
CLAY({ .image = { .imageData = &profilePicture }, .aspectRatio = 16.0 / 9.0 }) {}
|
||||||
// Rendering example
|
// Rendering example
|
||||||
YourImage *imageToRender = renderCommand->elementConfig.imageElementConfig->imageData;
|
YourImage *imageToRender = renderCommand->elementConfig.imageElementConfig->imageData;
|
||||||
```
|
```
|
||||||
|
@ -2020,7 +2103,6 @@ typedef struct {
|
||||||
typedef struct {
|
typedef struct {
|
||||||
Clay_Color backgroundColor;
|
Clay_Color backgroundColor;
|
||||||
Clay_CornerRadius cornerRadius;
|
Clay_CornerRadius cornerRadius;
|
||||||
Clay_Dimensions sourceDimensions;
|
|
||||||
void* imageData;
|
void* imageData;
|
||||||
} Clay_ImageRenderData;
|
} Clay_ImageRenderData;
|
||||||
```
|
```
|
||||||
|
|
|
@ -41,10 +41,10 @@ error_handler :: proc "c" (errorData: clay.ErrorData) {
|
||||||
// Do something with the error data.
|
// Do something with the error data.
|
||||||
}
|
}
|
||||||
|
|
||||||
min_memory_size: u32 = clay.MinMemorySize()
|
min_memory_size := clay.MinMemorySize()
|
||||||
memory := make([^]u8, min_memory_size)
|
memory := make([^]u8, min_memory_size)
|
||||||
arena: clay.Arena = clay.CreateArenaWithCapacityAndMemory(min_memory_size, memory)
|
arena: clay.Arena = clay.CreateArenaWithCapacityAndMemory(uint(min_memory_size), memory)
|
||||||
clay.Initialize(arena, { width = 1080, height = 720 }, { handler = error_handler })
|
clay.Initialize(arena, {1080, 720}, { handler = error_handler })
|
||||||
```
|
```
|
||||||
|
|
||||||
3. Provide a `measure_text(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.
|
3. Provide a `measure_text(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.
|
||||||
|
@ -74,7 +74,7 @@ clay.SetMeasureTextFunction(measure_text, nil)
|
||||||
```Odin
|
```Odin
|
||||||
// Update internal pointer position for handling mouseover / click / touch events
|
// Update internal pointer position for handling mouseover / click / touch events
|
||||||
clay.SetPointerState(
|
clay.SetPointerState(
|
||||||
clay.Vector2 { mouse_pos_x, mouse_pos_y },
|
{ mouse_pos_x, mouse_pos_y },
|
||||||
is_mouse_down,
|
is_mouse_down,
|
||||||
)
|
)
|
||||||
```
|
```
|
||||||
|
@ -148,6 +148,7 @@ create_layout :: proc() -> clay.ClayArray(clay.RenderCommand) {
|
||||||
sizing = { width = clay.SizingFixed(60), height = clay.SizingFixed(60) },
|
sizing = { width = clay.SizingFixed(60), height = clay.SizingFixed(60) },
|
||||||
},
|
},
|
||||||
image = {
|
image = {
|
||||||
|
// How you define `profile_picture` depends on your renderer.
|
||||||
imageData = &profile_picture,
|
imageData = &profile_picture,
|
||||||
sourceDimensions = {
|
sourceDimensions = {
|
||||||
width = 60,
|
width = 60,
|
||||||
|
@ -179,8 +180,7 @@ create_layout :: proc() -> clay.ClayArray(clay.RenderCommand) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns a list of render commands
|
// Returns a list of render commands
|
||||||
render_commands: clay.ClayArray(clay.RenderCommand) = clay.EndLayout()
|
return clay.EndLayout()
|
||||||
return render_commands
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -113,9 +113,12 @@ TextElementConfig :: struct {
|
||||||
textAlignment: TextAlignment,
|
textAlignment: TextAlignment,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AspectRatioElementConfig :: struct {
|
||||||
|
aspectRatio: f32,
|
||||||
|
}
|
||||||
|
|
||||||
ImageElementConfig :: struct {
|
ImageElementConfig :: struct {
|
||||||
imageData: rawptr,
|
imageData: rawptr,
|
||||||
sourceDimensions: Dimensions,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CustomElementConfig :: struct {
|
CustomElementConfig :: struct {
|
||||||
|
@ -203,7 +206,6 @@ RectangleRenderData :: struct {
|
||||||
ImageRenderData :: struct {
|
ImageRenderData :: struct {
|
||||||
backgroundColor: Color,
|
backgroundColor: Color,
|
||||||
cornerRadius: CornerRadius,
|
cornerRadius: CornerRadius,
|
||||||
sourceDimensions: Dimensions,
|
|
||||||
imageData: rawptr,
|
imageData: rawptr,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -340,6 +342,7 @@ ElementDeclaration :: struct {
|
||||||
layout: LayoutConfig,
|
layout: LayoutConfig,
|
||||||
backgroundColor: Color,
|
backgroundColor: Color,
|
||||||
cornerRadius: CornerRadius,
|
cornerRadius: CornerRadius,
|
||||||
|
aspectRatio: AspectRatioElementConfig,
|
||||||
image: ImageElementConfig,
|
image: ImageElementConfig,
|
||||||
floating: FloatingElementConfig,
|
floating: FloatingElementConfig,
|
||||||
custom: CustomElementConfig,
|
custom: CustomElementConfig,
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -72,7 +72,8 @@ LandingPageBlob :: proc(index: u32, fontSize: u16, fontId: u16, color: clay.Colo
|
||||||
if clay.UI()({
|
if clay.UI()({
|
||||||
id = clay.ID("CheckImage", index),
|
id = clay.ID("CheckImage", index),
|
||||||
layout = { sizing = { width = clay.SizingFixed(32) } },
|
layout = { sizing = { width = clay.SizingFixed(32) } },
|
||||||
image = { imageData = image, sourceDimensions = { 128, 128 } },
|
aspectRatio = { 1.0 },
|
||||||
|
image = { imageData = image },
|
||||||
}) {}
|
}) {}
|
||||||
clay.Text(text, clay.TextConfig({fontSize = fontSize, fontId = fontId, textColor = color}))
|
clay.Text(text, clay.TextConfig({fontSize = fontSize, fontId = fontId, textColor = color}))
|
||||||
}
|
}
|
||||||
|
@ -213,7 +214,8 @@ DeclarativeSyntaxPage :: proc(titleTextConfig: clay.TextElementConfig, widthSizi
|
||||||
if clay.UI()({
|
if clay.UI()({
|
||||||
id = clay.ID("SyntaxPageRightImageInner"),
|
id = clay.ID("SyntaxPageRightImageInner"),
|
||||||
layout = { sizing = { width = clay.SizingGrow({ max = 568 }) } },
|
layout = { sizing = { width = clay.SizingGrow({ max = 568 }) } },
|
||||||
image = { imageData = &syntaxImage, sourceDimensions = { 1136, 1194 } },
|
aspectRatio = { 1136.0 / 1194.0 },
|
||||||
|
image = { imageData = &syntaxImage },
|
||||||
}) {}
|
}) {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
241
clay.h
241
clay.h
|
@ -1,4 +1,4 @@
|
||||||
// VERSION: 0.13
|
// VERSION: 0.14
|
||||||
|
|
||||||
/*
|
/*
|
||||||
NOTE: In order to use this library you must define
|
NOTE: In order to use this library you must define
|
||||||
|
@ -31,7 +31,8 @@
|
||||||
#if !( \
|
#if !( \
|
||||||
(defined(__cplusplus) && __cplusplus >= 202002L) || \
|
(defined(__cplusplus) && __cplusplus >= 202002L) || \
|
||||||
(defined(__STDC__) && __STDC__ == 1 && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || \
|
(defined(__STDC__) && __STDC__ == 1 && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || \
|
||||||
defined(_MSC_VER) \
|
defined(_MSC_VER) || \
|
||||||
|
defined(__OBJC__) \
|
||||||
)
|
)
|
||||||
#error "Clay requires C99, C++20, or MSVC"
|
#error "Clay requires C99, C++20, or MSVC"
|
||||||
#endif
|
#endif
|
||||||
|
@ -184,7 +185,7 @@ extern "C" {
|
||||||
|
|
||||||
// Note: Clay_String is not guaranteed to be null terminated. It may be if created from a literal C string,
|
// Note: Clay_String is not guaranteed to be null terminated. It may be if created from a literal C string,
|
||||||
// but it is also used to represent slices.
|
// but it is also used to represent slices.
|
||||||
typedef struct {
|
typedef struct Clay_String {
|
||||||
// Set this boolean to true if the char* data underlying this string will live for the entire lifetime of the program.
|
// Set this boolean to true if the char* data underlying this string will live for the entire lifetime of the program.
|
||||||
// This will automatically be set for strings created with CLAY_STRING, as the macro requires a string literal.
|
// This will automatically be set for strings created with CLAY_STRING, as the macro requires a string literal.
|
||||||
bool isStaticallyAllocated;
|
bool isStaticallyAllocated;
|
||||||
|
@ -195,7 +196,7 @@ typedef struct {
|
||||||
|
|
||||||
// Clay_StringSlice is used to represent non owning string slices, and includes
|
// Clay_StringSlice is used to represent non owning string slices, and includes
|
||||||
// a baseChars field which points to the string this slice is derived from.
|
// a baseChars field which points to the string this slice is derived from.
|
||||||
typedef struct {
|
typedef struct Clay_StringSlice {
|
||||||
int32_t length;
|
int32_t length;
|
||||||
const char *chars;
|
const char *chars;
|
||||||
const char *baseChars; // The source string / char* that this slice was derived from
|
const char *baseChars; // The source string / char* that this slice was derived from
|
||||||
|
@ -205,33 +206,33 @@ typedef struct Clay_Context Clay_Context;
|
||||||
|
|
||||||
// Clay_Arena is a memory arena structure that is used by clay to manage its internal allocations.
|
// Clay_Arena is a memory arena structure that is used by clay to manage its internal allocations.
|
||||||
// Rather than creating it by hand, it's easier to use Clay_CreateArenaWithCapacityAndMemory()
|
// Rather than creating it by hand, it's easier to use Clay_CreateArenaWithCapacityAndMemory()
|
||||||
typedef struct {
|
typedef struct Clay_Arena {
|
||||||
uintptr_t nextAllocation;
|
uintptr_t nextAllocation;
|
||||||
size_t capacity;
|
size_t capacity;
|
||||||
char *memory;
|
char *memory;
|
||||||
} Clay_Arena;
|
} Clay_Arena;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct Clay_Dimensions {
|
||||||
float width, height;
|
float width, height;
|
||||||
} Clay_Dimensions;
|
} Clay_Dimensions;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct Clay_Vector2 {
|
||||||
float x, y;
|
float x, y;
|
||||||
} Clay_Vector2;
|
} Clay_Vector2;
|
||||||
|
|
||||||
// Internally clay conventionally represents colors as 0-255, but interpretation is up to the renderer.
|
// Internally clay conventionally represents colors as 0-255, but interpretation is up to the renderer.
|
||||||
typedef struct {
|
typedef struct Clay_Color {
|
||||||
float r, g, b, a;
|
float r, g, b, a;
|
||||||
} Clay_Color;
|
} Clay_Color;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct Clay_BoundingBox {
|
||||||
float x, y, width, height;
|
float x, y, width, height;
|
||||||
} Clay_BoundingBox;
|
} Clay_BoundingBox;
|
||||||
|
|
||||||
// Primarily created via the CLAY_ID(), CLAY_IDI(), CLAY_ID_LOCAL() and CLAY_IDI_LOCAL() macros.
|
// Primarily created via the CLAY_ID(), CLAY_IDI(), CLAY_ID_LOCAL() and CLAY_IDI_LOCAL() macros.
|
||||||
// Represents a hashed string ID used for identifying and finding specific clay UI elements, required
|
// Represents a hashed string ID used for identifying and finding specific clay UI elements, required
|
||||||
// by functions such as Clay_PointerOver() and Clay_GetElementData().
|
// by functions such as Clay_PointerOver() and Clay_GetElementData().
|
||||||
typedef struct {
|
typedef struct Clay_ElementId {
|
||||||
uint32_t id; // The resulting hash generated from the other fields.
|
uint32_t id; // The resulting hash generated from the other fields.
|
||||||
uint32_t offset; // A numerical offset applied after computing the hash from stringId.
|
uint32_t offset; // A numerical offset applied after computing the hash from stringId.
|
||||||
uint32_t baseId; // A base hash value to start from, for example the parent element ID is used when calculating CLAY_ID_LOCAL().
|
uint32_t baseId; // A base hash value to start from, for example the parent element ID is used when calculating CLAY_ID_LOCAL().
|
||||||
|
@ -248,7 +249,7 @@ typedef struct
|
||||||
|
|
||||||
// Controls the "radius", or corner rounding of elements, including rectangles, borders and images.
|
// Controls the "radius", or corner rounding of elements, including rectangles, borders and images.
|
||||||
// The rounding is determined by drawing a circle inset into the element corner by (radius, radius) pixels.
|
// The rounding is determined by drawing a circle inset into the element corner by (radius, radius) pixels.
|
||||||
typedef struct {
|
typedef struct Clay_CornerRadius {
|
||||||
float topLeft;
|
float topLeft;
|
||||||
float topRight;
|
float topRight;
|
||||||
float bottomLeft;
|
float bottomLeft;
|
||||||
|
@ -298,20 +299,20 @@ typedef CLAY_PACKED_ENUM {
|
||||||
} Clay__SizingType;
|
} Clay__SizingType;
|
||||||
|
|
||||||
// Controls how child elements are aligned on each axis.
|
// Controls how child elements are aligned on each axis.
|
||||||
typedef struct {
|
typedef struct Clay_ChildAlignment {
|
||||||
Clay_LayoutAlignmentX x; // Controls alignment of children along the x axis.
|
Clay_LayoutAlignmentX x; // Controls alignment of children along the x axis.
|
||||||
Clay_LayoutAlignmentY y; // Controls alignment of children along the y axis.
|
Clay_LayoutAlignmentY y; // Controls alignment of children along the y axis.
|
||||||
} Clay_ChildAlignment;
|
} Clay_ChildAlignment;
|
||||||
|
|
||||||
// Controls the minimum and maximum size in pixels that this element is allowed to grow or shrink to,
|
// Controls the minimum and maximum size in pixels that this element is allowed to grow or shrink to,
|
||||||
// overriding sizing types such as FIT or GROW.
|
// overriding sizing types such as FIT or GROW.
|
||||||
typedef struct {
|
typedef struct Clay_SizingMinMax {
|
||||||
float min; // The smallest final size of the element on this axis will be this value in pixels.
|
float min; // The smallest final size of the element on this axis will be this value in pixels.
|
||||||
float max; // The largest final size of the element on this axis will be this value in pixels.
|
float max; // The largest final size of the element on this axis will be this value in pixels.
|
||||||
} Clay_SizingMinMax;
|
} Clay_SizingMinMax;
|
||||||
|
|
||||||
// Controls the sizing of this element along one axis inside its parent container.
|
// Controls the sizing of this element along one axis inside its parent container.
|
||||||
typedef struct {
|
typedef struct Clay_SizingAxis {
|
||||||
union {
|
union {
|
||||||
Clay_SizingMinMax minMax; // Controls the minimum and maximum size in pixels that this element is allowed to grow or shrink to, overriding sizing types such as FIT or GROW.
|
Clay_SizingMinMax minMax; // Controls the minimum and maximum size in pixels that this element is allowed to grow or shrink to, overriding sizing types such as FIT or GROW.
|
||||||
float percent; // Expects 0-1 range. Clamps the axis size to a percent of the parent container's axis size minus padding and child gaps.
|
float percent; // Expects 0-1 range. Clamps the axis size to a percent of the parent container's axis size minus padding and child gaps.
|
||||||
|
@ -320,14 +321,14 @@ typedef struct {
|
||||||
} Clay_SizingAxis;
|
} Clay_SizingAxis;
|
||||||
|
|
||||||
// Controls the sizing of this element along one axis inside its parent container.
|
// Controls the sizing of this element along one axis inside its parent container.
|
||||||
typedef struct {
|
typedef struct Clay_Sizing {
|
||||||
Clay_SizingAxis width; // Controls the width sizing of the element, along the x axis.
|
Clay_SizingAxis width; // Controls the width sizing of the element, along the x axis.
|
||||||
Clay_SizingAxis height; // Controls the height sizing of the element, along the y axis.
|
Clay_SizingAxis height; // Controls the height sizing of the element, along the y axis.
|
||||||
} Clay_Sizing;
|
} Clay_Sizing;
|
||||||
|
|
||||||
// Controls "padding" in pixels, which is a gap between the bounding box of this element and where its children
|
// Controls "padding" in pixels, which is a gap between the bounding box of this element and where its children
|
||||||
// will be placed.
|
// will be placed.
|
||||||
typedef struct {
|
typedef struct Clay_Padding {
|
||||||
uint16_t left;
|
uint16_t left;
|
||||||
uint16_t right;
|
uint16_t right;
|
||||||
uint16_t top;
|
uint16_t top;
|
||||||
|
@ -338,7 +339,7 @@ CLAY__WRAPPER_STRUCT(Clay_Padding);
|
||||||
|
|
||||||
// Controls various settings that affect the size and position of an element, as well as the sizes and positions
|
// Controls various settings that affect the size and position of an element, as well as the sizes and positions
|
||||||
// of any child elements.
|
// of any child elements.
|
||||||
typedef struct {
|
typedef struct Clay_LayoutConfig {
|
||||||
Clay_Sizing sizing; // Controls the sizing of this element inside it's parent container, including FIT, GROW, PERCENT and FIXED sizing.
|
Clay_Sizing sizing; // Controls the sizing of this element inside it's parent container, including FIT, GROW, PERCENT and FIXED sizing.
|
||||||
Clay_Padding padding; // Controls "padding" in pixels, which is a gap between the bounding box of this element and where its children will be placed.
|
Clay_Padding padding; // Controls "padding" in pixels, which is a gap between the bounding box of this element and where its children will be placed.
|
||||||
uint16_t childGap; // Controls the gap in pixels between child elements along the layout axis (horizontal gap for LEFT_TO_RIGHT, vertical gap for TOP_TO_BOTTOM).
|
uint16_t childGap; // Controls the gap in pixels between child elements along the layout axis (horizontal gap for LEFT_TO_RIGHT, vertical gap for TOP_TO_BOTTOM).
|
||||||
|
@ -371,7 +372,7 @@ typedef CLAY_PACKED_ENUM {
|
||||||
} Clay_TextAlignment;
|
} Clay_TextAlignment;
|
||||||
|
|
||||||
// Controls various functionality related to text elements.
|
// Controls various functionality related to text elements.
|
||||||
typedef struct {
|
typedef struct Clay_TextElementConfig {
|
||||||
// A pointer that will be transparently passed through to the resulting render command.
|
// A pointer that will be transparently passed through to the resulting render command.
|
||||||
void *userData;
|
void *userData;
|
||||||
// The RGBA color of the font to render, conventionally specified as 0-255.
|
// The RGBA color of the font to render, conventionally specified as 0-255.
|
||||||
|
@ -399,12 +400,20 @@ typedef struct {
|
||||||
|
|
||||||
CLAY__WRAPPER_STRUCT(Clay_TextElementConfig);
|
CLAY__WRAPPER_STRUCT(Clay_TextElementConfig);
|
||||||
|
|
||||||
|
// Aspect Ratio --------------------------------
|
||||||
|
|
||||||
|
// Controls various settings related to aspect ratio scaling element.
|
||||||
|
typedef struct Clay_AspectRatioElementConfig {
|
||||||
|
float aspectRatio; // A float representing the target "Aspect ratio" for an element, which is its final width divided by its final height.
|
||||||
|
} Clay_AspectRatioElementConfig;
|
||||||
|
|
||||||
|
CLAY__WRAPPER_STRUCT(Clay_AspectRatioElementConfig);
|
||||||
|
|
||||||
// Image --------------------------------
|
// Image --------------------------------
|
||||||
|
|
||||||
// Controls various settings related to image elements.
|
// Controls various settings related to image elements.
|
||||||
typedef struct {
|
typedef struct Clay_ImageElementConfig {
|
||||||
void* imageData; // A transparent pointer used to pass image data through to the renderer.
|
void* imageData; // A transparent pointer used to pass image data through to the renderer.
|
||||||
Clay_Dimensions sourceDimensions; // The original dimensions of the source image, used to control aspect ratio.
|
|
||||||
} Clay_ImageElementConfig;
|
} Clay_ImageElementConfig;
|
||||||
|
|
||||||
CLAY__WRAPPER_STRUCT(Clay_ImageElementConfig);
|
CLAY__WRAPPER_STRUCT(Clay_ImageElementConfig);
|
||||||
|
@ -426,7 +435,7 @@ typedef CLAY_PACKED_ENUM {
|
||||||
} Clay_FloatingAttachPointType;
|
} Clay_FloatingAttachPointType;
|
||||||
|
|
||||||
// Controls where a floating element is offset relative to its parent element.
|
// Controls where a floating element is offset relative to its parent element.
|
||||||
typedef struct {
|
typedef struct Clay_FloatingAttachPoints {
|
||||||
Clay_FloatingAttachPointType element; // Controls the origin point on a floating element that attaches to its parent.
|
Clay_FloatingAttachPointType element; // Controls the origin point on a floating element that attaches to its parent.
|
||||||
Clay_FloatingAttachPointType parent; // Controls the origin point on the parent element that the floating element attaches to.
|
Clay_FloatingAttachPointType parent; // Controls the origin point on the parent element that the floating element attaches to.
|
||||||
} Clay_FloatingAttachPoints;
|
} Clay_FloatingAttachPoints;
|
||||||
|
@ -463,7 +472,7 @@ typedef CLAY_PACKED_ENUM {
|
||||||
|
|
||||||
// Controls various settings related to "floating" elements, which are elements that "float" above other elements, potentially overlapping their boundaries,
|
// Controls various settings related to "floating" elements, which are elements that "float" above other elements, potentially overlapping their boundaries,
|
||||||
// and not affecting the layout of sibling or parent elements.
|
// and not affecting the layout of sibling or parent elements.
|
||||||
typedef struct {
|
typedef struct Clay_FloatingElementConfig {
|
||||||
// Offsets this floating element by the provided x,y coordinates from its attachPoints.
|
// Offsets this floating element by the provided x,y coordinates from its attachPoints.
|
||||||
Clay_Vector2 offset;
|
Clay_Vector2 offset;
|
||||||
// Expands the boundaries of the outer floating element without affecting its children.
|
// Expands the boundaries of the outer floating element without affecting its children.
|
||||||
|
@ -500,7 +509,7 @@ CLAY__WRAPPER_STRUCT(Clay_FloatingElementConfig);
|
||||||
// Custom -----------------------------
|
// Custom -----------------------------
|
||||||
|
|
||||||
// Controls various settings related to custom elements.
|
// Controls various settings related to custom elements.
|
||||||
typedef struct {
|
typedef struct Clay_CustomElementConfig {
|
||||||
// A transparent pointer through which you can pass custom data to the renderer.
|
// A transparent pointer through which you can pass custom data to the renderer.
|
||||||
// Generates CUSTOM render commands.
|
// Generates CUSTOM render commands.
|
||||||
void* customData;
|
void* customData;
|
||||||
|
@ -511,7 +520,7 @@ CLAY__WRAPPER_STRUCT(Clay_CustomElementConfig);
|
||||||
// Scroll -----------------------------
|
// Scroll -----------------------------
|
||||||
|
|
||||||
// Controls the axis on which an element switches to "scrolling", which clips the contents and allows scrolling in that direction.
|
// Controls the axis on which an element switches to "scrolling", which clips the contents and allows scrolling in that direction.
|
||||||
typedef struct {
|
typedef struct Clay_ClipElementConfig {
|
||||||
bool horizontal; // Clip overflowing elements on the X axis.
|
bool horizontal; // Clip overflowing elements on the X axis.
|
||||||
bool vertical; // Clip overflowing elements on the Y axis.
|
bool vertical; // Clip overflowing elements on the Y axis.
|
||||||
Clay_Vector2 childOffset; // Offsets the x,y positions of all child elements. Used primarily for scrolling containers.
|
Clay_Vector2 childOffset; // Offsets the x,y positions of all child elements. Used primarily for scrolling containers.
|
||||||
|
@ -522,7 +531,7 @@ CLAY__WRAPPER_STRUCT(Clay_ClipElementConfig);
|
||||||
// Border -----------------------------
|
// Border -----------------------------
|
||||||
|
|
||||||
// Controls the widths of individual element borders.
|
// Controls the widths of individual element borders.
|
||||||
typedef struct {
|
typedef struct Clay_BorderWidth {
|
||||||
uint16_t left;
|
uint16_t left;
|
||||||
uint16_t right;
|
uint16_t right;
|
||||||
uint16_t top;
|
uint16_t top;
|
||||||
|
@ -534,7 +543,7 @@ typedef struct {
|
||||||
} Clay_BorderWidth;
|
} Clay_BorderWidth;
|
||||||
|
|
||||||
// Controls settings related to element borders.
|
// Controls settings related to element borders.
|
||||||
typedef struct {
|
typedef struct Clay_BorderElementConfig {
|
||||||
Clay_Color color; // Controls the color of all borders with width > 0. Conventionally represented as 0-255, but interpretation is up to the renderer.
|
Clay_Color color; // Controls the color of all borders with width > 0. Conventionally represented as 0-255, but interpretation is up to the renderer.
|
||||||
Clay_BorderWidth width; // Controls the widths of individual borders. At least one of these should be > 0 for a BORDER render command to be generated.
|
Clay_BorderWidth width; // Controls the widths of individual borders. At least one of these should be > 0 for a BORDER render command to be generated.
|
||||||
} Clay_BorderElementConfig;
|
} Clay_BorderElementConfig;
|
||||||
|
@ -544,7 +553,7 @@ CLAY__WRAPPER_STRUCT(Clay_BorderElementConfig);
|
||||||
// Render Command Data -----------------------------
|
// Render Command Data -----------------------------
|
||||||
|
|
||||||
// Render command data when commandType == CLAY_RENDER_COMMAND_TYPE_TEXT
|
// Render command data when commandType == CLAY_RENDER_COMMAND_TYPE_TEXT
|
||||||
typedef struct {
|
typedef struct Clay_TextRenderData {
|
||||||
// A string slice containing the text to be rendered.
|
// A string slice containing the text to be rendered.
|
||||||
// Note: this is not guaranteed to be null terminated.
|
// Note: this is not guaranteed to be null terminated.
|
||||||
Clay_StringSlice stringContents;
|
Clay_StringSlice stringContents;
|
||||||
|
@ -560,7 +569,7 @@ typedef struct {
|
||||||
} Clay_TextRenderData;
|
} Clay_TextRenderData;
|
||||||
|
|
||||||
// Render command data when commandType == CLAY_RENDER_COMMAND_TYPE_RECTANGLE
|
// Render command data when commandType == CLAY_RENDER_COMMAND_TYPE_RECTANGLE
|
||||||
typedef struct {
|
typedef struct Clay_RectangleRenderData {
|
||||||
// The solid background color to fill this rectangle with. Conventionally represented as 0-255 for each channel, but interpretation is up to the renderer.
|
// The solid background color to fill this rectangle with. Conventionally represented as 0-255 for each channel, but interpretation is up to the renderer.
|
||||||
Clay_Color backgroundColor;
|
Clay_Color backgroundColor;
|
||||||
// Controls the "radius", or corner rounding of elements, including rectangles, borders and images.
|
// Controls the "radius", or corner rounding of elements, including rectangles, borders and images.
|
||||||
|
@ -569,7 +578,7 @@ typedef struct {
|
||||||
} Clay_RectangleRenderData;
|
} Clay_RectangleRenderData;
|
||||||
|
|
||||||
// Render command data when commandType == CLAY_RENDER_COMMAND_TYPE_IMAGE
|
// Render command data when commandType == CLAY_RENDER_COMMAND_TYPE_IMAGE
|
||||||
typedef struct {
|
typedef struct Clay_ImageRenderData {
|
||||||
// The tint color for this image. Note that the default value is 0,0,0,0 and should likely be interpreted
|
// The tint color for this image. Note that the default value is 0,0,0,0 and should likely be interpreted
|
||||||
// as "untinted".
|
// as "untinted".
|
||||||
// Conventionally represented as 0-255 for each channel, but interpretation is up to the renderer.
|
// Conventionally represented as 0-255 for each channel, but interpretation is up to the renderer.
|
||||||
|
@ -577,14 +586,12 @@ typedef struct {
|
||||||
// Controls the "radius", or corner rounding of this image.
|
// Controls the "radius", or corner rounding of this image.
|
||||||
// The rounding is determined by drawing a circle inset into the element corner by (radius, radius) pixels.
|
// The rounding is determined by drawing a circle inset into the element corner by (radius, radius) pixels.
|
||||||
Clay_CornerRadius cornerRadius;
|
Clay_CornerRadius cornerRadius;
|
||||||
// The original dimensions of the source image, used to control aspect ratio.
|
|
||||||
Clay_Dimensions sourceDimensions;
|
|
||||||
// A pointer transparently passed through from the original element definition, typically used to represent image data.
|
// A pointer transparently passed through from the original element definition, typically used to represent image data.
|
||||||
void* imageData;
|
void* imageData;
|
||||||
} Clay_ImageRenderData;
|
} Clay_ImageRenderData;
|
||||||
|
|
||||||
// Render command data when commandType == CLAY_RENDER_COMMAND_TYPE_CUSTOM
|
// Render command data when commandType == CLAY_RENDER_COMMAND_TYPE_CUSTOM
|
||||||
typedef struct {
|
typedef struct Clay_CustomRenderData {
|
||||||
// Passed through from .backgroundColor in the original element declaration.
|
// Passed through from .backgroundColor in the original element declaration.
|
||||||
// Conventionally represented as 0-255 for each channel, but interpretation is up to the renderer.
|
// Conventionally represented as 0-255 for each channel, but interpretation is up to the renderer.
|
||||||
Clay_Color backgroundColor;
|
Clay_Color backgroundColor;
|
||||||
|
@ -596,13 +603,13 @@ typedef struct {
|
||||||
} Clay_CustomRenderData;
|
} Clay_CustomRenderData;
|
||||||
|
|
||||||
// Render command data when commandType == CLAY_RENDER_COMMAND_TYPE_SCISSOR_START || commandType == CLAY_RENDER_COMMAND_TYPE_SCISSOR_END
|
// Render command data when commandType == CLAY_RENDER_COMMAND_TYPE_SCISSOR_START || commandType == CLAY_RENDER_COMMAND_TYPE_SCISSOR_END
|
||||||
typedef struct {
|
typedef struct Clay_ScrollRenderData {
|
||||||
bool horizontal;
|
bool horizontal;
|
||||||
bool vertical;
|
bool vertical;
|
||||||
} Clay_ClipRenderData;
|
} Clay_ClipRenderData;
|
||||||
|
|
||||||
// Render command data when commandType == CLAY_RENDER_COMMAND_TYPE_BORDER
|
// Render command data when commandType == CLAY_RENDER_COMMAND_TYPE_BORDER
|
||||||
typedef struct {
|
typedef struct Clay_BorderRenderData {
|
||||||
// Controls a shared color for all this element's borders.
|
// Controls a shared color for all this element's borders.
|
||||||
// Conventionally represented as 0-255 for each channel, but interpretation is up to the renderer.
|
// Conventionally represented as 0-255 for each channel, but interpretation is up to the renderer.
|
||||||
Clay_Color color;
|
Clay_Color color;
|
||||||
|
@ -614,7 +621,7 @@ typedef struct {
|
||||||
} Clay_BorderRenderData;
|
} Clay_BorderRenderData;
|
||||||
|
|
||||||
// A struct union containing data specific to this command's .commandType
|
// A struct union containing data specific to this command's .commandType
|
||||||
typedef union {
|
typedef union Clay_RenderData {
|
||||||
// Render command data when commandType == CLAY_RENDER_COMMAND_TYPE_RECTANGLE
|
// Render command data when commandType == CLAY_RENDER_COMMAND_TYPE_RECTANGLE
|
||||||
Clay_RectangleRenderData rectangle;
|
Clay_RectangleRenderData rectangle;
|
||||||
// Render command data when commandType == CLAY_RENDER_COMMAND_TYPE_TEXT
|
// Render command data when commandType == CLAY_RENDER_COMMAND_TYPE_TEXT
|
||||||
|
@ -632,7 +639,7 @@ typedef union {
|
||||||
// Miscellaneous Structs & Enums ---------------------------------
|
// Miscellaneous Structs & Enums ---------------------------------
|
||||||
|
|
||||||
// Data representing the current internal state of a scrolling element.
|
// Data representing the current internal state of a scrolling element.
|
||||||
typedef struct {
|
typedef struct Clay_ScrollContainerData {
|
||||||
// Note: This is a pointer to the real internal scroll position, mutating it may cause a change in final layout.
|
// 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.
|
// Intended for use with external functionality that modifies scroll position, such as scroll bars or auto scrolling.
|
||||||
Clay_Vector2 *scrollPosition;
|
Clay_Vector2 *scrollPosition;
|
||||||
|
@ -647,7 +654,7 @@ typedef struct {
|
||||||
} Clay_ScrollContainerData;
|
} Clay_ScrollContainerData;
|
||||||
|
|
||||||
// Bounding box and other data for a specific UI element.
|
// Bounding box and other data for a specific UI element.
|
||||||
typedef struct {
|
typedef struct Clay_ElementData {
|
||||||
// The rectangle that encloses this UI element, with the position relative to the root of the layout.
|
// The rectangle that encloses this UI element, with the position relative to the root of the layout.
|
||||||
Clay_BoundingBox boundingBox;
|
Clay_BoundingBox boundingBox;
|
||||||
// Indicates whether an actual Element matched the provided ID or if the default struct was returned.
|
// Indicates whether an actual Element matched the provided ID or if the default struct was returned.
|
||||||
|
@ -674,7 +681,7 @@ typedef CLAY_PACKED_ENUM {
|
||||||
CLAY_RENDER_COMMAND_TYPE_CUSTOM,
|
CLAY_RENDER_COMMAND_TYPE_CUSTOM,
|
||||||
} Clay_RenderCommandType;
|
} Clay_RenderCommandType;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct Clay_RenderCommand {
|
||||||
// A rectangular box that fully encloses this UI element, with the position relative to the root of the layout.
|
// A rectangular box that fully encloses this UI element, with the position relative to the root of the layout.
|
||||||
Clay_BoundingBox boundingBox;
|
Clay_BoundingBox boundingBox;
|
||||||
// A struct union containing data specific to this command's commandType.
|
// A struct union containing data specific to this command's commandType.
|
||||||
|
@ -699,7 +706,7 @@ typedef struct {
|
||||||
} Clay_RenderCommand;
|
} Clay_RenderCommand;
|
||||||
|
|
||||||
// A sized array of render commands.
|
// A sized array of render commands.
|
||||||
typedef struct {
|
typedef struct Clay_RenderCommandArray {
|
||||||
// The underlying max capacity of the array, not necessarily all initialized.
|
// The underlying max capacity of the array, not necessarily all initialized.
|
||||||
int32_t capacity;
|
int32_t capacity;
|
||||||
// The number of initialized elements in this array. Used for loops and iteration.
|
// The number of initialized elements in this array. Used for loops and iteration.
|
||||||
|
@ -721,7 +728,7 @@ typedef CLAY_PACKED_ENUM {
|
||||||
} Clay_PointerDataInteractionState;
|
} Clay_PointerDataInteractionState;
|
||||||
|
|
||||||
// Information on the current state of pointer interactions this frame.
|
// Information on the current state of pointer interactions this frame.
|
||||||
typedef struct {
|
typedef struct Clay_PointerData {
|
||||||
// The position of the mouse / touch / pointer relative to the root of the layout.
|
// The position of the mouse / touch / pointer relative to the root of the layout.
|
||||||
Clay_Vector2 position;
|
Clay_Vector2 position;
|
||||||
// Represents the current state of interaction with clay this frame.
|
// Represents the current state of interaction with clay this frame.
|
||||||
|
@ -732,7 +739,7 @@ typedef struct {
|
||||||
Clay_PointerDataInteractionState state;
|
Clay_PointerDataInteractionState state;
|
||||||
} Clay_PointerData;
|
} Clay_PointerData;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct Clay_ElementDeclaration {
|
||||||
// Primarily created via the CLAY_ID(), CLAY_IDI(), CLAY_ID_LOCAL() and CLAY_IDI_LOCAL() macros.
|
// Primarily created via the CLAY_ID(), CLAY_IDI(), CLAY_ID_LOCAL() and CLAY_IDI_LOCAL() macros.
|
||||||
// Represents a hashed string ID used for identifying and finding specific clay UI elements, required by functions such as Clay_PointerOver() and Clay_GetElementData().
|
// Represents a hashed string ID used for identifying and finding specific clay UI elements, required by functions such as Clay_PointerOver() and Clay_GetElementData().
|
||||||
Clay_ElementId id;
|
Clay_ElementId id;
|
||||||
|
@ -744,6 +751,8 @@ typedef struct {
|
||||||
Clay_Color backgroundColor;
|
Clay_Color backgroundColor;
|
||||||
// Controls the "radius", or corner rounding of elements, including rectangles, borders and images.
|
// Controls the "radius", or corner rounding of elements, including rectangles, borders and images.
|
||||||
Clay_CornerRadius cornerRadius;
|
Clay_CornerRadius cornerRadius;
|
||||||
|
// Controls settings related to aspect ratio scaling.
|
||||||
|
Clay_AspectRatioElementConfig aspectRatio;
|
||||||
// Controls settings related to image elements.
|
// Controls settings related to image elements.
|
||||||
Clay_ImageElementConfig image;
|
Clay_ImageElementConfig image;
|
||||||
// Controls whether and how an element "floats", which means it layers over the top of other elements in z order, and doesn't affect the position and size of siblings or parent elements.
|
// Controls whether and how an element "floats", which means it layers over the top of other elements in z order, and doesn't affect the position and size of siblings or parent elements.
|
||||||
|
@ -783,7 +792,7 @@ typedef CLAY_PACKED_ENUM {
|
||||||
} Clay_ErrorType;
|
} Clay_ErrorType;
|
||||||
|
|
||||||
// Data to identify the error that clay has encountered.
|
// Data to identify the error that clay has encountered.
|
||||||
typedef struct {
|
typedef struct Clay_ErrorData {
|
||||||
// Represents the type of error clay encountered while computing layout.
|
// Represents the type of error clay encountered while computing layout.
|
||||||
// CLAY_ERROR_TYPE_TEXT_MEASUREMENT_FUNCTION_NOT_PROVIDED - A text measurement function wasn't provided using Clay_SetMeasureTextFunction(), or the provided function was null.
|
// CLAY_ERROR_TYPE_TEXT_MEASUREMENT_FUNCTION_NOT_PROVIDED - A text measurement function wasn't provided using Clay_SetMeasureTextFunction(), or the provided function was null.
|
||||||
// CLAY_ERROR_TYPE_ARENA_CAPACITY_EXCEEDED - Clay attempted to allocate its internal data structures but ran out of space. The arena passed to Clay_Initialize was created with a capacity smaller than that required by Clay_MinMemorySize().
|
// CLAY_ERROR_TYPE_ARENA_CAPACITY_EXCEEDED - Clay attempted to allocate its internal data structures but ran out of space. The arena passed to Clay_Initialize was created with a capacity smaller than that required by Clay_MinMemorySize().
|
||||||
|
@ -1058,6 +1067,7 @@ CLAY__ARRAY_DEFINE(char, Clay__charArray)
|
||||||
CLAY__ARRAY_DEFINE_FUNCTIONS(Clay_ElementId, Clay_ElementIdArray)
|
CLAY__ARRAY_DEFINE_FUNCTIONS(Clay_ElementId, Clay_ElementIdArray)
|
||||||
CLAY__ARRAY_DEFINE(Clay_LayoutConfig, Clay__LayoutConfigArray)
|
CLAY__ARRAY_DEFINE(Clay_LayoutConfig, Clay__LayoutConfigArray)
|
||||||
CLAY__ARRAY_DEFINE(Clay_TextElementConfig, Clay__TextElementConfigArray)
|
CLAY__ARRAY_DEFINE(Clay_TextElementConfig, Clay__TextElementConfigArray)
|
||||||
|
CLAY__ARRAY_DEFINE(Clay_AspectRatioElementConfig, Clay__AspectRatioElementConfigArray)
|
||||||
CLAY__ARRAY_DEFINE(Clay_ImageElementConfig, Clay__ImageElementConfigArray)
|
CLAY__ARRAY_DEFINE(Clay_ImageElementConfig, Clay__ImageElementConfigArray)
|
||||||
CLAY__ARRAY_DEFINE(Clay_FloatingElementConfig, Clay__FloatingElementConfigArray)
|
CLAY__ARRAY_DEFINE(Clay_FloatingElementConfig, Clay__FloatingElementConfigArray)
|
||||||
CLAY__ARRAY_DEFINE(Clay_CustomElementConfig, Clay__CustomElementConfigArray)
|
CLAY__ARRAY_DEFINE(Clay_CustomElementConfig, Clay__CustomElementConfigArray)
|
||||||
|
@ -1072,6 +1082,7 @@ typedef CLAY_PACKED_ENUM {
|
||||||
CLAY__ELEMENT_CONFIG_TYPE_BORDER,
|
CLAY__ELEMENT_CONFIG_TYPE_BORDER,
|
||||||
CLAY__ELEMENT_CONFIG_TYPE_FLOATING,
|
CLAY__ELEMENT_CONFIG_TYPE_FLOATING,
|
||||||
CLAY__ELEMENT_CONFIG_TYPE_CLIP,
|
CLAY__ELEMENT_CONFIG_TYPE_CLIP,
|
||||||
|
CLAY__ELEMENT_CONFIG_TYPE_ASPECT,
|
||||||
CLAY__ELEMENT_CONFIG_TYPE_IMAGE,
|
CLAY__ELEMENT_CONFIG_TYPE_IMAGE,
|
||||||
CLAY__ELEMENT_CONFIG_TYPE_TEXT,
|
CLAY__ELEMENT_CONFIG_TYPE_TEXT,
|
||||||
CLAY__ELEMENT_CONFIG_TYPE_CUSTOM,
|
CLAY__ELEMENT_CONFIG_TYPE_CUSTOM,
|
||||||
|
@ -1080,6 +1091,7 @@ typedef CLAY_PACKED_ENUM {
|
||||||
|
|
||||||
typedef union {
|
typedef union {
|
||||||
Clay_TextElementConfig *textElementConfig;
|
Clay_TextElementConfig *textElementConfig;
|
||||||
|
Clay_AspectRatioElementConfig *aspectRatioElementConfig;
|
||||||
Clay_ImageElementConfig *imageElementConfig;
|
Clay_ImageElementConfig *imageElementConfig;
|
||||||
Clay_FloatingElementConfig *floatingElementConfig;
|
Clay_FloatingElementConfig *floatingElementConfig;
|
||||||
Clay_CustomElementConfig *customElementConfig;
|
Clay_CustomElementConfig *customElementConfig;
|
||||||
|
@ -1236,13 +1248,14 @@ struct Clay_Context {
|
||||||
Clay__int32_tArray layoutElementChildren;
|
Clay__int32_tArray layoutElementChildren;
|
||||||
Clay__int32_tArray layoutElementChildrenBuffer;
|
Clay__int32_tArray layoutElementChildrenBuffer;
|
||||||
Clay__TextElementDataArray textElementData;
|
Clay__TextElementDataArray textElementData;
|
||||||
Clay__int32_tArray imageElementPointers;
|
Clay__int32_tArray aspectRatioElementIndexes;
|
||||||
Clay__int32_tArray reusableElementIndexBuffer;
|
Clay__int32_tArray reusableElementIndexBuffer;
|
||||||
Clay__int32_tArray layoutElementClipElementIds;
|
Clay__int32_tArray layoutElementClipElementIds;
|
||||||
// Configs
|
// Configs
|
||||||
Clay__LayoutConfigArray layoutConfigs;
|
Clay__LayoutConfigArray layoutConfigs;
|
||||||
Clay__ElementConfigArray elementConfigs;
|
Clay__ElementConfigArray elementConfigs;
|
||||||
Clay__TextElementConfigArray textElementConfigs;
|
Clay__TextElementConfigArray textElementConfigs;
|
||||||
|
Clay__AspectRatioElementConfigArray aspectRatioElementConfigs;
|
||||||
Clay__ImageElementConfigArray imageElementConfigs;
|
Clay__ImageElementConfigArray imageElementConfigs;
|
||||||
Clay__FloatingElementConfigArray floatingElementConfigs;
|
Clay__FloatingElementConfigArray floatingElementConfigs;
|
||||||
Clay__ClipElementConfigArray clipElementConfigs;
|
Clay__ClipElementConfigArray clipElementConfigs;
|
||||||
|
@ -1271,15 +1284,12 @@ struct Clay_Context {
|
||||||
|
|
||||||
Clay_Context* Clay__Context_Allocate_Arena(Clay_Arena *arena) {
|
Clay_Context* Clay__Context_Allocate_Arena(Clay_Arena *arena) {
|
||||||
size_t totalSizeBytes = sizeof(Clay_Context);
|
size_t totalSizeBytes = sizeof(Clay_Context);
|
||||||
uintptr_t memoryAddress = (uintptr_t)arena->memory;
|
if (totalSizeBytes > arena->capacity)
|
||||||
// Make sure the memory address passed in for clay to use is cache line aligned
|
|
||||||
uintptr_t nextAllocOffset = (memoryAddress % 64);
|
|
||||||
if (nextAllocOffset + totalSizeBytes > arena->capacity)
|
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
arena->nextAllocation = nextAllocOffset + totalSizeBytes;
|
arena->nextAllocation += totalSizeBytes;
|
||||||
return (Clay_Context*)(memoryAddress + nextAllocOffset);
|
return (Clay_Context*)(arena->memory);
|
||||||
}
|
}
|
||||||
|
|
||||||
Clay_String Clay__WriteStringToCharBuffer(Clay__charArray *buffer, Clay_String string) {
|
Clay_String Clay__WriteStringToCharBuffer(Clay__charArray *buffer, Clay_String string) {
|
||||||
|
@ -1310,6 +1320,7 @@ uint32_t Clay__GetParentElementId(void) {
|
||||||
|
|
||||||
Clay_LayoutConfig * Clay__StoreLayoutConfig(Clay_LayoutConfig config) { return Clay_GetCurrentContext()->booleanWarnings.maxElementsExceeded ? &CLAY_LAYOUT_DEFAULT : Clay__LayoutConfigArray_Add(&Clay_GetCurrentContext()->layoutConfigs, config); }
|
Clay_LayoutConfig * Clay__StoreLayoutConfig(Clay_LayoutConfig config) { return Clay_GetCurrentContext()->booleanWarnings.maxElementsExceeded ? &CLAY_LAYOUT_DEFAULT : Clay__LayoutConfigArray_Add(&Clay_GetCurrentContext()->layoutConfigs, config); }
|
||||||
Clay_TextElementConfig * Clay__StoreTextElementConfig(Clay_TextElementConfig config) { return Clay_GetCurrentContext()->booleanWarnings.maxElementsExceeded ? &Clay_TextElementConfig_DEFAULT : Clay__TextElementConfigArray_Add(&Clay_GetCurrentContext()->textElementConfigs, config); }
|
Clay_TextElementConfig * Clay__StoreTextElementConfig(Clay_TextElementConfig config) { return Clay_GetCurrentContext()->booleanWarnings.maxElementsExceeded ? &Clay_TextElementConfig_DEFAULT : Clay__TextElementConfigArray_Add(&Clay_GetCurrentContext()->textElementConfigs, config); }
|
||||||
|
Clay_AspectRatioElementConfig * Clay__StoreAspectRatioElementConfig(Clay_AspectRatioElementConfig config) { return Clay_GetCurrentContext()->booleanWarnings.maxElementsExceeded ? &Clay_AspectRatioElementConfig_DEFAULT : Clay__AspectRatioElementConfigArray_Add(&Clay_GetCurrentContext()->aspectRatioElementConfigs, config); }
|
||||||
Clay_ImageElementConfig * Clay__StoreImageElementConfig(Clay_ImageElementConfig config) { return Clay_GetCurrentContext()->booleanWarnings.maxElementsExceeded ? &Clay_ImageElementConfig_DEFAULT : Clay__ImageElementConfigArray_Add(&Clay_GetCurrentContext()->imageElementConfigs, config); }
|
Clay_ImageElementConfig * Clay__StoreImageElementConfig(Clay_ImageElementConfig config) { return Clay_GetCurrentContext()->booleanWarnings.maxElementsExceeded ? &Clay_ImageElementConfig_DEFAULT : Clay__ImageElementConfigArray_Add(&Clay_GetCurrentContext()->imageElementConfigs, config); }
|
||||||
Clay_FloatingElementConfig * Clay__StoreFloatingElementConfig(Clay_FloatingElementConfig config) { return Clay_GetCurrentContext()->booleanWarnings.maxElementsExceeded ? &Clay_FloatingElementConfig_DEFAULT : Clay__FloatingElementConfigArray_Add(&Clay_GetCurrentContext()->floatingElementConfigs, config); }
|
Clay_FloatingElementConfig * Clay__StoreFloatingElementConfig(Clay_FloatingElementConfig config) { return Clay_GetCurrentContext()->booleanWarnings.maxElementsExceeded ? &Clay_FloatingElementConfig_DEFAULT : Clay__FloatingElementConfigArray_Add(&Clay_GetCurrentContext()->floatingElementConfigs, config); }
|
||||||
Clay_CustomElementConfig * Clay__StoreCustomElementConfig(Clay_CustomElementConfig config) { return Clay_GetCurrentContext()->booleanWarnings.maxElementsExceeded ? &Clay_CustomElementConfig_DEFAULT : Clay__CustomElementConfigArray_Add(&Clay_GetCurrentContext()->customElementConfigs, config); }
|
Clay_CustomElementConfig * Clay__StoreCustomElementConfig(Clay_CustomElementConfig config) { return Clay_GetCurrentContext()->booleanWarnings.maxElementsExceeded ? &Clay_CustomElementConfig_DEFAULT : Clay__CustomElementConfigArray_Add(&Clay_GetCurrentContext()->customElementConfigs, config); }
|
||||||
|
@ -1483,7 +1494,7 @@ uint64_t Clay__HashData(const uint8_t* data, size_t length) {
|
||||||
uint64_t Clay__HashData(const uint8_t* data, size_t length) {
|
uint64_t Clay__HashData(const uint8_t* data, size_t length) {
|
||||||
uint64_t hash = 0;
|
uint64_t hash = 0;
|
||||||
|
|
||||||
for (int32_t i = 0; i < length; i++) {
|
for (size_t i = 0; i < length; i++) {
|
||||||
hash += data[i];
|
hash += data[i];
|
||||||
hash += (hash << 10);
|
hash += (hash << 10);
|
||||||
hash ^= (hash >> 6);
|
hash ^= (hash >> 6);
|
||||||
|
@ -1632,7 +1643,10 @@ Clay__MeasureTextCacheItem *Clay__MeasureTextCached(Clay_String *text, Clay_Text
|
||||||
char current = text->chars[end];
|
char current = text->chars[end];
|
||||||
if (current == ' ' || current == '\n') {
|
if (current == ' ' || current == '\n') {
|
||||||
int32_t length = end - start;
|
int32_t length = end - start;
|
||||||
Clay_Dimensions dimensions = Clay__MeasureText(CLAY__INIT(Clay_StringSlice) { .length = length, .chars = &text->chars[start], .baseChars = text->chars }, config, context->measureTextUserData);
|
Clay_Dimensions dimensions = {};
|
||||||
|
if (length > 0) {
|
||||||
|
dimensions = Clay__MeasureText(CLAY__INIT(Clay_StringSlice) {.length = length, .chars = &text->chars[start], .baseChars = text->chars}, config, context->measureTextUserData);
|
||||||
|
}
|
||||||
measured->minWidth = CLAY__MAX(dimensions.width, measured->minWidth);
|
measured->minWidth = CLAY__MAX(dimensions.width, measured->minWidth);
|
||||||
measuredHeight = CLAY__MAX(measuredHeight, dimensions.height);
|
measuredHeight = CLAY__MAX(measuredHeight, dimensions.height);
|
||||||
if (current == ' ') {
|
if (current == ' ') {
|
||||||
|
@ -1661,7 +1675,7 @@ Clay__MeasureTextCacheItem *Clay__MeasureTextCached(Clay_String *text, Clay_Text
|
||||||
measuredHeight = CLAY__MAX(measuredHeight, dimensions.height);
|
measuredHeight = CLAY__MAX(measuredHeight, dimensions.height);
|
||||||
measured->minWidth = CLAY__MAX(dimensions.width, measured->minWidth);
|
measured->minWidth = CLAY__MAX(dimensions.width, measured->minWidth);
|
||||||
}
|
}
|
||||||
measuredWidth = CLAY__MAX(lineWidth, measuredWidth);
|
measuredWidth = CLAY__MAX(lineWidth, measuredWidth) - config->letterSpacing;
|
||||||
|
|
||||||
measured->measuredWordsStartIndex = tempWord.next;
|
measured->measuredWordsStartIndex = tempWord.next;
|
||||||
measured->unwrappedDimensions.width = measuredWidth;
|
measured->unwrappedDimensions.width = measuredWidth;
|
||||||
|
@ -1760,16 +1774,15 @@ bool Clay__ElementHasConfig(Clay_LayoutElement *layoutElement, Clay__ElementConf
|
||||||
void Clay__UpdateAspectRatioBox(Clay_LayoutElement *layoutElement) {
|
void Clay__UpdateAspectRatioBox(Clay_LayoutElement *layoutElement) {
|
||||||
for (int32_t j = 0; j < layoutElement->elementConfigs.length; j++) {
|
for (int32_t j = 0; j < layoutElement->elementConfigs.length; j++) {
|
||||||
Clay_ElementConfig *config = Clay__ElementConfigArraySlice_Get(&layoutElement->elementConfigs, j);
|
Clay_ElementConfig *config = Clay__ElementConfigArraySlice_Get(&layoutElement->elementConfigs, j);
|
||||||
if (config->type == CLAY__ELEMENT_CONFIG_TYPE_IMAGE) {
|
if (config->type == CLAY__ELEMENT_CONFIG_TYPE_ASPECT) {
|
||||||
Clay_ImageElementConfig *imageConfig = config->config.imageElementConfig;
|
Clay_AspectRatioElementConfig *aspectConfig = config->config.aspectRatioElementConfig;
|
||||||
if (imageConfig->sourceDimensions.width == 0 || imageConfig->sourceDimensions.height == 0) {
|
if (aspectConfig->aspectRatio == 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
float aspect = imageConfig->sourceDimensions.width / imageConfig->sourceDimensions.height;
|
|
||||||
if (layoutElement->dimensions.width == 0 && layoutElement->dimensions.height != 0) {
|
if (layoutElement->dimensions.width == 0 && layoutElement->dimensions.height != 0) {
|
||||||
layoutElement->dimensions.width = layoutElement->dimensions.height * aspect;
|
layoutElement->dimensions.width = layoutElement->dimensions.height * aspectConfig->aspectRatio;
|
||||||
} else if (layoutElement->dimensions.width != 0 && layoutElement->dimensions.height == 0) {
|
} else if (layoutElement->dimensions.width != 0 && layoutElement->dimensions.height == 0) {
|
||||||
layoutElement->dimensions.height = layoutElement->dimensions.height * (1 / aspect);
|
layoutElement->dimensions.height = layoutElement->dimensions.width * (1 / aspectConfig->aspectRatio);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1783,13 +1796,13 @@ void Clay__CloseElement(void) {
|
||||||
}
|
}
|
||||||
Clay_LayoutElement *openLayoutElement = Clay__GetOpenLayoutElement();
|
Clay_LayoutElement *openLayoutElement = Clay__GetOpenLayoutElement();
|
||||||
Clay_LayoutConfig *layoutConfig = openLayoutElement->layoutConfig;
|
Clay_LayoutConfig *layoutConfig = openLayoutElement->layoutConfig;
|
||||||
bool elementHasScrollHorizontal = false;
|
bool elementHasClipHorizontal = false;
|
||||||
bool elementHasScrollVertical = false;
|
bool elementHasClipVertical = false;
|
||||||
for (int32_t i = 0; i < openLayoutElement->elementConfigs.length; i++) {
|
for (int32_t i = 0; i < openLayoutElement->elementConfigs.length; i++) {
|
||||||
Clay_ElementConfig *config = Clay__ElementConfigArraySlice_Get(&openLayoutElement->elementConfigs, i);
|
Clay_ElementConfig *config = Clay__ElementConfigArraySlice_Get(&openLayoutElement->elementConfigs, i);
|
||||||
if (config->type == CLAY__ELEMENT_CONFIG_TYPE_CLIP) {
|
if (config->type == CLAY__ELEMENT_CONFIG_TYPE_CLIP) {
|
||||||
elementHasScrollHorizontal = config->config.clipElementConfig->horizontal;
|
elementHasClipHorizontal = config->config.clipElementConfig->horizontal;
|
||||||
elementHasScrollVertical = config->config.clipElementConfig->vertical;
|
elementHasClipVertical = config->config.clipElementConfig->vertical;
|
||||||
context->openClipElementStack.length--;
|
context->openClipElementStack.length--;
|
||||||
break;
|
break;
|
||||||
} else if (config->type == CLAY__ELEMENT_CONFIG_TYPE_FLOATING) {
|
} else if (config->type == CLAY__ELEMENT_CONFIG_TYPE_FLOATING) {
|
||||||
|
@ -1810,19 +1823,21 @@ void Clay__CloseElement(void) {
|
||||||
Clay_LayoutElement *child = Clay_LayoutElementArray_Get(&context->layoutElements, childIndex);
|
Clay_LayoutElement *child = Clay_LayoutElementArray_Get(&context->layoutElements, childIndex);
|
||||||
openLayoutElement->dimensions.width += child->dimensions.width;
|
openLayoutElement->dimensions.width += child->dimensions.width;
|
||||||
openLayoutElement->dimensions.height = CLAY__MAX(openLayoutElement->dimensions.height, child->dimensions.height + topBottomPadding);
|
openLayoutElement->dimensions.height = CLAY__MAX(openLayoutElement->dimensions.height, child->dimensions.height + topBottomPadding);
|
||||||
// Minimum size of child elements doesn't matter to scroll containers as they can shrink and hide their contents
|
// Minimum size of child elements doesn't matter to clip containers as they can shrink and hide their contents
|
||||||
if (!elementHasScrollHorizontal) {
|
if (!elementHasClipHorizontal) {
|
||||||
openLayoutElement->minDimensions.width += child->minDimensions.width;
|
openLayoutElement->minDimensions.width += child->minDimensions.width;
|
||||||
}
|
}
|
||||||
if (!elementHasScrollVertical) {
|
if (!elementHasClipVertical) {
|
||||||
openLayoutElement->minDimensions.height = CLAY__MAX(openLayoutElement->minDimensions.height, child->minDimensions.height + topBottomPadding);
|
openLayoutElement->minDimensions.height = CLAY__MAX(openLayoutElement->minDimensions.height, child->minDimensions.height + topBottomPadding);
|
||||||
}
|
}
|
||||||
Clay__int32_tArray_Add(&context->layoutElementChildren, childIndex);
|
Clay__int32_tArray_Add(&context->layoutElementChildren, childIndex);
|
||||||
}
|
}
|
||||||
float childGap = (float)(CLAY__MAX(openLayoutElement->childrenOrTextContent.children.length - 1, 0) * layoutConfig->childGap);
|
float childGap = (float)(CLAY__MAX(openLayoutElement->childrenOrTextContent.children.length - 1, 0) * layoutConfig->childGap);
|
||||||
openLayoutElement->dimensions.width += childGap; // TODO this is technically a bug with childgap and scroll containers
|
openLayoutElement->dimensions.width += childGap;
|
||||||
|
if (!elementHasClipHorizontal) {
|
||||||
openLayoutElement->minDimensions.width += childGap;
|
openLayoutElement->minDimensions.width += childGap;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else if (layoutConfig->layoutDirection == CLAY_TOP_TO_BOTTOM) {
|
else if (layoutConfig->layoutDirection == CLAY_TOP_TO_BOTTOM) {
|
||||||
openLayoutElement->dimensions.height = topBottomPadding;
|
openLayoutElement->dimensions.height = topBottomPadding;
|
||||||
openLayoutElement->minDimensions.height = topBottomPadding;
|
openLayoutElement->minDimensions.height = topBottomPadding;
|
||||||
|
@ -1831,19 +1846,21 @@ void Clay__CloseElement(void) {
|
||||||
Clay_LayoutElement *child = Clay_LayoutElementArray_Get(&context->layoutElements, childIndex);
|
Clay_LayoutElement *child = Clay_LayoutElementArray_Get(&context->layoutElements, childIndex);
|
||||||
openLayoutElement->dimensions.height += child->dimensions.height;
|
openLayoutElement->dimensions.height += child->dimensions.height;
|
||||||
openLayoutElement->dimensions.width = CLAY__MAX(openLayoutElement->dimensions.width, child->dimensions.width + leftRightPadding);
|
openLayoutElement->dimensions.width = CLAY__MAX(openLayoutElement->dimensions.width, child->dimensions.width + leftRightPadding);
|
||||||
// Minimum size of child elements doesn't matter to scroll containers as they can shrink and hide their contents
|
// Minimum size of child elements doesn't matter to clip containers as they can shrink and hide their contents
|
||||||
if (!elementHasScrollVertical) {
|
if (!elementHasClipVertical) {
|
||||||
openLayoutElement->minDimensions.height += child->minDimensions.height;
|
openLayoutElement->minDimensions.height += child->minDimensions.height;
|
||||||
}
|
}
|
||||||
if (!elementHasScrollHorizontal) {
|
if (!elementHasClipHorizontal) {
|
||||||
openLayoutElement->minDimensions.width = CLAY__MAX(openLayoutElement->minDimensions.width, child->minDimensions.width + leftRightPadding);
|
openLayoutElement->minDimensions.width = CLAY__MAX(openLayoutElement->minDimensions.width, child->minDimensions.width + leftRightPadding);
|
||||||
}
|
}
|
||||||
Clay__int32_tArray_Add(&context->layoutElementChildren, childIndex);
|
Clay__int32_tArray_Add(&context->layoutElementChildren, childIndex);
|
||||||
}
|
}
|
||||||
float childGap = (float)(CLAY__MAX(openLayoutElement->childrenOrTextContent.children.length - 1, 0) * layoutConfig->childGap);
|
float childGap = (float)(CLAY__MAX(openLayoutElement->childrenOrTextContent.children.length - 1, 0) * layoutConfig->childGap);
|
||||||
openLayoutElement->dimensions.height += childGap; // TODO this is technically a bug with childgap and scroll containers
|
openLayoutElement->dimensions.height += childGap;
|
||||||
|
if (!elementHasClipVertical) {
|
||||||
openLayoutElement->minDimensions.height += childGap;
|
openLayoutElement->minDimensions.height += childGap;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
context->layoutElementChildrenBuffer.length -= openLayoutElement->childrenOrTextContent.children.length;
|
context->layoutElementChildrenBuffer.length -= openLayoutElement->childrenOrTextContent.children.length;
|
||||||
|
|
||||||
|
@ -2048,7 +2065,10 @@ void Clay__ConfigureOpenElementPtr(const Clay_ElementDeclaration *declaration) {
|
||||||
}
|
}
|
||||||
if (declaration->image.imageData) {
|
if (declaration->image.imageData) {
|
||||||
Clay__AttachElementConfig(CLAY__INIT(Clay_ElementConfigUnion) { .imageElementConfig = Clay__StoreImageElementConfig(declaration->image) }, CLAY__ELEMENT_CONFIG_TYPE_IMAGE);
|
Clay__AttachElementConfig(CLAY__INIT(Clay_ElementConfigUnion) { .imageElementConfig = Clay__StoreImageElementConfig(declaration->image) }, CLAY__ELEMENT_CONFIG_TYPE_IMAGE);
|
||||||
Clay__int32_tArray_Add(&context->imageElementPointers, context->layoutElements.length - 1);
|
}
|
||||||
|
if (declaration->aspectRatio.aspectRatio > 0) {
|
||||||
|
Clay__AttachElementConfig(CLAY__INIT(Clay_ElementConfigUnion) { .aspectRatioElementConfig = Clay__StoreAspectRatioElementConfig(declaration->aspectRatio) }, CLAY__ELEMENT_CONFIG_TYPE_ASPECT);
|
||||||
|
Clay__int32_tArray_Add(&context->aspectRatioElementIndexes, context->layoutElements.length - 1);
|
||||||
}
|
}
|
||||||
if (declaration->floating.attachTo != CLAY_ATTACH_TO_NONE) {
|
if (declaration->floating.attachTo != CLAY_ATTACH_TO_NONE) {
|
||||||
Clay_FloatingElementConfig floatingConfig = declaration->floating;
|
Clay_FloatingElementConfig floatingConfig = declaration->floating;
|
||||||
|
@ -2145,6 +2165,7 @@ void Clay__InitializeEphemeralMemory(Clay_Context* context) {
|
||||||
context->layoutConfigs = Clay__LayoutConfigArray_Allocate_Arena(maxElementCount, arena);
|
context->layoutConfigs = Clay__LayoutConfigArray_Allocate_Arena(maxElementCount, arena);
|
||||||
context->elementConfigs = Clay__ElementConfigArray_Allocate_Arena(maxElementCount, arena);
|
context->elementConfigs = Clay__ElementConfigArray_Allocate_Arena(maxElementCount, arena);
|
||||||
context->textElementConfigs = Clay__TextElementConfigArray_Allocate_Arena(maxElementCount, arena);
|
context->textElementConfigs = Clay__TextElementConfigArray_Allocate_Arena(maxElementCount, arena);
|
||||||
|
context->aspectRatioElementConfigs = Clay__AspectRatioElementConfigArray_Allocate_Arena(maxElementCount, arena);
|
||||||
context->imageElementConfigs = Clay__ImageElementConfigArray_Allocate_Arena(maxElementCount, arena);
|
context->imageElementConfigs = Clay__ImageElementConfigArray_Allocate_Arena(maxElementCount, arena);
|
||||||
context->floatingElementConfigs = Clay__FloatingElementConfigArray_Allocate_Arena(maxElementCount, arena);
|
context->floatingElementConfigs = Clay__FloatingElementConfigArray_Allocate_Arena(maxElementCount, arena);
|
||||||
context->clipElementConfigs = Clay__ClipElementConfigArray_Allocate_Arena(maxElementCount, arena);
|
context->clipElementConfigs = Clay__ClipElementConfigArray_Allocate_Arena(maxElementCount, arena);
|
||||||
|
@ -2159,7 +2180,7 @@ void Clay__InitializeEphemeralMemory(Clay_Context* context) {
|
||||||
context->layoutElementChildren = Clay__int32_tArray_Allocate_Arena(maxElementCount, arena);
|
context->layoutElementChildren = Clay__int32_tArray_Allocate_Arena(maxElementCount, arena);
|
||||||
context->openLayoutElementStack = Clay__int32_tArray_Allocate_Arena(maxElementCount, arena);
|
context->openLayoutElementStack = Clay__int32_tArray_Allocate_Arena(maxElementCount, arena);
|
||||||
context->textElementData = Clay__TextElementDataArray_Allocate_Arena(maxElementCount, arena);
|
context->textElementData = Clay__TextElementDataArray_Allocate_Arena(maxElementCount, arena);
|
||||||
context->imageElementPointers = Clay__int32_tArray_Allocate_Arena(maxElementCount, arena);
|
context->aspectRatioElementIndexes = Clay__int32_tArray_Allocate_Arena(maxElementCount, arena);
|
||||||
context->renderCommands = Clay_RenderCommandArray_Allocate_Arena(maxElementCount, arena);
|
context->renderCommands = Clay_RenderCommandArray_Allocate_Arena(maxElementCount, arena);
|
||||||
context->treeNodeVisited = Clay__boolArray_Allocate_Arena(maxElementCount, arena);
|
context->treeNodeVisited = Clay__boolArray_Allocate_Arena(maxElementCount, arena);
|
||||||
context->treeNodeVisited.length = context->treeNodeVisited.capacity; // This array is accessed directly rather than behaving as a list
|
context->treeNodeVisited.length = context->treeNodeVisited.capacity; // This array is accessed directly rather than behaving as a list
|
||||||
|
@ -2248,7 +2269,7 @@ void Clay__SizeContainersAlongAxis(bool xAxis) {
|
||||||
if (childSizing.type != CLAY__SIZING_TYPE_PERCENT
|
if (childSizing.type != CLAY__SIZING_TYPE_PERCENT
|
||||||
&& childSizing.type != CLAY__SIZING_TYPE_FIXED
|
&& childSizing.type != CLAY__SIZING_TYPE_FIXED
|
||||||
&& (!Clay__ElementHasConfig(childElement, CLAY__ELEMENT_CONFIG_TYPE_TEXT) || (Clay__FindElementConfigWithType(childElement, CLAY__ELEMENT_CONFIG_TYPE_TEXT).textElementConfig->wrapMode == CLAY_TEXT_WRAP_WORDS)) // todo too many loops
|
&& (!Clay__ElementHasConfig(childElement, CLAY__ELEMENT_CONFIG_TYPE_TEXT) || (Clay__FindElementConfigWithType(childElement, CLAY__ELEMENT_CONFIG_TYPE_TEXT).textElementConfig->wrapMode == CLAY_TEXT_WRAP_WORDS)) // todo too many loops
|
||||||
&& (xAxis || !Clay__ElementHasConfig(childElement, CLAY__ELEMENT_CONFIG_TYPE_IMAGE))
|
// && (xAxis || !Clay__ElementHasConfig(childElement, CLAY__ELEMENT_CONFIG_TYPE_ASPECT))
|
||||||
) {
|
) {
|
||||||
Clay__int32_tArray_Add(&resizableContainerBuffer, childElementIndex);
|
Clay__int32_tArray_Add(&resizableContainerBuffer, childElementIndex);
|
||||||
}
|
}
|
||||||
|
@ -2287,9 +2308,9 @@ void Clay__SizeContainersAlongAxis(bool xAxis) {
|
||||||
// The content is too large, compress the children as much as possible
|
// The content is too large, compress the children as much as possible
|
||||||
if (sizeToDistribute < 0) {
|
if (sizeToDistribute < 0) {
|
||||||
// If the parent clips content in this axis direction, don't compress children, just leave them alone
|
// If the parent clips content in this axis direction, don't compress children, just leave them alone
|
||||||
Clay_ClipElementConfig *scrollElementConfig = Clay__FindElementConfigWithType(parent, CLAY__ELEMENT_CONFIG_TYPE_CLIP).clipElementConfig;
|
Clay_ClipElementConfig *clipElementConfig = Clay__FindElementConfigWithType(parent, CLAY__ELEMENT_CONFIG_TYPE_CLIP).clipElementConfig;
|
||||||
if (scrollElementConfig) {
|
if (clipElementConfig) {
|
||||||
if (((xAxis && scrollElementConfig->horizontal) || (!xAxis && scrollElementConfig->vertical))) {
|
if (((xAxis && clipElementConfig->horizontal) || (!xAxis && clipElementConfig->vertical))) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2382,10 +2403,6 @@ void Clay__SizeContainersAlongAxis(bool xAxis) {
|
||||||
float minSize = xAxis ? childElement->minDimensions.width : childElement->minDimensions.height;
|
float minSize = xAxis ? childElement->minDimensions.width : childElement->minDimensions.height;
|
||||||
float *childSize = xAxis ? &childElement->dimensions.width : &childElement->dimensions.height;
|
float *childSize = xAxis ? &childElement->dimensions.width : &childElement->dimensions.height;
|
||||||
|
|
||||||
if (!xAxis && Clay__ElementHasConfig(childElement, CLAY__ELEMENT_CONFIG_TYPE_IMAGE)) {
|
|
||||||
continue; // Currently we don't support resizing aspect ratio images on the Y axis because it would break the ratio
|
|
||||||
}
|
|
||||||
|
|
||||||
float maxSize = parentSize - parentPadding;
|
float maxSize = parentSize - parentPadding;
|
||||||
// If we're laying out the children of a scroll panel, grow containers expand to the size of the inner content, not the outer container
|
// If we're laying out the children of a scroll panel, grow containers expand to the size of the inner content, not the outer container
|
||||||
if (Clay__ElementHasConfig(parent, CLAY__ELEMENT_CONFIG_TYPE_CLIP)) {
|
if (Clay__ElementHasConfig(parent, CLAY__ELEMENT_CONFIG_TYPE_CLIP)) {
|
||||||
|
@ -2500,7 +2517,7 @@ void Clay__CalculateFinalLayout(void) {
|
||||||
// measuredWord->length == 0 means a newline character
|
// measuredWord->length == 0 means a newline character
|
||||||
else if (measuredWord->length == 0 || lineWidth + measuredWord->width > containerElement->dimensions.width) {
|
else if (measuredWord->length == 0 || lineWidth + measuredWord->width > containerElement->dimensions.width) {
|
||||||
// Wrapped text lines list has overflowed, just render out the line
|
// Wrapped text lines list has overflowed, just render out the line
|
||||||
bool finalCharIsSpace = textElementData->text.chars[lineStartOffset + lineLengthChars - 1] == ' ';
|
bool finalCharIsSpace = textElementData->text.chars[CLAY__MAX(lineStartOffset + lineLengthChars - 1, 0)] == ' ';
|
||||||
Clay__WrappedTextLineArray_Add(&context->wrappedTextLines, CLAY__INIT(Clay__WrappedTextLine) { { lineWidth + (finalCharIsSpace ? -spaceWidth : 0), lineHeight }, { .length = lineLengthChars + (finalCharIsSpace ? -1 : 0), .chars = &textElementData->text.chars[lineStartOffset] } });
|
Clay__WrappedTextLineArray_Add(&context->wrappedTextLines, CLAY__INIT(Clay__WrappedTextLine) { { lineWidth + (finalCharIsSpace ? -spaceWidth : 0), lineHeight }, { .length = lineLengthChars + (finalCharIsSpace ? -1 : 0), .chars = &textElementData->text.chars[lineStartOffset] } });
|
||||||
textElementData->wrappedLines.length++;
|
textElementData->wrappedLines.length++;
|
||||||
if (lineLengthChars == 0 || measuredWord->length == 0) {
|
if (lineLengthChars == 0 || measuredWord->length == 0) {
|
||||||
|
@ -2510,26 +2527,27 @@ void Clay__CalculateFinalLayout(void) {
|
||||||
lineLengthChars = 0;
|
lineLengthChars = 0;
|
||||||
lineStartOffset = measuredWord->startOffset;
|
lineStartOffset = measuredWord->startOffset;
|
||||||
} else {
|
} else {
|
||||||
lineWidth += measuredWord->width;
|
lineWidth += measuredWord->width + textConfig->letterSpacing;
|
||||||
lineLengthChars += measuredWord->length;
|
lineLengthChars += measuredWord->length;
|
||||||
wordIndex = measuredWord->next;
|
wordIndex = measuredWord->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (lineLengthChars > 0) {
|
if (lineLengthChars > 0) {
|
||||||
Clay__WrappedTextLineArray_Add(&context->wrappedTextLines, CLAY__INIT(Clay__WrappedTextLine) { { lineWidth, lineHeight }, {.length = lineLengthChars, .chars = &textElementData->text.chars[lineStartOffset] } });
|
Clay__WrappedTextLineArray_Add(&context->wrappedTextLines, CLAY__INIT(Clay__WrappedTextLine) { { lineWidth - textConfig->letterSpacing, lineHeight }, {.length = lineLengthChars, .chars = &textElementData->text.chars[lineStartOffset] } });
|
||||||
textElementData->wrappedLines.length++;
|
textElementData->wrappedLines.length++;
|
||||||
}
|
}
|
||||||
containerElement->dimensions.height = lineHeight * (float)textElementData->wrappedLines.length;
|
containerElement->dimensions.height = lineHeight * (float)textElementData->wrappedLines.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scale vertical image heights according to aspect ratio
|
// Scale vertical heights according to aspect ratio
|
||||||
for (int32_t i = 0; i < context->imageElementPointers.length; ++i) {
|
for (int32_t i = 0; i < context->aspectRatioElementIndexes.length; ++i) {
|
||||||
Clay_LayoutElement* imageElement = Clay_LayoutElementArray_Get(&context->layoutElements, Clay__int32_tArray_GetValue(&context->imageElementPointers, i));
|
Clay_LayoutElement* aspectElement = Clay_LayoutElementArray_Get(&context->layoutElements, Clay__int32_tArray_GetValue(&context->aspectRatioElementIndexes, i));
|
||||||
Clay_ImageElementConfig *config = Clay__FindElementConfigWithType(imageElement, CLAY__ELEMENT_CONFIG_TYPE_IMAGE).imageElementConfig;
|
Clay_AspectRatioElementConfig *config = Clay__FindElementConfigWithType(aspectElement, CLAY__ELEMENT_CONFIG_TYPE_ASPECT).aspectRatioElementConfig;
|
||||||
imageElement->dimensions.height = (config->sourceDimensions.height / CLAY__MAX(config->sourceDimensions.width, 1)) * imageElement->dimensions.width;
|
aspectElement->dimensions.height = (1 / config->aspectRatio) * aspectElement->dimensions.width;
|
||||||
|
aspectElement->layoutConfig->sizing.height.size.minMax.max = aspectElement->dimensions.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Propagate effect of text wrapping, image aspect scaling etc. on height of parents
|
// Propagate effect of text wrapping, aspect scaling etc. on height of parents
|
||||||
Clay__LayoutElementTreeNodeArray dfsBuffer = context->layoutElementTreeNodeArray1;
|
Clay__LayoutElementTreeNodeArray dfsBuffer = context->layoutElementTreeNodeArray1;
|
||||||
dfsBuffer.length = 0;
|
dfsBuffer.length = 0;
|
||||||
for (int32_t i = 0; i < context->layoutElementTreeRoots.length; ++i) {
|
for (int32_t i = 0; i < context->layoutElementTreeRoots.length; ++i) {
|
||||||
|
@ -2580,6 +2598,13 @@ void Clay__CalculateFinalLayout(void) {
|
||||||
// Calculate sizing along the Y axis
|
// Calculate sizing along the Y axis
|
||||||
Clay__SizeContainersAlongAxis(false);
|
Clay__SizeContainersAlongAxis(false);
|
||||||
|
|
||||||
|
// Scale horizontal widths according to aspect ratio
|
||||||
|
for (int32_t i = 0; i < context->aspectRatioElementIndexes.length; ++i) {
|
||||||
|
Clay_LayoutElement* aspectElement = Clay_LayoutElementArray_Get(&context->layoutElements, Clay__int32_tArray_GetValue(&context->aspectRatioElementIndexes, i));
|
||||||
|
Clay_AspectRatioElementConfig *config = Clay__FindElementConfigWithType(aspectElement, CLAY__ELEMENT_CONFIG_TYPE_ASPECT).aspectRatioElementConfig;
|
||||||
|
aspectElement->dimensions.width = config->aspectRatio * aspectElement->dimensions.height;
|
||||||
|
}
|
||||||
|
|
||||||
// Sort tree roots by z-index
|
// Sort tree roots by z-index
|
||||||
int32_t sortMax = context->layoutElementTreeRoots.length - 1;
|
int32_t sortMax = context->layoutElementTreeRoots.length - 1;
|
||||||
while (sortMax > 0) { // todo dumb bubble sort
|
while (sortMax > 0) { // todo dumb bubble sort
|
||||||
|
@ -2670,7 +2695,6 @@ void Clay__CalculateFinalLayout(void) {
|
||||||
if (clipConfig->vertical) {
|
if (clipConfig->vertical) {
|
||||||
rootPosition.y += clipConfig->childOffset.y;
|
rootPosition.y += clipConfig->childOffset.y;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
Clay__AddRenderCommand(CLAY__INIT(Clay_RenderCommand) {
|
Clay__AddRenderCommand(CLAY__INIT(Clay_RenderCommand) {
|
||||||
.boundingBox = clipHashMapItem->boundingBox,
|
.boundingBox = clipHashMapItem->boundingBox,
|
||||||
|
@ -2776,6 +2800,7 @@ void Clay__CalculateFinalLayout(void) {
|
||||||
// Culling - Don't bother to generate render commands for rectangles entirely outside the screen - this won't stop their children from being rendered if they overflow
|
// Culling - Don't bother to generate render commands for rectangles entirely outside the screen - this won't stop their children from being rendered if they overflow
|
||||||
bool shouldRender = !offscreen;
|
bool shouldRender = !offscreen;
|
||||||
switch (elementConfig->type) {
|
switch (elementConfig->type) {
|
||||||
|
case CLAY__ELEMENT_CONFIG_TYPE_ASPECT:
|
||||||
case CLAY__ELEMENT_CONFIG_TYPE_FLOATING:
|
case CLAY__ELEMENT_CONFIG_TYPE_FLOATING:
|
||||||
case CLAY__ELEMENT_CONFIG_TYPE_SHARED:
|
case CLAY__ELEMENT_CONFIG_TYPE_SHARED:
|
||||||
case CLAY__ELEMENT_CONFIG_TYPE_BORDER: {
|
case CLAY__ELEMENT_CONFIG_TYPE_BORDER: {
|
||||||
|
@ -2798,7 +2823,6 @@ void Clay__CalculateFinalLayout(void) {
|
||||||
.image = {
|
.image = {
|
||||||
.backgroundColor = sharedConfig->backgroundColor,
|
.backgroundColor = sharedConfig->backgroundColor,
|
||||||
.cornerRadius = sharedConfig->cornerRadius,
|
.cornerRadius = sharedConfig->cornerRadius,
|
||||||
.sourceDimensions = elementConfig->config.imageElementConfig->sourceDimensions,
|
|
||||||
.imageData = elementConfig->config.imageElementConfig->imageData,
|
.imageData = elementConfig->config.imageElementConfig->imageData,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -2907,6 +2931,7 @@ void Clay__CalculateFinalLayout(void) {
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
currentElementTreeNode->nextChildOffset.x += extraSpace;
|
currentElementTreeNode->nextChildOffset.x += extraSpace;
|
||||||
|
extraSpace = CLAY__MAX(0, extraSpace);
|
||||||
} else {
|
} else {
|
||||||
for (int32_t i = 0; i < currentElement->childrenOrTextContent.children.length; ++i) {
|
for (int32_t i = 0; i < currentElement->childrenOrTextContent.children.length; ++i) {
|
||||||
Clay_LayoutElement *childElement = Clay_LayoutElementArray_Get(&context->layoutElements, currentElement->childrenOrTextContent.children.elements[i]);
|
Clay_LayoutElement *childElement = Clay_LayoutElementArray_Get(&context->layoutElements, currentElement->childrenOrTextContent.children.elements[i]);
|
||||||
|
@ -2920,6 +2945,7 @@ void Clay__CalculateFinalLayout(void) {
|
||||||
case CLAY_ALIGN_Y_CENTER: extraSpace /= 2; break;
|
case CLAY_ALIGN_Y_CENTER: extraSpace /= 2; break;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
|
extraSpace = CLAY__MAX(0, extraSpace);
|
||||||
currentElementTreeNode->nextChildOffset.y += extraSpace;
|
currentElementTreeNode->nextChildOffset.y += extraSpace;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3097,6 +3123,7 @@ Clay__DebugElementConfigTypeLabelConfig Clay__DebugGetElementConfigTypeLabel(Cla
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case CLAY__ELEMENT_CONFIG_TYPE_SHARED: return CLAY__INIT(Clay__DebugElementConfigTypeLabelConfig) { CLAY_STRING("Shared"), {243,134,48,255} };
|
case CLAY__ELEMENT_CONFIG_TYPE_SHARED: return CLAY__INIT(Clay__DebugElementConfigTypeLabelConfig) { CLAY_STRING("Shared"), {243,134,48,255} };
|
||||||
case CLAY__ELEMENT_CONFIG_TYPE_TEXT: return CLAY__INIT(Clay__DebugElementConfigTypeLabelConfig) { CLAY_STRING("Text"), {105,210,231,255} };
|
case CLAY__ELEMENT_CONFIG_TYPE_TEXT: return CLAY__INIT(Clay__DebugElementConfigTypeLabelConfig) { CLAY_STRING("Text"), {105,210,231,255} };
|
||||||
|
case CLAY__ELEMENT_CONFIG_TYPE_ASPECT: return CLAY__INIT(Clay__DebugElementConfigTypeLabelConfig) { CLAY_STRING("Aspect"), {101,149,194,255} };
|
||||||
case CLAY__ELEMENT_CONFIG_TYPE_IMAGE: return CLAY__INIT(Clay__DebugElementConfigTypeLabelConfig) { CLAY_STRING("Image"), {121,189,154,255} };
|
case CLAY__ELEMENT_CONFIG_TYPE_IMAGE: return CLAY__INIT(Clay__DebugElementConfigTypeLabelConfig) { CLAY_STRING("Image"), {121,189,154,255} };
|
||||||
case CLAY__ELEMENT_CONFIG_TYPE_FLOATING: return CLAY__INIT(Clay__DebugElementConfigTypeLabelConfig) { CLAY_STRING("Floating"), {250,105,0,255} };
|
case CLAY__ELEMENT_CONFIG_TYPE_FLOATING: return CLAY__INIT(Clay__DebugElementConfigTypeLabelConfig) { CLAY_STRING("Floating"), {250,105,0,255} };
|
||||||
case CLAY__ELEMENT_CONFIG_TYPE_CLIP: return CLAY__INIT(Clay__DebugElementConfigTypeLabelConfig) {CLAY_STRING("Scroll"), {242, 196, 90, 255} };
|
case CLAY__ELEMENT_CONFIG_TYPE_CLIP: return CLAY__INIT(Clay__DebugElementConfigTypeLabelConfig) {CLAY_STRING("Scroll"), {242, 196, 90, 255} };
|
||||||
|
@ -3581,21 +3608,25 @@ void Clay__RenderDebugView(void) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case CLAY__ELEMENT_CONFIG_TYPE_ASPECT: {
|
||||||
|
Clay_AspectRatioElementConfig *aspectRatioConfig = elementConfig->config.aspectRatioElementConfig;
|
||||||
|
CLAY({ .id = CLAY_ID("Clay__DebugViewElementInfoAspectRatioBody"), .layout = { .padding = attributeConfigPadding, .childGap = 8, .layoutDirection = CLAY_TOP_TO_BOTTOM } }) {
|
||||||
|
CLAY_TEXT(CLAY_STRING("Aspect Ratio"), infoTitleConfig);
|
||||||
|
// Aspect Ratio
|
||||||
|
CLAY_TEXT(Clay__IntToString(aspectRatioConfig->aspectRatio), infoTextConfig);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
case CLAY__ELEMENT_CONFIG_TYPE_IMAGE: {
|
case CLAY__ELEMENT_CONFIG_TYPE_IMAGE: {
|
||||||
Clay_ImageElementConfig *imageConfig = elementConfig->config.imageElementConfig;
|
Clay_ImageElementConfig *imageConfig = elementConfig->config.imageElementConfig;
|
||||||
CLAY({ .id = CLAY_ID("Clay__DebugViewElementInfoImageBody"), .layout = { .padding = attributeConfigPadding, .childGap = 8, .layoutDirection = CLAY_TOP_TO_BOTTOM } }) {
|
Clay_AspectRatioElementConfig aspectConfig = { 1 };
|
||||||
// .sourceDimensions
|
if (Clay__ElementHasConfig(selectedItem->layoutElement, CLAY__ELEMENT_CONFIG_TYPE_ASPECT)) {
|
||||||
CLAY_TEXT(CLAY_STRING("Source Dimensions"), infoTitleConfig);
|
aspectConfig = *Clay__FindElementConfigWithType(selectedItem->layoutElement, CLAY__ELEMENT_CONFIG_TYPE_ASPECT).aspectRatioElementConfig;
|
||||||
CLAY({ .id = CLAY_ID("Clay__DebugViewElementInfoImageDimensions") }) {
|
|
||||||
CLAY_TEXT(CLAY_STRING("{ width: "), infoTextConfig);
|
|
||||||
CLAY_TEXT(Clay__IntToString(imageConfig->sourceDimensions.width), infoTextConfig);
|
|
||||||
CLAY_TEXT(CLAY_STRING(", height: "), infoTextConfig);
|
|
||||||
CLAY_TEXT(Clay__IntToString(imageConfig->sourceDimensions.height), infoTextConfig);
|
|
||||||
CLAY_TEXT(CLAY_STRING(" }"), infoTextConfig);
|
|
||||||
}
|
}
|
||||||
|
CLAY({ .id = CLAY_ID("Clay__DebugViewElementInfoImageBody"), .layout = { .padding = attributeConfigPadding, .childGap = 8, .layoutDirection = CLAY_TOP_TO_BOTTOM } }) {
|
||||||
// Image Preview
|
// Image Preview
|
||||||
CLAY_TEXT(CLAY_STRING("Preview"), infoTitleConfig);
|
CLAY_TEXT(CLAY_STRING("Preview"), infoTitleConfig);
|
||||||
CLAY({ .layout = { .sizing = { .width = CLAY_SIZING_GROW(0, imageConfig->sourceDimensions.width) }}, .image = *imageConfig }) {}
|
CLAY({ .layout = { .sizing = { .width = CLAY_SIZING_GROW(64, 128), .height = CLAY_SIZING_GROW(64, 128) }}, .aspectRatio = aspectConfig, .image = *imageConfig }) {}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -3793,7 +3824,7 @@ Clay__Warning *Clay__WarningArray_Add(Clay__WarningArray *array, Clay__Warning i
|
||||||
void* Clay__Array_Allocate_Arena(int32_t capacity, uint32_t itemSize, Clay_Arena *arena)
|
void* Clay__Array_Allocate_Arena(int32_t capacity, uint32_t itemSize, Clay_Arena *arena)
|
||||||
{
|
{
|
||||||
size_t totalSizeBytes = capacity * itemSize;
|
size_t totalSizeBytes = capacity * itemSize;
|
||||||
uintptr_t nextAllocOffset = arena->nextAllocation + (64 - (arena->nextAllocation % 64));
|
uintptr_t nextAllocOffset = arena->nextAllocation + ((64 - (arena->nextAllocation % 64)) & 63);
|
||||||
if (nextAllocOffset + totalSizeBytes <= arena->capacity) {
|
if (nextAllocOffset + totalSizeBytes <= arena->capacity) {
|
||||||
arena->nextAllocation = nextAllocOffset + totalSizeBytes;
|
arena->nextAllocation = nextAllocOffset + totalSizeBytes;
|
||||||
return (void*)((uintptr_t)arena->memory + (uintptr_t)nextAllocOffset);
|
return (void*)((uintptr_t)arena->memory + (uintptr_t)nextAllocOffset);
|
||||||
|
@ -3913,7 +3944,7 @@ void Clay_SetPointerState(Clay_Vector2 position, bool isPointerDown) {
|
||||||
Clay_BoundingBox elementBox = mapItem->boundingBox;
|
Clay_BoundingBox elementBox = mapItem->boundingBox;
|
||||||
elementBox.x -= root->pointerOffset.x;
|
elementBox.x -= root->pointerOffset.x;
|
||||||
elementBox.y -= root->pointerOffset.y;
|
elementBox.y -= root->pointerOffset.y;
|
||||||
if ((Clay__PointIsInsideRect(position, elementBox)) && (clipElementId == 0 || (Clay__PointIsInsideRect(position, clipItem->boundingBox)))) {
|
if ((Clay__PointIsInsideRect(position, elementBox)) && (clipElementId == 0 || (Clay__PointIsInsideRect(position, clipItem->boundingBox)) || context->externalScrollHandlingEnabled)) {
|
||||||
if (mapItem->onHoverFunction) {
|
if (mapItem->onHoverFunction) {
|
||||||
mapItem->onHoverFunction(mapItem->elementId, context->pointerInfo, mapItem->hoverFunctionUserData);
|
mapItem->onHoverFunction(mapItem->elementId, context->pointerInfo, mapItem->hoverFunctionUserData);
|
||||||
}
|
}
|
||||||
|
@ -3961,6 +3992,10 @@ void Clay_SetPointerState(Clay_Vector2 position, bool isPointerDown) {
|
||||||
|
|
||||||
CLAY_WASM_EXPORT("Clay_Initialize")
|
CLAY_WASM_EXPORT("Clay_Initialize")
|
||||||
Clay_Context* Clay_Initialize(Clay_Arena arena, Clay_Dimensions layoutDimensions, Clay_ErrorHandler errorHandler) {
|
Clay_Context* Clay_Initialize(Clay_Arena arena, Clay_Dimensions layoutDimensions, Clay_ErrorHandler errorHandler) {
|
||||||
|
// Cacheline align memory passed in
|
||||||
|
uintptr_t baseOffset = 64 - ((uintptr_t)arena.memory % 64);
|
||||||
|
baseOffset = baseOffset == 64 ? 0 : baseOffset;
|
||||||
|
arena.memory += baseOffset;
|
||||||
Clay_Context *context = Clay__Context_Allocate_Arena(&arena);
|
Clay_Context *context = Clay__Context_Allocate_Arena(&arena);
|
||||||
if (context == NULL) return NULL;
|
if (context == NULL) return NULL;
|
||||||
// DEFAULTS
|
// DEFAULTS
|
||||||
|
|
|
@ -55,4 +55,5 @@ add_custom_command(
|
||||||
TARGET SDL2_video_demo POST_BUILD
|
TARGET SDL2_video_demo POST_BUILD
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/resources
|
${CMAKE_CURRENT_SOURCE_DIR}/resources
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/resources)
|
${CMAKE_CURRENT_BINARY_DIR}/resources
|
||||||
|
)
|
||||||
|
|
|
@ -26,7 +26,7 @@ set_property(DIRECTORY "${sdl_SOURCE_DIR}" PROPERTY EXCLUDE_FROM_ALL TRUE)
|
||||||
FetchContent_Declare(
|
FetchContent_Declare(
|
||||||
SDL_ttf
|
SDL_ttf
|
||||||
GIT_REPOSITORY https://github.com/libsdl-org/SDL_ttf.git
|
GIT_REPOSITORY https://github.com/libsdl-org/SDL_ttf.git
|
||||||
GIT_TAG main # Slightly risky to use main branch, but it's the only one available
|
GIT_TAG release-3.2.2
|
||||||
GIT_SHALLOW TRUE
|
GIT_SHALLOW TRUE
|
||||||
GIT_PROGRESS TRUE
|
GIT_PROGRESS TRUE
|
||||||
)
|
)
|
||||||
|
@ -38,7 +38,7 @@ set_property(DIRECTORY "${sdl_ttf_SOURCE_DIR}" PROPERTY EXCLUDE_FROM_ALL TRUE)
|
||||||
FetchContent_Declare(
|
FetchContent_Declare(
|
||||||
SDL_image
|
SDL_image
|
||||||
GIT_REPOSITORY "https://github.com/libsdl-org/SDL_image.git"
|
GIT_REPOSITORY "https://github.com/libsdl-org/SDL_image.git"
|
||||||
GIT_TAG release-3.2.0 # Slightly risky to use main branch, but it's the only one available
|
GIT_TAG release-3.2.0
|
||||||
GIT_SHALLOW TRUE
|
GIT_SHALLOW TRUE
|
||||||
GIT_PROGRESS TRUE
|
GIT_PROGRESS TRUE
|
||||||
)
|
)
|
||||||
|
|
|
@ -32,6 +32,7 @@ static inline Clay_Dimensions SDL_MeasureText(Clay_StringSlice text, Clay_TextEl
|
||||||
TTF_Font *font = fonts[config->fontId];
|
TTF_Font *font = fonts[config->fontId];
|
||||||
int width, height;
|
int width, height;
|
||||||
|
|
||||||
|
TTF_SetFontSize(font, config->fontSize);
|
||||||
if (!TTF_GetStringSize(font, text.chars, text.length, &width, &height)) {
|
if (!TTF_GetStringSize(font, text.chars, text.length, &width, &height)) {
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_ERROR, "Failed to measure text: %s", SDL_GetError());
|
SDL_LogError(SDL_LOG_CATEGORY_ERROR, "Failed to measure text: %s", SDL_GetError());
|
||||||
}
|
}
|
||||||
|
@ -65,12 +66,9 @@ Clay_RenderCommandArray ClayImageSample_CreateLayout() {
|
||||||
.layout = {
|
.layout = {
|
||||||
.sizing = layoutExpand
|
.sizing = layoutExpand
|
||||||
},
|
},
|
||||||
|
.aspectRatio = { 23.0 / 42.0 },
|
||||||
.image = {
|
.image = {
|
||||||
.imageData = sample_image,
|
.imageData = sample_image,
|
||||||
.sourceDimensions = {
|
|
||||||
.width = 23,
|
|
||||||
.height = 42
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,7 +88,7 @@ void Layout() {
|
||||||
.childAlignment = { CLAY_ALIGN_X_CENTER, CLAY_ALIGN_Y_CENTER }},
|
.childAlignment = { CLAY_ALIGN_X_CENTER, CLAY_ALIGN_Y_CENTER }},
|
||||||
.border = { .color = PRIMARY, .width = 2, 2, 2, 2 }, .cornerRadius = 10
|
.border = { .color = PRIMARY, .width = 2, 2, 2, 2 }, .cornerRadius = 10
|
||||||
}) {
|
}) {
|
||||||
CLAY({ .layout = { .sizing = { CLAY_SIZING_FIXED(32), CLAY_SIZING_FIXED(32) } }, .image = { .sourceDimensions = { 32, 32 }, .imageData = "resources/check.png" }});
|
CLAY({ .layout = { .sizing = { CLAY_SIZING_FIXED(32), CLAY_SIZING_FIXED(32) } }, .image = { .imageData = "resources/check.png" }});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,6 +97,7 @@
|
||||||
{name: 'a', type: 'float' },
|
{name: 'a', type: 'float' },
|
||||||
]};
|
]};
|
||||||
let stringDefinition = { type: 'struct', members: [
|
let stringDefinition = { type: 'struct', members: [
|
||||||
|
{name: 'isStaticallyAllocated', type: 'uint32_t'},
|
||||||
{name: 'length', type: 'uint32_t' },
|
{name: 'length', type: 'uint32_t' },
|
||||||
{name: 'chars', type: 'uint32_t' },
|
{name: 'chars', type: 'uint32_t' },
|
||||||
]};
|
]};
|
||||||
|
@ -144,7 +145,6 @@
|
||||||
let imageRenderDataDefinition = { type: 'struct', members: [
|
let imageRenderDataDefinition = { type: 'struct', members: [
|
||||||
{ name: 'backgroundColor', ...colorDefinition },
|
{ name: 'backgroundColor', ...colorDefinition },
|
||||||
{ name: 'cornerRadius', ...cornerRadiusDefinition },
|
{ name: 'cornerRadius', ...cornerRadiusDefinition },
|
||||||
{ name: 'sourceDimensions', ...dimensionsDefinition },
|
|
||||||
{ name: 'imageData', type: 'uint32_t' },
|
{ name: 'imageData', type: 'uint32_t' },
|
||||||
]};
|
]};
|
||||||
let customRenderDataDefinition = { type: 'struct', members: [
|
let customRenderDataDefinition = { type: 'struct', members: [
|
||||||
|
@ -158,7 +158,7 @@
|
||||||
{ name: 'width', ...borderWidthDefinition },
|
{ name: 'width', ...borderWidthDefinition },
|
||||||
{ name: 'padding', type: 'uint16_t'}
|
{ name: 'padding', type: 'uint16_t'}
|
||||||
]};
|
]};
|
||||||
let scrollRenderDataDefinition = { type: 'struct', members: [
|
let clipRenderDataDefinition = { type: 'struct', members: [
|
||||||
{ name: 'horizontal', type: 'bool' },
|
{ name: 'horizontal', type: 'bool' },
|
||||||
{ name: 'vertical', type: 'bool' },
|
{ name: 'vertical', type: 'bool' },
|
||||||
]};
|
]};
|
||||||
|
@ -166,9 +166,10 @@
|
||||||
{ name: 'link', ...stringDefinition },
|
{ name: 'link', ...stringDefinition },
|
||||||
{ name: 'cursorPointer', type: 'uint8_t' },
|
{ name: 'cursorPointer', type: 'uint8_t' },
|
||||||
{ name: 'disablePointerEvents', type: 'uint8_t' },
|
{ name: 'disablePointerEvents', type: 'uint8_t' },
|
||||||
|
{ name: 'padding', type: 'uint16_t'}
|
||||||
]};
|
]};
|
||||||
let renderCommandDefinition = {
|
let renderCommandDefinition = {
|
||||||
name: 'CLay_RenderCommand',
|
name: 'Clay_RenderCommand',
|
||||||
type: 'struct',
|
type: 'struct',
|
||||||
members: [
|
members: [
|
||||||
{ name: 'boundingBox', type: 'struct', members: [
|
{ name: 'boundingBox', type: 'struct', members: [
|
||||||
|
@ -183,7 +184,7 @@
|
||||||
{ name: 'image', ...imageRenderDataDefinition },
|
{ name: 'image', ...imageRenderDataDefinition },
|
||||||
{ name: 'custom', ...customRenderDataDefinition },
|
{ name: 'custom', ...customRenderDataDefinition },
|
||||||
{ name: 'border', ...borderRenderDataDefinition },
|
{ name: 'border', ...borderRenderDataDefinition },
|
||||||
{ name: 'scroll', ...scrollRenderDataDefinition },
|
{ name: 'clip', ...clipRenderDataDefinition },
|
||||||
]},
|
]},
|
||||||
{ name: 'userData', type: 'uint32_t'},
|
{ name: 'userData', type: 'uint32_t'},
|
||||||
{ name: 'id', type: 'uint32_t' },
|
{ name: 'id', type: 'uint32_t' },
|
||||||
|
@ -380,7 +381,7 @@
|
||||||
memoryDataView.setFloat32(instance.exports.__heap_base.value, window.innerWidth, true);
|
memoryDataView.setFloat32(instance.exports.__heap_base.value, window.innerWidth, true);
|
||||||
memoryDataView.setFloat32(instance.exports.__heap_base.value + 4, window.innerHeight, true);
|
memoryDataView.setFloat32(instance.exports.__heap_base.value + 4, window.innerHeight, true);
|
||||||
instance.exports.Clay_Initialize(arenaAddress, instance.exports.__heap_base.value);
|
instance.exports.Clay_Initialize(arenaAddress, instance.exports.__heap_base.value);
|
||||||
instance.exports.SetScratchMemory(arenaAddress, clayScratchSpaceAddress);
|
instance.exports.SetScratchMemory(clayScratchSpaceAddress);
|
||||||
renderCommandSize = getStructTotalSize(renderCommandDefinition);
|
renderCommandSize = getStructTotalSize(renderCommandDefinition);
|
||||||
renderLoop();
|
renderLoop();
|
||||||
}
|
}
|
||||||
|
@ -425,10 +426,13 @@
|
||||||
if (!elementCache[renderCommand.id.value]) {
|
if (!elementCache[renderCommand.id.value]) {
|
||||||
let elementType = 'div';
|
let elementType = 'div';
|
||||||
switch (renderCommand.commandType.value & 0xff) {
|
switch (renderCommand.commandType.value & 0xff) {
|
||||||
|
case CLAY_RENDER_COMMAND_TYPE_TEXT:
|
||||||
case CLAY_RENDER_COMMAND_TYPE_RECTANGLE: {
|
case CLAY_RENDER_COMMAND_TYPE_RECTANGLE: {
|
||||||
// if (readStructAtAddress(renderCommand.renderData.rectangle.value, rectangleRenderDataDefinition).link.length.value > 0) { TODO reimplement links
|
if (renderCommand.userData.value !== 0) {
|
||||||
// elementType = 'a';
|
if (readStructAtAddress(renderCommand.userData.value, customHTMLDataDefinition).link.length.value > 0) {
|
||||||
// }
|
elementType = 'a';
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CLAY_RENDER_COMMAND_TYPE_IMAGE: {
|
case CLAY_RENDER_COMMAND_TYPE_IMAGE: {
|
||||||
|
@ -549,7 +553,6 @@
|
||||||
}
|
}
|
||||||
case (CLAY_RENDER_COMMAND_TYPE_TEXT): {
|
case (CLAY_RENDER_COMMAND_TYPE_TEXT): {
|
||||||
let config = renderCommand.renderData.text;
|
let config = renderCommand.renderData.text;
|
||||||
let customData = readStructAtAddress(renderCommand.userData.value, customHTMLDataDefinition);
|
|
||||||
let configMemory = JSON.stringify(config);
|
let configMemory = JSON.stringify(config);
|
||||||
let stringContents = new Uint8Array(memoryDataView.buffer.slice(config.stringContents.chars.value, config.stringContents.chars.value + config.stringContents.length.value));
|
let stringContents = new Uint8Array(memoryDataView.buffer.slice(config.stringContents.chars.value, config.stringContents.chars.value + config.stringContents.length.value));
|
||||||
if (configMemory !== elementData.previousMemoryConfig) {
|
if (configMemory !== elementData.previousMemoryConfig) {
|
||||||
|
@ -559,7 +562,23 @@
|
||||||
element.style.color = `rgba(${textColor.r.value}, ${textColor.g.value}, ${textColor.b.value}, ${textColor.a.value})`;
|
element.style.color = `rgba(${textColor.r.value}, ${textColor.g.value}, ${textColor.b.value}, ${textColor.a.value})`;
|
||||||
element.style.fontFamily = fontsById[config.fontId.value];
|
element.style.fontFamily = fontsById[config.fontId.value];
|
||||||
element.style.fontSize = fontSize + 'px';
|
element.style.fontSize = fontSize + 'px';
|
||||||
|
if (renderCommand.userData.value !== 0) {
|
||||||
|
let customData = readStructAtAddress(renderCommand.userData.value, customHTMLDataDefinition);
|
||||||
element.style.pointerEvents = customData.disablePointerEvents.value ? 'none' : 'all';
|
element.style.pointerEvents = customData.disablePointerEvents.value ? 'none' : 'all';
|
||||||
|
let linkContents = customData.link.length.value > 0 ? textDecoder.decode(new Uint8Array(memoryDataView.buffer.slice(customData.link.chars.value, customData.link.chars.value + customData.link.length.value))) : 0;
|
||||||
|
memoryDataView.setUint32(0, renderCommand.id.value, true);
|
||||||
|
if (linkContents.length > 0 && (window.mouseDownThisFrame || window.touchDown) && instance.exports.Clay_PointerOver(0)) {
|
||||||
|
window.location.href = linkContents;
|
||||||
|
}
|
||||||
|
if (linkContents.length > 0) {
|
||||||
|
element.href = linkContents;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (linkContents.length > 0 || customData.cursorPointer.value) {
|
||||||
|
element.style.pointerEvents = 'all';
|
||||||
|
element.style.cursor = 'pointer';
|
||||||
|
}
|
||||||
|
}
|
||||||
elementData.previousMemoryConfig = configMemory;
|
elementData.previousMemoryConfig = configMemory;
|
||||||
}
|
}
|
||||||
if (stringContents.length !== elementData.previousMemoryText.length || MemoryIsDifferent(stringContents, elementData.previousMemoryText, stringContents.length)) {
|
if (stringContents.length !== elementData.previousMemoryText.length || MemoryIsDifferent(stringContents, elementData.previousMemoryText, stringContents.length)) {
|
||||||
|
@ -570,7 +589,7 @@
|
||||||
}
|
}
|
||||||
case (CLAY_RENDER_COMMAND_TYPE_SCISSOR_START): {
|
case (CLAY_RENDER_COMMAND_TYPE_SCISSOR_START): {
|
||||||
scissorStack.push({ nextAllocation: { x: renderCommand.boundingBox.x.value, y: renderCommand.boundingBox.y.value }, element, nextElementIndex: 0 });
|
scissorStack.push({ nextAllocation: { x: renderCommand.boundingBox.x.value, y: renderCommand.boundingBox.y.value }, element, nextElementIndex: 0 });
|
||||||
let config = renderCommand.renderData.scroll;
|
let config = renderCommand.renderData.clip;
|
||||||
let configMemory = JSON.stringify(config);
|
let configMemory = JSON.stringify(config);
|
||||||
if (configMemory === elementData.previousMemoryConfig) {
|
if (configMemory === elementData.previousMemoryConfig) {
|
||||||
break;
|
break;
|
||||||
|
|
Binary file not shown.
|
@ -97,6 +97,7 @@
|
||||||
{name: 'a', type: 'float' },
|
{name: 'a', type: 'float' },
|
||||||
]};
|
]};
|
||||||
let stringDefinition = { type: 'struct', members: [
|
let stringDefinition = { type: 'struct', members: [
|
||||||
|
{name: 'isStaticallyAllocated', type: 'uint32_t'},
|
||||||
{name: 'length', type: 'uint32_t' },
|
{name: 'length', type: 'uint32_t' },
|
||||||
{name: 'chars', type: 'uint32_t' },
|
{name: 'chars', type: 'uint32_t' },
|
||||||
]};
|
]};
|
||||||
|
@ -144,7 +145,6 @@
|
||||||
let imageRenderDataDefinition = { type: 'struct', members: [
|
let imageRenderDataDefinition = { type: 'struct', members: [
|
||||||
{ name: 'backgroundColor', ...colorDefinition },
|
{ name: 'backgroundColor', ...colorDefinition },
|
||||||
{ name: 'cornerRadius', ...cornerRadiusDefinition },
|
{ name: 'cornerRadius', ...cornerRadiusDefinition },
|
||||||
{ name: 'sourceDimensions', ...dimensionsDefinition },
|
|
||||||
{ name: 'imageData', type: 'uint32_t' },
|
{ name: 'imageData', type: 'uint32_t' },
|
||||||
]};
|
]};
|
||||||
let customRenderDataDefinition = { type: 'struct', members: [
|
let customRenderDataDefinition = { type: 'struct', members: [
|
||||||
|
@ -158,7 +158,7 @@
|
||||||
{ name: 'width', ...borderWidthDefinition },
|
{ name: 'width', ...borderWidthDefinition },
|
||||||
{ name: 'padding', type: 'uint16_t'}
|
{ name: 'padding', type: 'uint16_t'}
|
||||||
]};
|
]};
|
||||||
let scrollRenderDataDefinition = { type: 'struct', members: [
|
let clipRenderDataDefinition = { type: 'struct', members: [
|
||||||
{ name: 'horizontal', type: 'bool' },
|
{ name: 'horizontal', type: 'bool' },
|
||||||
{ name: 'vertical', type: 'bool' },
|
{ name: 'vertical', type: 'bool' },
|
||||||
]};
|
]};
|
||||||
|
@ -166,9 +166,10 @@
|
||||||
{ name: 'link', ...stringDefinition },
|
{ name: 'link', ...stringDefinition },
|
||||||
{ name: 'cursorPointer', type: 'uint8_t' },
|
{ name: 'cursorPointer', type: 'uint8_t' },
|
||||||
{ name: 'disablePointerEvents', type: 'uint8_t' },
|
{ name: 'disablePointerEvents', type: 'uint8_t' },
|
||||||
|
{ name: 'padding', type: 'uint16_t'}
|
||||||
]};
|
]};
|
||||||
let renderCommandDefinition = {
|
let renderCommandDefinition = {
|
||||||
name: 'CLay_RenderCommand',
|
name: 'Clay_RenderCommand',
|
||||||
type: 'struct',
|
type: 'struct',
|
||||||
members: [
|
members: [
|
||||||
{ name: 'boundingBox', type: 'struct', members: [
|
{ name: 'boundingBox', type: 'struct', members: [
|
||||||
|
@ -183,7 +184,7 @@
|
||||||
{ name: 'image', ...imageRenderDataDefinition },
|
{ name: 'image', ...imageRenderDataDefinition },
|
||||||
{ name: 'custom', ...customRenderDataDefinition },
|
{ name: 'custom', ...customRenderDataDefinition },
|
||||||
{ name: 'border', ...borderRenderDataDefinition },
|
{ name: 'border', ...borderRenderDataDefinition },
|
||||||
{ name: 'scroll', ...scrollRenderDataDefinition },
|
{ name: 'clip', ...clipRenderDataDefinition },
|
||||||
]},
|
]},
|
||||||
{ name: 'userData', type: 'uint32_t'},
|
{ name: 'userData', type: 'uint32_t'},
|
||||||
{ name: 'id', type: 'uint32_t' },
|
{ name: 'id', type: 'uint32_t' },
|
||||||
|
@ -380,7 +381,7 @@
|
||||||
memoryDataView.setFloat32(instance.exports.__heap_base.value, window.innerWidth, true);
|
memoryDataView.setFloat32(instance.exports.__heap_base.value, window.innerWidth, true);
|
||||||
memoryDataView.setFloat32(instance.exports.__heap_base.value + 4, window.innerHeight, true);
|
memoryDataView.setFloat32(instance.exports.__heap_base.value + 4, window.innerHeight, true);
|
||||||
instance.exports.Clay_Initialize(arenaAddress, instance.exports.__heap_base.value);
|
instance.exports.Clay_Initialize(arenaAddress, instance.exports.__heap_base.value);
|
||||||
instance.exports.SetScratchMemory(arenaAddress, clayScratchSpaceAddress);
|
instance.exports.SetScratchMemory(clayScratchSpaceAddress);
|
||||||
renderCommandSize = getStructTotalSize(renderCommandDefinition);
|
renderCommandSize = getStructTotalSize(renderCommandDefinition);
|
||||||
renderLoop();
|
renderLoop();
|
||||||
}
|
}
|
||||||
|
@ -425,10 +426,13 @@
|
||||||
if (!elementCache[renderCommand.id.value]) {
|
if (!elementCache[renderCommand.id.value]) {
|
||||||
let elementType = 'div';
|
let elementType = 'div';
|
||||||
switch (renderCommand.commandType.value & 0xff) {
|
switch (renderCommand.commandType.value & 0xff) {
|
||||||
|
case CLAY_RENDER_COMMAND_TYPE_TEXT:
|
||||||
case CLAY_RENDER_COMMAND_TYPE_RECTANGLE: {
|
case CLAY_RENDER_COMMAND_TYPE_RECTANGLE: {
|
||||||
// if (readStructAtAddress(renderCommand.renderData.rectangle.value, rectangleRenderDataDefinition).link.length.value > 0) { TODO reimplement links
|
if (renderCommand.userData.value !== 0) {
|
||||||
// elementType = 'a';
|
if (readStructAtAddress(renderCommand.userData.value, customHTMLDataDefinition).link.length.value > 0) {
|
||||||
// }
|
elementType = 'a';
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CLAY_RENDER_COMMAND_TYPE_IMAGE: {
|
case CLAY_RENDER_COMMAND_TYPE_IMAGE: {
|
||||||
|
@ -549,7 +553,6 @@
|
||||||
}
|
}
|
||||||
case (CLAY_RENDER_COMMAND_TYPE_TEXT): {
|
case (CLAY_RENDER_COMMAND_TYPE_TEXT): {
|
||||||
let config = renderCommand.renderData.text;
|
let config = renderCommand.renderData.text;
|
||||||
let customData = readStructAtAddress(renderCommand.userData.value, customHTMLDataDefinition);
|
|
||||||
let configMemory = JSON.stringify(config);
|
let configMemory = JSON.stringify(config);
|
||||||
let stringContents = new Uint8Array(memoryDataView.buffer.slice(config.stringContents.chars.value, config.stringContents.chars.value + config.stringContents.length.value));
|
let stringContents = new Uint8Array(memoryDataView.buffer.slice(config.stringContents.chars.value, config.stringContents.chars.value + config.stringContents.length.value));
|
||||||
if (configMemory !== elementData.previousMemoryConfig) {
|
if (configMemory !== elementData.previousMemoryConfig) {
|
||||||
|
@ -559,7 +562,23 @@
|
||||||
element.style.color = `rgba(${textColor.r.value}, ${textColor.g.value}, ${textColor.b.value}, ${textColor.a.value})`;
|
element.style.color = `rgba(${textColor.r.value}, ${textColor.g.value}, ${textColor.b.value}, ${textColor.a.value})`;
|
||||||
element.style.fontFamily = fontsById[config.fontId.value];
|
element.style.fontFamily = fontsById[config.fontId.value];
|
||||||
element.style.fontSize = fontSize + 'px';
|
element.style.fontSize = fontSize + 'px';
|
||||||
|
if (renderCommand.userData.value !== 0) {
|
||||||
|
let customData = readStructAtAddress(renderCommand.userData.value, customHTMLDataDefinition);
|
||||||
element.style.pointerEvents = customData.disablePointerEvents.value ? 'none' : 'all';
|
element.style.pointerEvents = customData.disablePointerEvents.value ? 'none' : 'all';
|
||||||
|
let linkContents = customData.link.length.value > 0 ? textDecoder.decode(new Uint8Array(memoryDataView.buffer.slice(customData.link.chars.value, customData.link.chars.value + customData.link.length.value))) : 0;
|
||||||
|
memoryDataView.setUint32(0, renderCommand.id.value, true);
|
||||||
|
if (linkContents.length > 0 && (window.mouseDownThisFrame || window.touchDown) && instance.exports.Clay_PointerOver(0)) {
|
||||||
|
window.location.href = linkContents;
|
||||||
|
}
|
||||||
|
if (linkContents.length > 0) {
|
||||||
|
element.href = linkContents;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (linkContents.length > 0 || customData.cursorPointer.value) {
|
||||||
|
element.style.pointerEvents = 'all';
|
||||||
|
element.style.cursor = 'pointer';
|
||||||
|
}
|
||||||
|
}
|
||||||
elementData.previousMemoryConfig = configMemory;
|
elementData.previousMemoryConfig = configMemory;
|
||||||
}
|
}
|
||||||
if (stringContents.length !== elementData.previousMemoryText.length || MemoryIsDifferent(stringContents, elementData.previousMemoryText, stringContents.length)) {
|
if (stringContents.length !== elementData.previousMemoryText.length || MemoryIsDifferent(stringContents, elementData.previousMemoryText, stringContents.length)) {
|
||||||
|
@ -570,7 +589,7 @@
|
||||||
}
|
}
|
||||||
case (CLAY_RENDER_COMMAND_TYPE_SCISSOR_START): {
|
case (CLAY_RENDER_COMMAND_TYPE_SCISSOR_START): {
|
||||||
scissorStack.push({ nextAllocation: { x: renderCommand.boundingBox.x.value, y: renderCommand.boundingBox.y.value }, element, nextElementIndex: 0 });
|
scissorStack.push({ nextAllocation: { x: renderCommand.boundingBox.x.value, y: renderCommand.boundingBox.y.value }, element, nextElementIndex: 0 });
|
||||||
let config = renderCommand.renderData.scroll;
|
let config = renderCommand.renderData.clip;
|
||||||
let configMemory = JSON.stringify(config);
|
let configMemory = JSON.stringify(config);
|
||||||
if (configMemory === elementData.previousMemoryConfig) {
|
if (configMemory === elementData.previousMemoryConfig) {
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -44,7 +44,7 @@ typedef struct {
|
||||||
|
|
||||||
Arena frameArena = {};
|
Arena frameArena = {};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct d {
|
||||||
Clay_String link;
|
Clay_String link;
|
||||||
bool cursorPointer;
|
bool cursorPointer;
|
||||||
bool disablePointerEvents;
|
bool disablePointerEvents;
|
||||||
|
@ -66,7 +66,7 @@ Clay_String* FrameAllocateString(Clay_String string) {
|
||||||
|
|
||||||
void LandingPageBlob(int index, int fontSize, Clay_Color color, Clay_String text, Clay_String imageURL) {
|
void LandingPageBlob(int index, int fontSize, Clay_Color color, Clay_String text, Clay_String imageURL) {
|
||||||
CLAY({ .id = CLAY_IDI("HeroBlob", index), .layout = { .sizing = { CLAY_SIZING_GROW(.max = 480) }, .padding = CLAY_PADDING_ALL(16), .childGap = 16, .childAlignment = {.y = CLAY_ALIGN_Y_CENTER} }, .border = { .color = color, .width = { 2, 2, 2, 2 }}, .cornerRadius = CLAY_CORNER_RADIUS(10) }) {
|
CLAY({ .id = CLAY_IDI("HeroBlob", index), .layout = { .sizing = { CLAY_SIZING_GROW(.max = 480) }, .padding = CLAY_PADDING_ALL(16), .childGap = 16, .childAlignment = {.y = CLAY_ALIGN_Y_CENTER} }, .border = { .color = color, .width = { 2, 2, 2, 2 }}, .cornerRadius = CLAY_CORNER_RADIUS(10) }) {
|
||||||
CLAY({ .id = CLAY_IDI("CheckImage", index), .layout = { .sizing = { CLAY_SIZING_FIXED(32) } }, .image = { .sourceDimensions = { 128, 128 }, .imageData = FrameAllocateString(imageURL) } }) {}
|
CLAY({ .id = CLAY_IDI("CheckImage", index), .layout = { .sizing = { CLAY_SIZING_FIXED(32) } }, .aspectRatio = { 1 }, .image = { .imageData = FrameAllocateString(imageURL) } }) {}
|
||||||
CLAY_TEXT(text, CLAY_TEXT_CONFIG({ .fontSize = fontSize, .fontId = FONT_ID_BODY_24, .textColor = color }));
|
CLAY_TEXT(text, CLAY_TEXT_CONFIG({ .fontSize = fontSize, .fontId = FONT_ID_BODY_24, .textColor = color }));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -156,7 +156,7 @@ void DeclarativeSyntaxPageDesktop() {
|
||||||
CLAY_TEXT(CLAY_STRING("Create your own library of re-usable components from UI primitives like text, images and rectangles."), CLAY_TEXT_CONFIG({ .fontSize = 28, .fontId = FONT_ID_BODY_36, .textColor = COLOR_RED }));
|
CLAY_TEXT(CLAY_STRING("Create your own library of re-usable components from UI primitives like text, images and rectangles."), CLAY_TEXT_CONFIG({ .fontSize = 28, .fontId = FONT_ID_BODY_36, .textColor = COLOR_RED }));
|
||||||
}
|
}
|
||||||
CLAY({ .id = CLAY_ID("SyntaxPageRightImage"), .layout = { .sizing = { CLAY_SIZING_PERCENT(0.50) }, .childAlignment = {.x = CLAY_ALIGN_X_CENTER} } }) {
|
CLAY({ .id = CLAY_ID("SyntaxPageRightImage"), .layout = { .sizing = { CLAY_SIZING_PERCENT(0.50) }, .childAlignment = {.x = CLAY_ALIGN_X_CENTER} } }) {
|
||||||
CLAY({ .id = CLAY_ID("SyntaxPageRightImageInner"), .layout = { .sizing = { CLAY_SIZING_GROW(.max = 568) } }, .image = { .sourceDimensions = {1136, 1194}, .imageData = FrameAllocateString(CLAY_STRING("/clay/images/declarative.png")) } }) {}
|
CLAY({ .id = CLAY_ID("SyntaxPageRightImageInner"), .layout = { .sizing = { CLAY_SIZING_GROW(.max = 568) } }, .aspectRatio = { 1136.0 / 1194.0 }, .image = { .imageData = FrameAllocateString(CLAY_STRING("/clay/images/declarative.png")) } }) {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -172,7 +172,7 @@ void DeclarativeSyntaxPageMobile() {
|
||||||
CLAY_TEXT(CLAY_STRING("Create your own library of re-usable components from UI primitives like text, images and rectangles."), CLAY_TEXT_CONFIG({ .fontSize = 28, .fontId = FONT_ID_BODY_36, .textColor = COLOR_RED }));
|
CLAY_TEXT(CLAY_STRING("Create your own library of re-usable components from UI primitives like text, images and rectangles."), CLAY_TEXT_CONFIG({ .fontSize = 28, .fontId = FONT_ID_BODY_36, .textColor = COLOR_RED }));
|
||||||
}
|
}
|
||||||
CLAY({ .id = CLAY_ID("SyntaxPageRightImage"), .layout = { .sizing = { CLAY_SIZING_GROW(0) }, .childAlignment = {.x = CLAY_ALIGN_X_CENTER} } }) {
|
CLAY({ .id = CLAY_ID("SyntaxPageRightImage"), .layout = { .sizing = { CLAY_SIZING_GROW(0) }, .childAlignment = {.x = CLAY_ALIGN_X_CENTER} } }) {
|
||||||
CLAY({ .id = CLAY_ID("SyntaxPageRightImageInner"), .layout = { .sizing = { CLAY_SIZING_GROW(.max = 568) } }, .image = { .sourceDimensions = {1136, 1194}, .imageData = FrameAllocateString(CLAY_STRING("/clay/images/declarative.png")) } }) {}
|
CLAY({ .id = CLAY_ID("SyntaxPageRightImageInner"), .layout = { .sizing = { CLAY_SIZING_GROW(.max = 568) } }, .aspectRatio = { 1136.0 / 1194.0 }, .image = { .imageData = FrameAllocateString(CLAY_STRING("/clay/images/declarative.png")) } }) {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -323,7 +323,7 @@ void DebuggerPageDesktop() {
|
||||||
CLAY_TEXT(CLAY_STRING("Press the \"d\" key to try it out now!"), CLAY_TEXT_CONFIG({ .fontSize = 32, .fontId = FONT_ID_TITLE_36, .textColor = COLOR_ORANGE }));
|
CLAY_TEXT(CLAY_STRING("Press the \"d\" key to try it out now!"), CLAY_TEXT_CONFIG({ .fontSize = 32, .fontId = FONT_ID_TITLE_36, .textColor = COLOR_ORANGE }));
|
||||||
}
|
}
|
||||||
CLAY({ .id = CLAY_ID("DebuggerRightImageOuter"), .layout = { .sizing = { CLAY_SIZING_PERCENT(0.50) }, .childAlignment = {CLAY_ALIGN_X_CENTER} } }) {
|
CLAY({ .id = CLAY_ID("DebuggerRightImageOuter"), .layout = { .sizing = { CLAY_SIZING_PERCENT(0.50) }, .childAlignment = {CLAY_ALIGN_X_CENTER} } }) {
|
||||||
CLAY({ .id = CLAY_ID("DebuggerPageRightImageInner"), .layout = { .sizing = { CLAY_SIZING_GROW(.max = 558) } }, .image = { .sourceDimensions = {1620, 1474}, .imageData = FrameAllocateString(CLAY_STRING("/clay/images/debugger.png")) } }) {}
|
CLAY({ .id = CLAY_ID("DebuggerPageRightImageInner"), .layout = { .sizing = { CLAY_SIZING_GROW(.max = 558) } }, .aspectRatio = { 1620.0 / 1474.0 }, .image = {.imageData = FrameAllocateString(CLAY_STRING("/clay/images/debugger.png")) } }) {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -345,11 +345,18 @@ Clay_RenderCommandArray CreateLayout(bool mobileScreen, float lerpValue) {
|
||||||
CLAY_TEXT(CLAY_STRING("Clay"), &headerTextConfig);
|
CLAY_TEXT(CLAY_STRING("Clay"), &headerTextConfig);
|
||||||
CLAY({ .id = CLAY_ID("Spacer"), .layout = { .sizing = { .width = CLAY_SIZING_GROW(0) } } }) {}
|
CLAY({ .id = CLAY_ID("Spacer"), .layout = { .sizing = { .width = CLAY_SIZING_GROW(0) } } }) {}
|
||||||
if (!mobileScreen) {
|
if (!mobileScreen) {
|
||||||
CLAY({ .id = CLAY_ID("LinkExamplesOuter"), .layout = { .padding = {8, 8} }, .userData = FrameAllocateCustomData((CustomHTMLData) { .link = CLAY_STRING("https://github.com/nicbarker/clay/tree/main/examples") }) }) {
|
CLAY({ .id = CLAY_ID("LinkExamplesOuter"), .layout = { .padding = {8, 8} } }) {
|
||||||
CLAY_TEXT(CLAY_STRING("Examples"), CLAY_TEXT_CONFIG({ .fontId = FONT_ID_BODY_24, .fontSize = 24, .textColor = {61, 26, 5, 255} }));
|
CLAY_TEXT(CLAY_STRING("Examples"), CLAY_TEXT_CONFIG({
|
||||||
|
.userData = FrameAllocateCustomData((CustomHTMLData) {
|
||||||
|
.link = CLAY_STRING("https://github.com/nicbarker/clay/tree/main/examples")
|
||||||
|
}),
|
||||||
|
.fontId = FONT_ID_BODY_24, .fontSize = 24, .textColor = {61, 26, 5, 255} }));
|
||||||
}
|
}
|
||||||
CLAY({ .id = CLAY_ID("LinkDocsOuter"), .layout = { .padding = {8, 8} }, .userData = FrameAllocateCustomData((CustomHTMLData) { .link = CLAY_STRING("https://github.com/nicbarker/clay/blob/main/README.md") }) }) {
|
CLAY({ .id = CLAY_ID("LinkDocsOuter"), .layout = { .padding = {8, 8} } }) {
|
||||||
CLAY_TEXT(CLAY_STRING("Docs"), CLAY_TEXT_CONFIG({ .fontId = FONT_ID_BODY_24, .fontSize = 24, .textColor = {61, 26, 5, 255} }));
|
CLAY_TEXT(CLAY_STRING("Docs"), CLAY_TEXT_CONFIG({
|
||||||
|
.userData = FrameAllocateCustomData((CustomHTMLData) { .link = CLAY_STRING("https://github.com/nicbarker/clay/blob/main/README.md") }),
|
||||||
|
.fontId = FONT_ID_BODY_24, .fontSize = 24, .textColor = {61, 26, 5, 255} })
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
CLAY({
|
CLAY({
|
||||||
|
@ -357,9 +364,11 @@ Clay_RenderCommandArray CreateLayout(bool mobileScreen, float lerpValue) {
|
||||||
.backgroundColor = Clay_Hovered() ? COLOR_LIGHT_HOVER : COLOR_LIGHT,
|
.backgroundColor = Clay_Hovered() ? COLOR_LIGHT_HOVER : COLOR_LIGHT,
|
||||||
.border = { .width = {2, 2, 2, 2}, .color = COLOR_RED },
|
.border = { .width = {2, 2, 2, 2}, .color = COLOR_RED },
|
||||||
.cornerRadius = CLAY_CORNER_RADIUS(10),
|
.cornerRadius = CLAY_CORNER_RADIUS(10),
|
||||||
.userData = FrameAllocateCustomData((CustomHTMLData) { .link = CLAY_STRING("https://github.com/nicbarker/clay/tree/main/examples") }),
|
.userData = FrameAllocateCustomData((CustomHTMLData) { .link = CLAY_STRING("https://discord.gg/b4FTWkxdvT") }),
|
||||||
}) {
|
}) {
|
||||||
CLAY_TEXT(CLAY_STRING("Discord"), CLAY_TEXT_CONFIG({ .fontId = FONT_ID_BODY_24, .fontSize = 24, .textColor = {61, 26, 5, 255} }));
|
CLAY_TEXT(CLAY_STRING("Discord"), CLAY_TEXT_CONFIG({
|
||||||
|
.userData = FrameAllocateCustomData((CustomHTMLData) { .disablePointerEvents = true }),
|
||||||
|
.fontId = FONT_ID_BODY_24, .fontSize = 24, .textColor = {61, 26, 5, 255} }));
|
||||||
}
|
}
|
||||||
CLAY({
|
CLAY({
|
||||||
.layout = { .padding = {16, 16, 6, 6} },
|
.layout = { .padding = {16, 16, 6, 6} },
|
||||||
|
@ -368,7 +377,9 @@ Clay_RenderCommandArray CreateLayout(bool mobileScreen, float lerpValue) {
|
||||||
.cornerRadius = CLAY_CORNER_RADIUS(10),
|
.cornerRadius = CLAY_CORNER_RADIUS(10),
|
||||||
.userData = FrameAllocateCustomData((CustomHTMLData) { .link = CLAY_STRING("https://github.com/nicbarker/clay") }),
|
.userData = FrameAllocateCustomData((CustomHTMLData) { .link = CLAY_STRING("https://github.com/nicbarker/clay") }),
|
||||||
}) {
|
}) {
|
||||||
CLAY_TEXT(CLAY_STRING("Github"), CLAY_TEXT_CONFIG({ .fontId = FONT_ID_BODY_24, .fontSize = 24, .textColor = {61, 26, 5, 255} }));
|
CLAY_TEXT(CLAY_STRING("Github"), CLAY_TEXT_CONFIG({
|
||||||
|
.userData = FrameAllocateCustomData((CustomHTMLData) { .disablePointerEvents = true }),
|
||||||
|
.fontId = FONT_ID_BODY_24, .fontSize = 24, .textColor = {61, 26, 5, 255} }));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Clay_LayoutConfig topBorderConfig = (Clay_LayoutConfig) { .sizing = { CLAY_SIZING_GROW(0), CLAY_SIZING_FIXED(4) }};
|
Clay_LayoutConfig topBorderConfig = (Clay_LayoutConfig) { .sizing = { CLAY_SIZING_GROW(0), CLAY_SIZING_FIXED(4) }};
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -23,6 +23,7 @@ static Clay_Dimensions SDL2_MeasureText(Clay_StringSlice text, Clay_TextElementC
|
||||||
SDL2_Font *fonts = (SDL2_Font*)userData;
|
SDL2_Font *fonts = (SDL2_Font*)userData;
|
||||||
|
|
||||||
TTF_Font *font = fonts[config->fontId].font;
|
TTF_Font *font = fonts[config->fontId].font;
|
||||||
|
TTF_SetFontSize(font, config->fontSize);
|
||||||
char *chars = (char *)calloc(text.length + 1, 1);
|
char *chars = (char *)calloc(text.length + 1, 1);
|
||||||
memcpy(chars, text.chars, text.length);
|
memcpy(chars, text.chars, text.length);
|
||||||
int width = 0;
|
int width = 0;
|
||||||
|
@ -294,6 +295,7 @@ static void Clay_SDL2_Render(SDL_Renderer *renderer, Clay_RenderCommandArray ren
|
||||||
char *cloned = (char *)calloc(config->stringContents.length + 1, 1);
|
char *cloned = (char *)calloc(config->stringContents.length + 1, 1);
|
||||||
memcpy(cloned, config->stringContents.chars, config->stringContents.length);
|
memcpy(cloned, config->stringContents.chars, config->stringContents.length);
|
||||||
TTF_Font* font = fonts[config->fontId].font;
|
TTF_Font* font = fonts[config->fontId].font;
|
||||||
|
TTF_SetFontSize(font, config->fontSize);
|
||||||
SDL_Surface *surface = TTF_RenderUTF8_Blended(font, cloned, (SDL_Color) {
|
SDL_Surface *surface = TTF_RenderUTF8_Blended(font, cloned, (SDL_Color) {
|
||||||
.r = (Uint8)config->textColor.r,
|
.r = (Uint8)config->textColor.r,
|
||||||
.g = (Uint8)config->textColor.g,
|
.g = (Uint8)config->textColor.g,
|
||||||
|
|
|
@ -164,6 +164,7 @@ static void SDL_Clay_RenderClayCommands(Clay_SDL3RendererData *rendererData, Cla
|
||||||
case CLAY_RENDER_COMMAND_TYPE_TEXT: {
|
case CLAY_RENDER_COMMAND_TYPE_TEXT: {
|
||||||
Clay_TextRenderData *config = &rcmd->renderData.text;
|
Clay_TextRenderData *config = &rcmd->renderData.text;
|
||||||
TTF_Font *font = rendererData->fonts[config->fontId];
|
TTF_Font *font = rendererData->fonts[config->fontId];
|
||||||
|
TTF_SetFontSize(font, config->fontSize);
|
||||||
TTF_Text *text = TTF_CreateText(rendererData->textEngine, font, config->stringContents.chars, config->stringContents.length);
|
TTF_Text *text = TTF_CreateText(rendererData->textEngine, font, config->stringContents.chars, config->stringContents.length);
|
||||||
TTF_SetTextColor(text, config->textColor.r, config->textColor.g, config->textColor.b, config->textColor.a);
|
TTF_SetTextColor(text, config->textColor.r, config->textColor.g, config->textColor.b, config->textColor.a);
|
||||||
TTF_DrawRendererText(text, rect.x, rect.y);
|
TTF_DrawRendererText(text, rect.x, rect.y);
|
||||||
|
@ -184,11 +185,11 @@ static void SDL_Clay_RenderClayCommands(Clay_SDL3RendererData *rendererData, Cla
|
||||||
if (config->width.left > 0) {
|
if (config->width.left > 0) {
|
||||||
const float starting_y = rect.y + clampedRadii.topLeft;
|
const float starting_y = rect.y + clampedRadii.topLeft;
|
||||||
const float length = rect.h - clampedRadii.topLeft - clampedRadii.bottomLeft;
|
const float length = rect.h - clampedRadii.topLeft - clampedRadii.bottomLeft;
|
||||||
SDL_FRect line = { rect.x, starting_y, config->width.left, length };
|
SDL_FRect line = { rect.x - 1, starting_y, config->width.left, length };
|
||||||
SDL_RenderFillRect(rendererData->renderer, &line);
|
SDL_RenderFillRect(rendererData->renderer, &line);
|
||||||
}
|
}
|
||||||
if (config->width.right > 0) {
|
if (config->width.right > 0) {
|
||||||
const float starting_x = rect.x + rect.w - (float)config->width.right;
|
const float starting_x = rect.x + rect.w - (float)config->width.right + 1;
|
||||||
const float starting_y = rect.y + clampedRadii.topRight;
|
const float starting_y = rect.y + clampedRadii.topRight;
|
||||||
const float length = rect.h - clampedRadii.topRight - clampedRadii.bottomRight;
|
const float length = rect.h - clampedRadii.topRight - clampedRadii.bottomRight;
|
||||||
SDL_FRect line = { starting_x, starting_y, config->width.right, length };
|
SDL_FRect line = { starting_x, starting_y, config->width.right, length };
|
||||||
|
@ -197,12 +198,12 @@ static void SDL_Clay_RenderClayCommands(Clay_SDL3RendererData *rendererData, Cla
|
||||||
if (config->width.top > 0) {
|
if (config->width.top > 0) {
|
||||||
const float starting_x = rect.x + clampedRadii.topLeft;
|
const float starting_x = rect.x + clampedRadii.topLeft;
|
||||||
const float length = rect.w - clampedRadii.topLeft - clampedRadii.topRight;
|
const float length = rect.w - clampedRadii.topLeft - clampedRadii.topRight;
|
||||||
SDL_FRect line = { starting_x, rect.y, length, config->width.top };
|
SDL_FRect line = { starting_x, rect.y - 1, length, config->width.top };
|
||||||
SDL_RenderFillRect(rendererData->renderer, &line);
|
SDL_RenderFillRect(rendererData->renderer, &line);
|
||||||
}
|
}
|
||||||
if (config->width.bottom > 0) {
|
if (config->width.bottom > 0) {
|
||||||
const float starting_x = rect.x + clampedRadii.bottomLeft;
|
const float starting_x = rect.x + clampedRadii.bottomLeft;
|
||||||
const float starting_y = rect.y + rect.h - (float)config->width.bottom;
|
const float starting_y = rect.y + rect.h - (float)config->width.bottom + 1;
|
||||||
const float length = rect.w - clampedRadii.bottomLeft - clampedRadii.bottomRight;
|
const float length = rect.w - clampedRadii.bottomLeft - clampedRadii.bottomRight;
|
||||||
SDL_FRect line = { starting_x, starting_y, length, config->width.bottom };
|
SDL_FRect line = { starting_x, starting_y, length, config->width.bottom };
|
||||||
SDL_SetRenderDrawColor(rendererData->renderer, config->color.r, config->color.g, config->color.b, config->color.a);
|
SDL_SetRenderDrawColor(rendererData->renderer, config->color.r, config->color.g, config->color.b, config->color.a);
|
||||||
|
@ -211,25 +212,25 @@ static void SDL_Clay_RenderClayCommands(Clay_SDL3RendererData *rendererData, Cla
|
||||||
//corners
|
//corners
|
||||||
if (config->cornerRadius.topLeft > 0) {
|
if (config->cornerRadius.topLeft > 0) {
|
||||||
const float centerX = rect.x + clampedRadii.topLeft -1;
|
const float centerX = rect.x + clampedRadii.topLeft -1;
|
||||||
const float centerY = rect.y + clampedRadii.topLeft;
|
const float centerY = rect.y + clampedRadii.topLeft - 1;
|
||||||
SDL_Clay_RenderArc(rendererData, (SDL_FPoint){centerX, centerY}, clampedRadii.topLeft,
|
SDL_Clay_RenderArc(rendererData, (SDL_FPoint){centerX, centerY}, clampedRadii.topLeft,
|
||||||
180.0f, 270.0f, config->width.top, config->color);
|
180.0f, 270.0f, config->width.top, config->color);
|
||||||
}
|
}
|
||||||
if (config->cornerRadius.topRight > 0) {
|
if (config->cornerRadius.topRight > 0) {
|
||||||
const float centerX = rect.x + rect.w - clampedRadii.topRight -1;
|
const float centerX = rect.x + rect.w - clampedRadii.topRight;
|
||||||
const float centerY = rect.y + clampedRadii.topRight;
|
const float centerY = rect.y + clampedRadii.topRight - 1;
|
||||||
SDL_Clay_RenderArc(rendererData, (SDL_FPoint){centerX, centerY}, clampedRadii.topRight,
|
SDL_Clay_RenderArc(rendererData, (SDL_FPoint){centerX, centerY}, clampedRadii.topRight,
|
||||||
270.0f, 360.0f, config->width.top, config->color);
|
270.0f, 360.0f, config->width.top, config->color);
|
||||||
}
|
}
|
||||||
if (config->cornerRadius.bottomLeft > 0) {
|
if (config->cornerRadius.bottomLeft > 0) {
|
||||||
const float centerX = rect.x + clampedRadii.bottomLeft -1;
|
const float centerX = rect.x + clampedRadii.bottomLeft -1;
|
||||||
const float centerY = rect.y + rect.h - clampedRadii.bottomLeft -1;
|
const float centerY = rect.y + rect.h - clampedRadii.bottomLeft;
|
||||||
SDL_Clay_RenderArc(rendererData, (SDL_FPoint){centerX, centerY}, clampedRadii.bottomLeft,
|
SDL_Clay_RenderArc(rendererData, (SDL_FPoint){centerX, centerY}, clampedRadii.bottomLeft,
|
||||||
90.0f, 180.0f, config->width.bottom, config->color);
|
90.0f, 180.0f, config->width.bottom, config->color);
|
||||||
}
|
}
|
||||||
if (config->cornerRadius.bottomRight > 0) {
|
if (config->cornerRadius.bottomRight > 0) {
|
||||||
const float centerX = rect.x + rect.w - clampedRadii.bottomRight -1; //TODO: why need to -1 in all calculations???
|
const float centerX = rect.x + rect.w - clampedRadii.bottomRight;
|
||||||
const float centerY = rect.y + rect.h - clampedRadii.bottomRight -1;
|
const float centerY = rect.y + rect.h - clampedRadii.bottomRight;
|
||||||
SDL_Clay_RenderArc(rendererData, (SDL_FPoint){centerX, centerY}, clampedRadii.bottomRight,
|
SDL_Clay_RenderArc(rendererData, (SDL_FPoint){centerX, centerY}, clampedRadii.bottomRight,
|
||||||
0.0f, 90.0f, config->width.bottom, config->color);
|
0.0f, 90.0f, config->width.bottom, config->color);
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,6 +87,8 @@ static inline Clay_Dimensions Raylib_MeasureText(Clay_StringSlice text, Clay_Tex
|
||||||
|
|
||||||
float maxTextWidth = 0.0f;
|
float maxTextWidth = 0.0f;
|
||||||
float lineTextWidth = 0;
|
float lineTextWidth = 0;
|
||||||
|
int maxLineCharCount = 0;
|
||||||
|
int lineCharCount = 0;
|
||||||
|
|
||||||
float textHeight = config->fontSize;
|
float textHeight = config->fontSize;
|
||||||
Font* fonts = (Font*)userData;
|
Font* fonts = (Font*)userData;
|
||||||
|
@ -99,11 +101,13 @@ static inline Clay_Dimensions Raylib_MeasureText(Clay_StringSlice text, Clay_Tex
|
||||||
|
|
||||||
float scaleFactor = config->fontSize/(float)fontToUse.baseSize;
|
float scaleFactor = config->fontSize/(float)fontToUse.baseSize;
|
||||||
|
|
||||||
for (int i = 0; i < text.length; ++i)
|
for (int i = 0; i < text.length; ++i, lineCharCount++)
|
||||||
{
|
{
|
||||||
if (text.chars[i] == '\n') {
|
if (text.chars[i] == '\n') {
|
||||||
maxTextWidth = fmax(maxTextWidth, lineTextWidth);
|
maxTextWidth = fmax(maxTextWidth, lineTextWidth);
|
||||||
|
maxLineCharCount = CLAY__MAX(maxLineCharCount, lineCharCount);
|
||||||
lineTextWidth = 0;
|
lineTextWidth = 0;
|
||||||
|
lineCharCount = 0;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
int index = text.chars[i] - 32;
|
int index = text.chars[i] - 32;
|
||||||
|
@ -112,8 +116,9 @@ static inline Clay_Dimensions Raylib_MeasureText(Clay_StringSlice text, Clay_Tex
|
||||||
}
|
}
|
||||||
|
|
||||||
maxTextWidth = fmax(maxTextWidth, lineTextWidth);
|
maxTextWidth = fmax(maxTextWidth, lineTextWidth);
|
||||||
|
maxLineCharCount = CLAY__MAX(maxLineCharCount, lineCharCount);
|
||||||
|
|
||||||
textSize.width = maxTextWidth * scaleFactor;
|
textSize.width = maxTextWidth * scaleFactor + (lineCharCount * config->letterSpacing);
|
||||||
textSize.height = textHeight;
|
textSize.height = textHeight;
|
||||||
|
|
||||||
return textSize;
|
return textSize;
|
||||||
|
@ -145,7 +150,7 @@ void Clay_Raylib_Render(Clay_RenderCommandArray renderCommands, Font* fonts)
|
||||||
for (int j = 0; j < renderCommands.length; j++)
|
for (int j = 0; j < renderCommands.length; j++)
|
||||||
{
|
{
|
||||||
Clay_RenderCommand *renderCommand = Clay_RenderCommandArray_Get(&renderCommands, j);
|
Clay_RenderCommand *renderCommand = Clay_RenderCommandArray_Get(&renderCommands, j);
|
||||||
Clay_BoundingBox boundingBox = renderCommand->boundingBox;
|
Clay_BoundingBox boundingBox = {roundf(renderCommand->boundingBox.x), roundf(renderCommand->boundingBox.y), roundf(renderCommand->boundingBox.width), roundf(renderCommand->boundingBox.height)};
|
||||||
switch (renderCommand->commandType)
|
switch (renderCommand->commandType)
|
||||||
{
|
{
|
||||||
case CLAY_RENDER_COMMAND_TYPE_TEXT: {
|
case CLAY_RENDER_COMMAND_TYPE_TEXT: {
|
||||||
|
@ -174,11 +179,12 @@ void Clay_Raylib_Render(Clay_RenderCommandArray renderCommands, Font* fonts)
|
||||||
if (tintColor.r == 0 && tintColor.g == 0 && tintColor.b == 0 && tintColor.a == 0) {
|
if (tintColor.r == 0 && tintColor.g == 0 && tintColor.b == 0 && tintColor.a == 0) {
|
||||||
tintColor = (Clay_Color) { 255, 255, 255, 255 };
|
tintColor = (Clay_Color) { 255, 255, 255, 255 };
|
||||||
}
|
}
|
||||||
DrawTextureEx(
|
DrawTexturePro(
|
||||||
imageTexture,
|
imageTexture,
|
||||||
(Vector2){boundingBox.x, boundingBox.y},
|
(Rectangle) { 0, 0, imageTexture.width, imageTexture.height },
|
||||||
|
(Rectangle){boundingBox.x, boundingBox.y, boundingBox.width, boundingBox.height},
|
||||||
|
(Vector2) {},
|
||||||
0,
|
0,
|
||||||
boundingBox.width / (float)imageTexture.width,
|
|
||||||
CLAY_COLOR_TO_RAYLIB_COLOR(tintColor));
|
CLAY_COLOR_TO_RAYLIB_COLOR(tintColor));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue