Migrate to Clay main branch rather than release (#27)

Co-authored-by: Zachary Levy <zachary@sunforge.is>
Reviewed-on: #27
This commit was merged in pull request #27.
This commit is contained in:
2026-05-09 01:55:25 +00:00
parent 43f08ed30c
commit 0ecd93a334
11 changed files with 233 additions and 114 deletions
+7 -1
View File
@@ -684,7 +684,13 @@ upload_backdrop_primitives :: proc(device: ^sdl.GPUDevice, pass: ^sdl.GPUCopyPas
sdl.GPUBufferUsageFlags{.GRAPHICS_STORAGE_READ}, sdl.GPUBufferUsageFlags{.GRAPHICS_STORAGE_READ},
) )
prim_array := sdl.MapGPUTransferBuffer(device, GLOB.backdrop.primitive_buffer.transfer, false) // cycle=true: this is a persistent per-frame streaming transfer buffer. The previous
// frame's UploadToGPUBuffer is almost certainly still in flight when we map here
// (allowedFramesInFlight defaults to 2 on Metal). Without cycling, the CPU memcpy below
// races the GPU's blit read on the same MTLBuffer.contents. Cycling rebinds the
// container's active internal buffer to an unbound one (or allocates a new one) — O(1)
// in steady state, no fence wait. See SDL_gpu_metal.m's METAL_INTERNAL_PrepareBufferForWrite.
prim_array := sdl.MapGPUTransferBuffer(device, GLOB.backdrop.primitive_buffer.transfer, true)
if prim_array == nil { if prim_array == nil {
log.panicf("Failed to map backdrop primitive transfer buffer: %s", sdl.GetError()) log.panicf("Failed to map backdrop primitive transfer buffer: %s", sdl.GetError())
} }
+7 -3
View File
@@ -538,7 +538,9 @@ upload :: proc(device: ^sdl.GPUDevice, pass: ^sdl.GPUCopyPass) {
sdl.GPUBufferUsageFlags{.VERTEX}, sdl.GPUBufferUsageFlags{.VERTEX},
) )
vert_array := sdl.MapGPUTransferBuffer(device, GLOB.core_2d.vertex_buffer.transfer, false) // cycle=true: see backdrop.odin upload_backdrop_primitives. Persistent per-frame
// streaming buffer; previous frame's blit is still in flight at map time.
vert_array := sdl.MapGPUTransferBuffer(device, GLOB.core_2d.vertex_buffer.transfer, true)
if vert_array == nil { if vert_array == nil {
log.panicf("Failed to map vertex transfer buffer: %s", sdl.GetError()) log.panicf("Failed to map vertex transfer buffer: %s", sdl.GetError())
} }
@@ -569,7 +571,8 @@ upload :: proc(device: ^sdl.GPUDevice, pass: ^sdl.GPUCopyPass) {
grow_buffer_if_needed(device, &GLOB.core_2d.index_buffer, index_size, sdl.GPUBufferUsageFlags{.INDEX}) grow_buffer_if_needed(device, &GLOB.core_2d.index_buffer, index_size, sdl.GPUBufferUsageFlags{.INDEX})
idx_array := sdl.MapGPUTransferBuffer(device, GLOB.core_2d.index_buffer.transfer, false) // cycle=true: see vertex_buffer above.
idx_array := sdl.MapGPUTransferBuffer(device, GLOB.core_2d.index_buffer.transfer, true)
if idx_array == nil { if idx_array == nil {
log.panicf("Failed to map index transfer buffer: %s", sdl.GetError()) log.panicf("Failed to map index transfer buffer: %s", sdl.GetError())
} }
@@ -596,7 +599,8 @@ upload :: proc(device: ^sdl.GPUDevice, pass: ^sdl.GPUCopyPass) {
sdl.GPUBufferUsageFlags{.GRAPHICS_STORAGE_READ}, sdl.GPUBufferUsageFlags{.GRAPHICS_STORAGE_READ},
) )
prim_array := sdl.MapGPUTransferBuffer(device, GLOB.core_2d.primitive_buffer.transfer, false) // cycle=true: see vertex_buffer above.
prim_array := sdl.MapGPUTransferBuffer(device, GLOB.core_2d.primitive_buffer.transfer, true)
if prim_array == nil { if prim_array == nil {
log.panicf("Failed to map primitive transfer buffer: %s", sdl.GetError()) log.panicf("Failed to map primitive transfer buffer: %s", sdl.GetError())
} }
+2
View File
@@ -915,6 +915,8 @@ dispatch_clay_command :: proc(
} }
} }
case clay.RenderCommandType.ScissorEnd: case clay.RenderCommandType.ScissorEnd:
case clay.RenderCommandType.OverlayColorStart, clay.RenderCommandType.OverlayColorEnd:
unimplemented("Clay overlays not supported yet...")
case clay.RenderCommandType.Rectangle: case clay.RenderCommandType.Rectangle:
render_data := render_command.renderData.rectangle render_data := render_command.renderData.rectangle
cr := render_data.cornerRadius cr := render_data.cornerRadius
+25 -30
View File
@@ -244,9 +244,8 @@ hellope_clay :: proc() {
base_layer := draw.begin({width = 500, height = 500}) base_layer := draw.begin({width = 500, height = 500})
clay.SetLayoutDimensions({width = base_layer.bounds.width, height = base_layer.bounds.height}) clay.SetLayoutDimensions({width = base_layer.bounds.width, height = base_layer.bounds.height})
clay.BeginLayout() clay.BeginLayout()
if clay.UI()( if clay.UI(clay.ID("outer"))(
{ {
id = clay.ID("outer"),
layout = { layout = {
sizing = {clay.SizingGrow({}), clay.SizingGrow({})}, sizing = {clay.SizingGrow({}), clay.SizingGrow({})},
childAlignment = {x = .Center, y = .Center}, childAlignment = {x = .Center, y = .Center},
@@ -254,11 +253,11 @@ hellope_clay :: proc() {
backgroundColor = {127, 127, 127, 255}, backgroundColor = {127, 127, 127, 255},
}, },
) { ) {
clay.Text("Hellope!", &text_config) clay.Text("Hellope!", text_config)
} }
clay_batch := draw.ClayBatch { clay_batch := draw.ClayBatch {
bounds = base_layer.bounds, bounds = base_layer.bounds,
cmds = clay.EndLayout(), cmds = clay.EndLayout(0),
} }
draw.prepare_clay_batch(base_layer, &clay_batch, {0, 0}) draw.prepare_clay_batch(base_layer, &clay_batch, {0, 0})
draw.end(gpu, window) draw.end(gpu, window)
@@ -280,12 +279,14 @@ hellope_custom :: proc() {
} }
gauge := Gauge { gauge := Gauge {
value = 0.73, value = 0.73,
color = {50, 200, 100, 255}, color = {50, 200, 100, 255},
bg_color = {80, 80, 80, 255},
} }
gauge2 := Gauge { gauge2 := Gauge {
value = 0.45, value = 0.45,
color = {200, 100, 50, 255}, color = {200, 100, 50, 255},
bg_color = {80, 80, 80, 255},
} }
// `clay.CustomElementConfig.customData` is a rawptr; the Clay integration in `draw` // `clay.CustomElementConfig.customData` is a rawptr; the Clay integration in `draw`
@@ -320,9 +321,8 @@ hellope_custom :: proc() {
clay.SetLayoutDimensions({width = base_layer.bounds.width, height = base_layer.bounds.height}) clay.SetLayoutDimensions({width = base_layer.bounds.width, height = base_layer.bounds.height})
clay.BeginLayout() clay.BeginLayout()
if clay.UI()( if clay.UI(clay.ID("outer"))(
{ {
id = clay.ID("outer"),
layout = { layout = {
sizing = {clay.SizingGrow({}), clay.SizingGrow({})}, sizing = {clay.SizingGrow({}), clay.SizingGrow({})},
childAlignment = {x = .Center, y = .Center}, childAlignment = {x = .Center, y = .Center},
@@ -332,8 +332,8 @@ hellope_custom :: proc() {
backgroundColor = {50, 50, 50, 255}, backgroundColor = {50, 50, 50, 255},
}, },
) { ) {
if clay.UI()({id = clay.ID("title"), layout = {sizing = {clay.SizingFit({}), clay.SizingFit({})}}}) { if clay.UI(clay.ID("title"))({layout = {sizing = {clay.SizingFit({}), clay.SizingFit({})}}}) {
clay.Text("Custom Draw Demo", &text_config) clay.Text("Custom Draw Demo", text_config)
} }
// gauge1 is BEHIND the backdrop — the backdrop is declared as a floating CHILD // gauge1 is BEHIND the backdrop — the backdrop is declared as a floating CHILD
@@ -344,17 +344,15 @@ hellope_custom :: proc() {
// reflection inside the strip), and gauge2 is deferred-replayed by // reflection inside the strip), and gauge2 is deferred-replayed by
// `prepare_clay_batch` after the bracket closes (renders crisp on top of the // `prepare_clay_batch` after the bracket closes (renders crisp on top of the
// bracket output — unrelated to the strip since they don't overlap). // bracket output — unrelated to the strip since they don't overlap).
if clay.UI()( // `backgroundColor` is omitted on the gauges; bg lives on `Gauge.bg_color`. See `draw_custom`.
if clay.UI(clay.ID("gauge"))(
{ {
id = clay.ID("gauge"),
layout = {sizing = {clay.SizingFixed(300), clay.SizingFixed(30)}}, layout = {sizing = {clay.SizingFixed(300), clay.SizingFixed(30)}},
custom = {customData = &gauge_custom}, custom = {customData = &gauge_custom},
backgroundColor = {80, 80, 80, 255},
}, },
) { ) {
if clay.UI()( if clay.UI(clay.ID("backdrop"))(
{ {
id = clay.ID("backdrop"),
floating = {attachTo = .Parent, attachment = {parent = .LeftTop, element = .LeftTop}}, floating = {attachTo = .Parent, attachment = {parent = .LeftTop, element = .LeftTop}},
layout = {sizing = {clay.SizingFixed(300), clay.SizingFixed(30)}}, layout = {sizing = {clay.SizingFixed(300), clay.SizingFixed(30)}},
custom = {customData = &backdrop_custom}, custom = {customData = &backdrop_custom},
@@ -362,27 +360,26 @@ hellope_custom :: proc() {
) {} ) {}
} }
if clay.UI()( if clay.UI(clay.ID("gauge2"))(
{ {
id = clay.ID("gauge2"),
layout = {sizing = {clay.SizingFixed(300), clay.SizingFixed(30)}}, layout = {sizing = {clay.SizingFixed(300), clay.SizingFixed(30)}},
custom = {customData = &gauge2_custom}, custom = {customData = &gauge2_custom},
backgroundColor = {80, 80, 80, 255},
}, },
) {} ) {}
} }
clay_batch := draw.ClayBatch { clay_batch := draw.ClayBatch {
bounds = base_layer.bounds, bounds = base_layer.bounds,
cmds = clay.EndLayout(), cmds = clay.EndLayout(0),
} }
draw.prepare_clay_batch(base_layer, &clay_batch, {0, 0}, custom_draw = draw_custom) draw.prepare_clay_batch(base_layer, &clay_batch, {0, 0}, custom_draw = draw_custom)
draw.end(gpu, window) draw.end(gpu, window)
} }
Gauge :: struct { Gauge :: struct {
value: f32, value: f32,
color: draw.Color, color: draw.Color,
bg_color: draw.Color,
} }
draw_custom :: proc(layer: ^draw.Layer, bounds: draw.Rectangle, render_data: clay.CustomRenderData) { draw_custom :: proc(layer: ^draw.Layer, bounds: draw.Rectangle, render_data: clay.CustomRenderData) {
@@ -391,14 +388,12 @@ hellope_custom :: proc() {
// before the union refactor. // before the union refactor.
gauge := cast(^Gauge)render_data.customData gauge := cast(^Gauge)render_data.customData
// `gauge.bg_color` instead of `render_data.backgroundColor`: under Clay master, an
// element with both `custom.customData` and `backgroundColor` emits a Custom AND a
// Rectangle for the same bounds, in that order — the Rectangle paints over the
// callback's output. Carrying bg on user data sidesteps it.
border_width: f32 = 2 border_width: f32 = 2
draw.rectangle( draw.rectangle(layer, bounds, gauge.bg_color, outline_color = draw.WHITE, outline_width = border_width)
layer,
bounds,
draw.color_from_clay(render_data.backgroundColor),
outline_color = draw.WHITE,
outline_width = border_width,
)
fill := draw.Rectangle { fill := draw.Rectangle {
x = bounds.x, x = bounds.x,
+192 -74
View File
@@ -18,14 +18,14 @@ when ODIN_OS == .Windows {
String :: struct { String :: struct {
isStaticallyAllocated: c.bool, isStaticallyAllocated: c.bool,
length: c.int32_t, length: c.int32_t,
chars: [^]c.char, chars: [^]c.char,
} }
StringSlice :: struct { StringSlice :: struct {
length: c.int32_t, length: c.int32_t,
chars: [^]c.char, chars: [^]c.char,
baseChars: [^]c.char, baseChars: [^]c.char,
} }
Vector2 :: [2]c.float Vector2 :: [2]c.float
@@ -57,11 +57,6 @@ CornerRadius :: struct {
bottomRight: c.float, bottomRight: c.float,
} }
BorderData :: struct {
width: u32,
color: Color,
}
ElementId :: struct { ElementId :: struct {
id: u32, id: u32,
offset: u32, offset: u32,
@@ -69,6 +64,12 @@ ElementId :: struct {
stringId: String, stringId: String,
} }
ElementIdArray :: struct {
capacity: i32,
length: i32,
internalArray: [^]ElementId,
}
when ODIN_OS == .Windows { when ODIN_OS == .Windows {
EnumBackingType :: u32 EnumBackingType :: u32
} else { } else {
@@ -83,11 +84,13 @@ RenderCommandType :: enum EnumBackingType {
Image, Image,
ScissorStart, ScissorStart,
ScissorEnd, ScissorEnd,
OverlayColorStart,
OverlayColorEnd,
Custom, Custom,
} }
RectangleElementConfig :: struct { RectangleElementConfig :: struct {
color: Color, color: Color,
} }
TextWrapMode :: enum EnumBackingType { TextWrapMode :: enum EnumBackingType {
@@ -103,22 +106,22 @@ TextAlignment :: enum EnumBackingType {
} }
TextElementConfig :: struct { TextElementConfig :: struct {
userData: rawptr, userData: rawptr,
textColor: Color, textColor: Color,
fontId: u16, fontId: u16,
fontSize: u16, fontSize: u16,
letterSpacing: u16, letterSpacing: u16,
lineHeight: u16, lineHeight: u16,
wrapMode: TextWrapMode, wrapMode: TextWrapMode,
textAlignment: TextAlignment, textAlignment: TextAlignment,
} }
AspectRatioElementConfig :: struct { AspectRatioElementConfig :: struct {
aspectRatio: f32, aspectRatio: f32,
} }
ImageElementConfig :: struct { ImageElementConfig :: struct {
imageData: rawptr, imageData: rawptr,
} }
CustomElementConfig :: struct { CustomElementConfig :: struct {
@@ -126,10 +129,10 @@ CustomElementConfig :: struct {
} }
BorderWidth :: struct { BorderWidth :: struct {
left: u16, left: u16,
right: u16, right: u16,
top: u16, top: u16,
bottom: u16, bottom: u16,
betweenChildren: u16, betweenChildren: u16,
} }
@@ -138,6 +141,92 @@ BorderElementConfig :: struct {
width: BorderWidth, width: BorderWidth,
} }
TransitionData :: struct {
boundingBox: BoundingBox,
backgroundColor: Color,
overlayColor: Color,
borderColor: Color,
borderWidth: BorderWidth,
}
TransitionState :: enum c.int {
Idle,
Entering,
Transitioning,
Exiting,
}
TransitionProperty :: enum c.int {
X,
Y,
Width,
Height,
BackgroundColor,
OverlayColor,
CornerRadius,
BorderColor,
BorderWidth,
}
TransitionPropertyFlags :: bit_set[TransitionProperty;c.int]
TransitionPropertyPosition :: TransitionPropertyFlags{.X, .Y}
TransitionPropertyDimensions :: TransitionPropertyFlags{.Width, .Height}
TransitionPropertyBoundingBox :: TransitionPropertyPosition + TransitionPropertyDimensions
TransitionPropertyBorder :: TransitionPropertyFlags{.BorderColor, .BorderWidth}
TransitionCallbackArguments :: struct {
transitionState: TransitionState,
initial: TransitionData,
current: ^TransitionData,
target: TransitionData,
elapsedTime: f32,
duration: f32,
properties: TransitionPropertyFlags,
}
TransitionEnterTriggerType :: enum EnumBackingType {
SkipOnFirstParentFrame,
TriggerOnFirstParentFrame,
}
TransitionExitTriggerType :: enum EnumBackingType {
SkipWhenParentExits,
TriggerWhenParentExits,
}
TransitionInteractionHandlingType :: enum EnumBackingType {
DisableInteractionsWhileTransitioningPosition,
AllowInteractionsWhileTransitioningPosition,
}
ExitTransitionSiblingOrdering :: enum EnumBackingType {
UnderneathSiblings,
NaturalOrder,
AboveSiblings,
}
TransitionElementConfig :: struct {
handler: proc "c" (args: TransitionCallbackArguments) -> bool,
duration: f32,
properties: TransitionPropertyFlags,
interactionHandling: TransitionInteractionHandlingType,
enter: struct {
setInitialState: proc "c" (
initialState: TransitionData,
properties: TransitionPropertyFlags,
) -> TransitionData,
trigger: TransitionEnterTriggerType,
},
exit: struct {
setFinalState: proc "c" (
finalState: TransitionData,
properties: TransitionPropertyFlags,
) -> TransitionData,
trigger: TransitionExitTriggerType,
siblingOrdering: ExitTransitionSiblingOrdering,
},
}
ClipElementConfig :: struct { ClipElementConfig :: struct {
horizontal: bool, // clip overflowing elements on the "X" axis horizontal: bool, // clip overflowing elements on the "X" axis
vertical: bool, // clip overflowing elements on the "Y" axis vertical: bool, // clip overflowing elements on the "Y" axis
@@ -186,56 +275,67 @@ FloatingElementConfig :: struct {
attachment: FloatingAttachPoints, attachment: FloatingAttachPoints,
pointerCaptureMode: PointerCaptureMode, pointerCaptureMode: PointerCaptureMode,
attachTo: FloatingAttachToElement, attachTo: FloatingAttachToElement,
clipTo: FloatingClipToElement, clipTo: FloatingClipToElement,
} }
TextRenderData :: struct { TextRenderData :: struct {
stringContents: StringSlice, stringContents: StringSlice,
textColor: Color, textColor: Color,
fontId: u16, fontId: u16,
fontSize: u16, fontSize: u16,
letterSpacing: u16, letterSpacing: u16,
lineHeight: u16, lineHeight: u16,
} }
RectangleRenderData :: struct { RectangleRenderData :: struct {
backgroundColor: Color, backgroundColor: Color,
cornerRadius: CornerRadius, cornerRadius: CornerRadius,
} }
ImageRenderData :: struct { ImageRenderData :: struct {
backgroundColor: Color, backgroundColor: Color,
cornerRadius: CornerRadius, cornerRadius: CornerRadius,
imageData: rawptr, imageData: rawptr,
} }
CustomRenderData :: struct { CustomRenderData :: struct {
backgroundColor: Color, backgroundColor: Color,
cornerRadius: CornerRadius, cornerRadius: CornerRadius,
customData: rawptr, customData: rawptr,
}
ClipRenderData :: struct {
horizontal: bool,
vertical: bool,
}
OverlayColorRenderData :: struct {
color: Color,
} }
BorderRenderData :: struct { BorderRenderData :: struct {
color: Color, color: Color,
cornerRadius: CornerRadius, cornerRadius: CornerRadius,
width: BorderWidth, width: BorderWidth,
} }
RenderCommandData :: struct #raw_union { RenderCommandData :: struct #raw_union {
rectangle: RectangleRenderData, rectangle: RectangleRenderData,
text: TextRenderData, text: TextRenderData,
image: ImageRenderData, image: ImageRenderData,
custom: CustomRenderData, custom: CustomRenderData,
border: BorderRenderData, border: BorderRenderData,
clip: ClipRenderData,
overlayColor: OverlayColorRenderData,
} }
RenderCommand :: struct { RenderCommand :: struct {
boundingBox: BoundingBox, boundingBox: BoundingBox,
renderData: RenderCommandData, renderData: RenderCommandData,
userData: rawptr, userData: rawptr,
id: u32, id: u32,
zIndex: i16, zIndex: i16,
commandType: RenderCommandType, commandType: RenderCommandType,
} }
ScrollContainerData :: struct { ScrollContainerData :: struct {
@@ -295,9 +395,9 @@ Sizing :: struct {
} }
Padding :: struct { Padding :: struct {
left: u16, left: u16,
right: u16, right: u16,
top: u16, top: u16,
bottom: u16, bottom: u16,
} }
@@ -338,16 +438,17 @@ ClayArray :: struct($type: typeid) {
} }
ElementDeclaration :: struct { ElementDeclaration :: struct {
id: ElementId,
layout: LayoutConfig, layout: LayoutConfig,
backgroundColor: Color, backgroundColor: Color,
overlayColor: Color,
cornerRadius: CornerRadius, cornerRadius: CornerRadius,
aspectRatio: AspectRatioElementConfig, aspectRatio: AspectRatioElementConfig,
image: ImageElementConfig, image: ImageElementConfig,
floating: FloatingElementConfig, floating: FloatingElementConfig,
custom: CustomElementConfig, custom: CustomElementConfig,
clip: ClipElementConfig, clip: ClipElementConfig,
border: BorderElementConfig, border: BorderElementConfig,
transition: TransitionElementConfig,
userData: rawptr, userData: rawptr,
} }
@@ -360,16 +461,17 @@ ErrorType :: enum EnumBackingType {
FloatingContainerParentNotFound, FloatingContainerParentNotFound,
PercentageOver1, PercentageOver1,
InternalError, InternalError,
UnbalancedOpenClose,
} }
ErrorData :: struct { ErrorData :: struct {
errorType: ErrorType, errorType: ErrorType,
errorText: String, errorText: String,
userData: rawptr, userData: rawptr,
} }
ErrorHandler :: struct { ErrorHandler :: struct {
handler: proc "c" (errorData: ErrorData), handler: proc "c" (errorData: ErrorData),
userData: rawptr, userData: rawptr,
} }
@@ -378,23 +480,27 @@ Context :: struct {} // opaque structure, only use as a pointer
@(link_prefix = "Clay_", default_calling_convention = "c") @(link_prefix = "Clay_", default_calling_convention = "c")
foreign Clay { foreign Clay {
_OpenElement :: proc() --- _OpenElement :: proc() ---
_OpenElementWithId :: proc(id: ElementId) ---
_CloseElement :: proc() --- _CloseElement :: proc() ---
MinMemorySize :: proc() -> u32 --- MinMemorySize :: proc() -> u32 ---
CreateArenaWithCapacityAndMemory :: proc(capacity: c.size_t, offset: [^]u8) -> Arena --- CreateArenaWithCapacityAndMemory :: proc(capacity: c.size_t, offset: [^]u8) -> Arena ---
SetPointerState :: proc(position: Vector2, pointerDown: bool) --- SetPointerState :: proc(position: Vector2, pointerDown: bool) ---
GetPointerState :: proc() -> PointerData ---
Initialize :: proc(arena: Arena, layoutDimensions: Dimensions, errorHandler: ErrorHandler) -> ^Context --- Initialize :: proc(arena: Arena, layoutDimensions: Dimensions, errorHandler: ErrorHandler) -> ^Context ---
GetCurrentContext :: proc() -> ^Context --- GetCurrentContext :: proc() -> ^Context ---
SetCurrentContext :: proc(ctx: ^Context) --- SetCurrentContext :: proc(ctx: ^Context) ---
UpdateScrollContainers :: proc(enableDragScrolling: bool, scrollDelta: Vector2, deltaTime: c.float) --- UpdateScrollContainers :: proc(enableDragScrolling: bool, scrollDelta: Vector2, deltaTime: c.float) ---
SetLayoutDimensions :: proc(dimensions: Dimensions) --- SetLayoutDimensions :: proc(dimensions: Dimensions) ---
BeginLayout :: proc() --- BeginLayout :: proc() ---
EndLayout :: proc() -> ClayArray(RenderCommand) --- EndLayout :: proc(deltaTime: c.float) -> ClayArray(RenderCommand) ---
GetOpenElementId :: proc() -> u32 ---
GetElementId :: proc(id: String) -> ElementId --- GetElementId :: proc(id: String) -> ElementId ---
GetElementIdWithIndex :: proc(id: String, index: u32) -> ElementId --- GetElementIdWithIndex :: proc(id: String, index: u32) -> ElementId ---
GetElementData :: proc(id: ElementId) -> ElementData --- GetElementData :: proc(id: ElementId) -> ElementData ---
Hovered :: proc() -> bool --- Hovered :: proc() -> bool ---
OnHover :: proc(onHoverFunction: proc "c" (id: ElementId, pointerData: PointerData, userData: rawptr), userData: rawptr) --- OnHover :: proc(onHoverFunction: proc "c" (id: ElementId, pointerData: PointerData, userData: rawptr), userData: rawptr) ---
PointerOver :: proc(id: ElementId) -> bool --- PointerOver :: proc(id: ElementId) -> bool ---
GetPointerOverIds :: proc() -> ElementIdArray ---
GetScrollOffset :: proc() -> Vector2 --- GetScrollOffset :: proc() -> Vector2 ---
GetScrollContainerData :: proc(id: ElementId) -> ScrollContainerData --- GetScrollContainerData :: proc(id: ElementId) -> ScrollContainerData ---
SetMeasureTextFunction :: proc(measureTextFunction: proc "c" (text: StringSlice, config: ^TextElementConfig, userData: rawptr) -> Dimensions, userData: rawptr) --- SetMeasureTextFunction :: proc(measureTextFunction: proc "c" (text: StringSlice, config: ^TextElementConfig, userData: rawptr) -> Dimensions, userData: rawptr) ---
@@ -408,15 +514,15 @@ foreign Clay {
GetMaxMeasureTextCacheWordCount :: proc() -> i32 --- GetMaxMeasureTextCacheWordCount :: proc() -> i32 ---
SetMaxMeasureTextCacheWordCount :: proc(maxMeasureTextCacheWordCount: i32) --- SetMaxMeasureTextCacheWordCount :: proc(maxMeasureTextCacheWordCount: i32) ---
ResetMeasureTextCache :: proc() --- ResetMeasureTextCache :: proc() ---
EaseOut :: proc(arguments: TransitionCallbackArguments) -> bool ---
} }
@(link_prefix = "Clay_", default_calling_convention = "c", private) @(link_prefix = "Clay_", default_calling_convention = "c", private)
foreign Clay { foreign Clay {
_ConfigureOpenElement :: proc(config: ElementDeclaration) --- _ConfigureOpenElement :: proc(config: ElementDeclaration) ---
_HashString :: proc(key: String, offset: u32, seed: u32) -> ElementId --- _HashString :: proc(key: String, seed: u32) -> ElementId ---
_OpenTextElement :: proc(text: String, textConfig: ^TextElementConfig) --- _HashStringWithOffset :: proc(key: String, index: u32, seed: u32) -> ElementId ---
_StoreTextElementConfig :: proc(config: TextElementConfig) -> ^TextElementConfig --- _OpenTextElement :: proc(text: String, textConfig: TextElementConfig) ---
_GetParentElementId :: proc() -> u32 ---
} }
ConfigureOpenElement :: proc(config: ElementDeclaration) -> bool { ConfigureOpenElement :: proc(config: ElementDeclaration) -> bool {
@@ -425,27 +531,39 @@ ConfigureOpenElement :: proc(config: ElementDeclaration) -> bool {
} }
@(deferred_none = _CloseElement) @(deferred_none = _CloseElement)
UI :: proc() -> proc (config: ElementDeclaration) -> bool { UI_WithId :: proc(id: ElementId) -> proc(config: ElementDeclaration) -> bool {
_OpenElementWithId(id)
return ConfigureOpenElement
}
@(deferred_none = _CloseElement)
UI_AutoId :: proc() -> proc(config: ElementDeclaration) -> bool {
_OpenElement() _OpenElement()
return ConfigureOpenElement return ConfigureOpenElement
} }
Text :: proc($text: string, config: ^TextElementConfig) { UI :: proc {
UI_WithId,
UI_AutoId,
}
Text :: proc {
TextStatic,
TextDynamic,
}
TextStatic :: proc($text: string, config: TextElementConfig) {
wrapped := MakeString(text) wrapped := MakeString(text)
wrapped.isStaticallyAllocated = true wrapped.isStaticallyAllocated = true
_OpenTextElement(wrapped, config) _OpenTextElement(wrapped, config)
} }
TextDynamic :: proc(text: string, config: ^TextElementConfig) { TextDynamic :: proc(text: string, config: TextElementConfig) {
_OpenTextElement(MakeString(text), config) _OpenTextElement(MakeString(text), config)
} }
TextConfig :: proc(config: TextElementConfig) -> ^TextElementConfig {
return _StoreTextElementConfig(config)
}
PaddingAll :: proc(allPadding: u16) -> Padding { PaddingAll :: proc(allPadding: u16) -> Padding {
return { left = allPadding, right = allPadding, top = allPadding, bottom = allPadding } return {left = allPadding, right = allPadding, top = allPadding, bottom = allPadding}
} }
BorderOutside :: proc(width: u16) -> BorderWidth { BorderOutside :: proc(width: u16) -> BorderWidth {
@@ -460,11 +578,11 @@ CornerRadiusAll :: proc(radius: f32) -> CornerRadius {
return CornerRadius{radius, radius, radius, radius} return CornerRadius{radius, radius, radius, radius}
} }
SizingFit :: proc(sizeMinMax: SizingConstraintsMinMax) -> SizingAxis { SizingFit :: proc(sizeMinMax: SizingConstraintsMinMax = {}) -> SizingAxis {
return SizingAxis{type = SizingType.Fit, constraints = {sizeMinMax = sizeMinMax}} return SizingAxis{type = SizingType.Fit, constraints = {sizeMinMax = sizeMinMax}}
} }
SizingGrow :: proc(sizeMinMax: SizingConstraintsMinMax) -> SizingAxis { SizingGrow :: proc(sizeMinMax: SizingConstraintsMinMax = {}) -> SizingAxis {
return SizingAxis{type = SizingType.Grow, constraints = {sizeMinMax = sizeMinMax}} return SizingAxis{type = SizingType.Grow, constraints = {sizeMinMax = sizeMinMax}}
} }
@@ -481,9 +599,9 @@ MakeString :: proc(label: string) -> String {
} }
ID :: proc(label: string, index: u32 = 0) -> ElementId { ID :: proc(label: string, index: u32 = 0) -> ElementId {
return _HashString(MakeString(label), index, 0) return _HashString(MakeString(label), index)
} }
ID_LOCAL :: proc(label: string, index: u32 = 0) -> ElementId { ID_LOCAL :: proc(label: string, index: u32 = 0) -> ElementId {
return _HashString(MakeString(label), index, _GetParentElementId()) return _HashStringWithOffset(MakeString(label), index, GetOpenElementId())
} }
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
-6
View File
@@ -1,6 +0,0 @@
{
"$schema": "https://raw.githubusercontent.com/DanielGavin/ols/master/misc/odinfmt.schema.json",
"character_width": 180,
"sort_imports": true,
"tabs": false
}
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.