diff --git a/bindings/odin/README.md b/bindings/odin/README.md index e69de29..30404ce 100644 --- a/bindings/odin/README.md +++ b/bindings/odin/README.md @@ -0,0 +1 @@ +TODO \ No newline at end of file diff --git a/bindings/odin/clay-odin/clay.odin b/bindings/odin/clay-odin/clay.odin index d705fda..c3ef0dd 100644 --- a/bindings/odin/clay-odin/clay.odin +++ b/bindings/odin/clay-odin/clay.odin @@ -5,429 +5,423 @@ import "core:strings" foreign import Clay "clay.a" String :: struct { - length: c.int, - chars: [^]c.char, + length: c.int, + chars: [^]c.char, } Vector2 :: struct { - x: c.float, - y: c.float, + x: c.float, + y: c.float, } Dimensions :: struct { - width: c.float, - height: c.float, + width: c.float, + height: c.float, } Arena :: struct { - label: String, - nextAllocation: c.uint64_t, - capacity: c.uint64_t, - memory: [^]c.char, + label: String, + nextAllocation: c.uint64_t, + capacity: c.uint64_t, + memory: [^]c.char, } BoundingBox :: struct { - x: c.float, - y: c.float, - width: c.float, - height: c.float, + x: c.float, + y: c.float, + width: c.float, + height: c.float, } Color :: struct { - r: c.float, - g: c.float, - b: c.float, - a: c.float, + r: c.float, + g: c.float, + b: c.float, + a: c.float, } CornerRadius :: struct { - topLeft: c.float, - topRight: c.float, - bottomLeft: c.float, - bottomRight: c.float, + topLeft: c.float, + topRight: c.float, + bottomLeft: c.float, + bottomRight: c.float, } BorderData :: struct { - width: c.uint32_t, - color: Color, + width: c.uint32_t, + color: Color, } RenderCommandType :: enum u8 { - None, - Rectangle, - Border, - Text, - Image, - ScissorStart, - ScissorEnd, - Custom, + None, + Rectangle, + Border, + Text, + Image, + ScissorStart, + ScissorEnd, + Custom, } RectangleElementConfig :: struct { - color: Color, - cornerRadius: CornerRadius, + color: Color, + cornerRadius: CornerRadius, } TextElementConfig :: struct { - textColor: Color, - fontId: c.uint16_t, - fontSize: c.uint16_t, - letterSpacing: c.uint16_t, - lineSpacing: c.uint16_t, + textColor: Color, + fontId: c.uint16_t, + fontSize: c.uint16_t, + letterSpacing: c.uint16_t, + lineSpacing: c.uint16_t, } ImageElementConfig :: struct { - imageData: rawptr, - sourceDimensions: Dimensions, + imageData: rawptr, + sourceDimensions: Dimensions, } CustomElementConfig :: struct { - customData: rawptr, + customData: rawptr, } BorderElementConfig :: struct { - left: BorderData, - right: BorderData, - top: BorderData, - bottom: BorderData, - betweenChildren: BorderData, - cornerRadius: CornerRadius, + left: BorderData, + right: BorderData, + top: BorderData, + bottom: BorderData, + betweenChildren: BorderData, + cornerRadius: CornerRadius, } ScrollElementConfig :: struct { - horizontal: c.bool, - vertical: c.bool, + horizontal: c.bool, + vertical: c.bool, } FloatingAttachPointType :: enum u8 { - LEFT_TOP, - LEFT_CENTER, - LEFT_BOTTOM, - CENTER_TOP, - CENTER_CENTER, - CENTER_BOTTOM, - RIGHT_TOP, - RIGHT_CENTER, - RIGHT_BOTTOM, + LEFT_TOP, + LEFT_CENTER, + LEFT_BOTTOM, + CENTER_TOP, + CENTER_CENTER, + CENTER_BOTTOM, + RIGHT_TOP, + RIGHT_CENTER, + RIGHT_BOTTOM, } FloatingAttachPoints :: struct { - element: FloatingAttachPointType, - parent: FloatingAttachPointType, + element: FloatingAttachPointType, + parent: FloatingAttachPointType, } FloatingElementConfig :: struct { - offset: Vector2, - expand: Dimensions, - zIndex: c.uint16_t, - parentId: c.uint32_t, - attachment: FloatingAttachPoints, + offset: Vector2, + expand: Dimensions, + zIndex: c.uint16_t, + parentId: c.uint32_t, + attachment: FloatingAttachPoints, } ElementConfigUnion :: struct #raw_union { - rectangleElementConfig: ^RectangleElementConfig, - textElementConfig: ^TextElementConfig, - imageElementConfig: ^ImageElementConfig, - customElementConfig: ^CustomElementConfig, - borderElementConfig: ^BorderElementConfig, + rectangleElementConfig: ^RectangleElementConfig, + textElementConfig: ^TextElementConfig, + imageElementConfig: ^ImageElementConfig, + customElementConfig: ^CustomElementConfig, + borderElementConfig: ^BorderElementConfig, } RenderCommand :: struct { - boundingBox: BoundingBox, - config: ElementConfigUnion, - text: String, - id: c.uint32_t, - commandType: RenderCommandType, + boundingBox: BoundingBox, + config: ElementConfigUnion, + text: String, + id: c.uint32_t, + commandType: RenderCommandType, } ScrollContainerData :: struct { - // Note: This is a pointer to the real internal scroll position, mutating it may cause a change in final layout. - // Intended for use with external functionality that modifies scroll position, such as scroll bars or auto scrolling. - scrollPosition: ^Vector2, - scrollContainerDimensions: Dimensions, - contentDimensions: Dimensions, - config: ScrollElementConfig, - // Indicates whether an actual scroll container matched the provided ID or if the default struct was returned. - found: c.bool, + // Note: This is a pointer to the real internal scroll position, mutating it may cause a change in final layout. + // Intended for use with external functionality that modifies scroll position, such as scroll bars or auto scrolling. + scrollPosition: ^Vector2, + scrollContainerDimensions: Dimensions, + contentDimensions: Dimensions, + config: ScrollElementConfig, + // Indicates whether an actual scroll container matched the provided ID or if the default struct was returned. + found: c.bool, } SizingType :: enum u8 { - FIT, - GROW, - PERCENT, + FIT, + GROW, + PERCENT, +} + +SizingConstraintsMinMax :: struct { + min: c.float, + max: c.float, +} + +SizingConstraints :: struct #raw_union { + sizeMinMax: SizingConstraintsMinMax, + sizePercent: c.float, } SizingAxis :: struct { - // Note: `min` is used for CLAY_SIZING_PERCENT, slightly different to clay.h due to lack of C anonymous unions - min: c.float, - max: c.float, - type: SizingType, + // Note: `min` is used for CLAY_SIZING_PERCENT, slightly different to clay.h due to lack of C anonymous unions + constraints: SizingConstraints, + type: SizingType, } Sizing :: struct { - width: SizingAxis, - height: SizingAxis, + width: SizingAxis, + height: SizingAxis, } Padding :: struct { - x: c.uint16_t, - y: c.uint16_t, + x: c.uint16_t, + y: c.uint16_t, } LayoutDirection :: enum u8 { - LEFT_TO_RIGHT, - TOP_TO_BOTTOM, + LEFT_TO_RIGHT, + TOP_TO_BOTTOM, } LayoutAlignmentX :: enum u8 { - LEFT, - RIGHT, - CENTER, + LEFT, + RIGHT, + CENTER, } LayoutAlignmentY :: enum u8 { - TOP, - BOTTOM, - CENTER, + TOP, + BOTTOM, + CENTER, } ChildAlignment :: struct { - x: LayoutAlignmentX, - y: LayoutAlignmentY, + x: LayoutAlignmentX, + y: LayoutAlignmentY, } LayoutConfig :: struct { - sizing: Sizing, - padding: Padding, - childGap: c.uint16_t, - layoutDirection: LayoutDirection, - childAlignment: ChildAlignment, + sizing: Sizing, + padding: Padding, + childGap: c.uint16_t, + layoutDirection: LayoutDirection, + childAlignment: ChildAlignment, } ClayArray :: struct($type: typeid) { - capacity: c.uint32_t, - length: c.uint32_t, - internalArray: [^]type, + capacity: c.uint32_t, + length: c.uint32_t, + internalArray: [^]type, } +@(link_prefix = "Clay_") foreign Clay { - Clay_MinMemorySize :: proc() -> c.uint32_t --- - Clay_CreateArenaWithCapacityAndMemory :: proc(capacity: c.uint32_t, offset: [^]u8) -> Arena --- - Clay_SetPointerPosition :: proc(position: Vector2) --- - Clay_Initialize :: proc(arena: Arena) --- - Clay_UpdateScrollContainers :: proc(isPointerActive: c.bool, scrollDelta: Vector2, deltaTime: c.float) --- - Clay_BeginLayout :: proc(screenWidth: c.int, screenHeight: c.int) --- - Clay_EndLayout :: proc(screenWidth: c.int, screenHeight: c.int) -> ClayArray(RenderCommand) --- - Clay_PointerOver :: proc(id: c.uint32_t) -> c.bool --- - Clay_GetScrollContainerData :: proc(id: c.uint32_t) -> ScrollContainerData --- - Clay_SetMeasureTextFunction :: proc(measureTextFunction: proc(text: [^]String, config: [^]TextElementConfig) -> Dimensions) --- - Clay__OpenContainerElement :: proc(id: c.uint32_t, layoutConfig: ^LayoutConfig) --- - Clay__OpenRectangleElement :: proc(id: c.uint32_t, layoutConfig: ^LayoutConfig, rectangleConfig: ^RectangleElementConfig) --- - Clay__OpenTextElement :: proc(id: c.uint32_t, text: String, textConfig: ^TextElementConfig) --- - Clay__OpenImageElement :: proc(id: c.uint32_t, layoutConfig: ^LayoutConfig, imageConfig: ^ImageElementConfig) --- - Clay__OpenScrollElement :: proc(id: c.uint32_t, layoutConfig: ^LayoutConfig, imageConfig: ^ScrollElementConfig) --- - Clay__OpenFloatingElement :: proc(id: c.uint32_t, layoutConfig: ^LayoutConfig, imageConfig: ^FloatingElementConfig) --- - Clay__OpenBorderElement :: proc(id: c.uint32_t, layoutConfig: ^LayoutConfig, imageConfig: ^BorderElementConfig) --- - Clay__OpenCustomElement :: proc(id: c.uint32_t, layoutConfig: ^LayoutConfig, imageConfig: ^CustomElementConfig) --- - Clay__CloseElementWithChildren :: proc() --- - Clay__CloseScrollElement :: proc() --- - Clay__CloseFloatingElement :: proc() --- - Clay__layoutConfigs: ClayArray(LayoutConfig) - Clay__LayoutConfigArray_Add :: proc(array: ^ClayArray(LayoutConfig), config: LayoutConfig) -> ^LayoutConfig --- - Clay__rectangleElementConfigs: ClayArray(RectangleElementConfig) - Clay__RectangleElementConfigArray_Add :: proc(array: ^ClayArray(RectangleElementConfig), config: RectangleElementConfig) -> ^RectangleElementConfig --- - Clay__textElementConfigs: ClayArray(TextElementConfig) - Clay__TextElementConfigArray_Add :: proc(array: ^ClayArray(TextElementConfig), config: TextElementConfig) -> ^TextElementConfig --- - Clay__imageElementConfigs: ClayArray(ImageElementConfig) - Clay__ImageElementConfigArray_Add :: proc(array: ^ClayArray(ImageElementConfig), config: ImageElementConfig) -> ^ImageElementConfig --- - Clay__floatingElementConfigs: ClayArray(FloatingElementConfig) - Clay__FloatingElementConfigArray_Add :: proc(array: ^ClayArray(FloatingElementConfig), config: FloatingElementConfig) -> ^FloatingElementConfig --- - Clay__customElementConfigs: ClayArray(CustomElementConfig) - Clay__CustomElementConfigArray_Add :: proc(array: ^ClayArray(CustomElementConfig), config: CustomElementConfig) -> ^CustomElementConfig --- - Clay__scrollElementConfigs: ClayArray(ScrollElementConfig) - Clay__ScrollElementConfigArray_Add :: proc(array: ^ClayArray(ScrollElementConfig), config: ScrollElementConfig) -> ^ScrollElementConfig --- - Clay__borderElementConfigs: ClayArray(BorderElementConfig) - Clay__BorderElementConfigArray_Add :: proc(array: ^ClayArray(BorderElementConfig), config: BorderElementConfig) -> ^BorderElementConfig --- - Clay__HashString :: proc(toHash: String, index: c.uint32_t) -> c.uint32_t --- + MinMemorySize :: proc() -> c.uint32_t --- + CreateArenaWithCapacityAndMemory :: proc(capacity: c.uint32_t, offset: [^]u8) -> Arena --- + SetPointerPosition :: proc(position: Vector2) --- + Initialize :: proc(arena: Arena) --- + UpdateScrollContainers :: proc(isPointerActive: c.bool, scrollDelta: Vector2, deltaTime: c.float) --- + BeginLayout :: proc(screenWidth: c.int, screenHeight: c.int) --- + EndLayout :: proc(screenWidth: c.int, screenHeight: c.int) -> ClayArray(RenderCommand) --- + PointerOver :: proc(id: c.uint32_t) -> c.bool --- + GetScrollContainerData :: proc(id: c.uint32_t) -> ScrollContainerData --- + SetMeasureTextFunction :: proc(measureTextFunction: proc(text: ^String, config: ^TextElementConfig) -> Dimensions) --- + RenderCommandArray_Get :: proc(array: ^ClayArray(RenderCommand), index: c.int32_t) -> ^RenderCommand --- + @(private) + _OpenContainerElement :: proc(id: c.uint32_t, layoutConfig: ^LayoutConfig) --- + @(private) + _OpenRectangleElement :: proc(id: c.uint32_t, layoutConfig: ^LayoutConfig, rectangleConfig: ^RectangleElementConfig) --- + @(private) + _OpenTextElement :: proc(id: c.uint32_t, text: String, textConfig: ^TextElementConfig) --- + @(private) + _OpenImageElement :: proc(id: c.uint32_t, layoutConfig: ^LayoutConfig, imageConfig: ^ImageElementConfig) --- + @(private) + _OpenScrollElement :: proc(id: c.uint32_t, layoutConfig: ^LayoutConfig, imageConfig: ^ScrollElementConfig) --- + @(private) + _OpenFloatingElement :: proc(id: c.uint32_t, layoutConfig: ^LayoutConfig, imageConfig: ^FloatingElementConfig) --- + @(private) + _OpenBorderElement :: proc(id: c.uint32_t, layoutConfig: ^LayoutConfig, imageConfig: ^BorderElementConfig) --- + @(private) + _OpenCustomElement :: proc(id: c.uint32_t, layoutConfig: ^LayoutConfig, imageConfig: ^CustomElementConfig) --- + @(private) + _CloseElementWithChildren :: proc() --- + @(private) + _CloseScrollElement :: proc() --- + @(private) + _CloseFloatingElement :: proc() --- + @(private) + _layoutConfigs: ClayArray(LayoutConfig) + @(private) + _LayoutConfigArray_Add :: proc(array: ^ClayArray(LayoutConfig), config: LayoutConfig) -> ^LayoutConfig --- + @(private) + _rectangleElementConfigs: ClayArray(RectangleElementConfig) + @(private) + _RectangleElementConfigArray_Add :: proc(array: ^ClayArray(RectangleElementConfig), config: RectangleElementConfig) -> ^RectangleElementConfig --- + @(private) + _textElementConfigs: ClayArray(TextElementConfig) + @(private) + _TextElementConfigArray_Add :: proc(array: ^ClayArray(TextElementConfig), config: TextElementConfig) -> ^TextElementConfig --- + @(private) + _imageElementConfigs: ClayArray(ImageElementConfig) + @(private) + _ImageElementConfigArray_Add :: proc(array: ^ClayArray(ImageElementConfig), config: ImageElementConfig) -> ^ImageElementConfig --- + @(private) + _floatingElementConfigs: ClayArray(FloatingElementConfig) + @(private) + _FloatingElementConfigArray_Add :: proc(array: ^ClayArray(FloatingElementConfig), config: FloatingElementConfig) -> ^FloatingElementConfig --- + @(private) + _customElementConfigs: ClayArray(CustomElementConfig) + @(private) + _CustomElementConfigArray_Add :: proc(array: ^ClayArray(CustomElementConfig), config: CustomElementConfig) -> ^CustomElementConfig --- + @(private) + _scrollElementConfigs: ClayArray(ScrollElementConfig) + @(private) + _ScrollElementConfigArray_Add :: proc(array: ^ClayArray(ScrollElementConfig), config: ScrollElementConfig) -> ^ScrollElementConfig --- + @(private) + _borderElementConfigs: ClayArray(BorderElementConfig) + @(private) + _BorderElementConfigArray_Add :: proc(array: ^ClayArray(BorderElementConfig), config: BorderElementConfig) -> ^BorderElementConfig --- + @(private) + _HashString :: proc(toHash: String, index: c.uint32_t) -> c.uint32_t --- } -MinMemorySize :: proc() -> c.uint32_t { - return Clay_MinMemorySize() -} -CreateArenaWithCapacityAndMemory :: proc(capacity: c.uint32_t, offset: [^]u8) -> Arena { - return Clay_CreateArenaWithCapacityAndMemory(capacity, offset) -} - -SetPointerPosition :: proc(position: Vector2) { - Clay_SetPointerPosition(position) -} - -Initialize :: proc(arena: Arena) { - Clay_Initialize(arena) -} - -UpdateScrollContainers :: proc(isPointerActive: c.bool, scrollDelta: Vector2, deltaTime: c.float) { - Clay_UpdateScrollContainers(isPointerActive, scrollDelta, deltaTime) -} - -BeginLayout :: proc(screenWidth: c.int, screenHeight: c.int) { - Clay_BeginLayout(screenWidth, screenHeight) -} - -EndLayout :: proc(screenWidth: c.int, screenHeight: c.int) -> ClayArray(RenderCommand) { - return Clay_EndLayout(screenWidth, screenHeight) -} - -PointerOver :: proc(id: c.uint32_t) -> c.bool { - return Clay_PointerOver(id) -} - -GetScrollContainerData :: proc(id: c.uint32_t) -> ScrollContainerData { - return Clay_GetScrollContainerData(id) -} - -@(deferred_none = Clay__CloseElementWithChildren) +@(require_results, deferred_none = _CloseElementWithChildren) Container :: proc(id: c.uint32_t, layoutConfig: ^LayoutConfig) -> bool { - Clay__OpenContainerElement(id, layoutConfig) - return true + _OpenContainerElement(id, layoutConfig) + return true } -@(deferred_none = Clay__CloseElementWithChildren) -Rectangle :: proc( - id: c.uint32_t, - layoutConfig: ^LayoutConfig, - rectangleConfig: ^RectangleElementConfig, -) -> bool { - Clay__OpenRectangleElement(id, layoutConfig, rectangleConfig) - return true +@(require_results, deferred_none = _CloseElementWithChildren) +Rectangle :: proc(id: c.uint32_t, layoutConfig: ^LayoutConfig, rectangleConfig: ^RectangleElementConfig) -> bool { + _OpenRectangleElement(id, layoutConfig, rectangleConfig) + return true } Text :: proc(id: c.uint32_t, text: String, textConfig: ^TextElementConfig) -> bool { - Clay__OpenTextElement(id, text, textConfig) - return true + _OpenTextElement(id, text, textConfig) + return true } -@(deferred_none = Clay__CloseElementWithChildren) -Image :: proc( - id: c.uint32_t, - layoutConfig: ^LayoutConfig, - imageConfig: ^ImageElementConfig, -) -> bool { - Clay__OpenImageElement(id, layoutConfig, imageConfig) - return true +@(require_results, deferred_none = _CloseElementWithChildren) +Image :: proc(id: c.uint32_t, layoutConfig: ^LayoutConfig, imageConfig: ^ImageElementConfig) -> bool { + _OpenImageElement(id, layoutConfig, imageConfig) + return true } -@(deferred_none = Clay__CloseScrollElement) -Scroll :: proc( - id: c.uint32_t, - layoutConfig: ^LayoutConfig, - scrollConfig: ^ScrollElementConfig, -) -> bool { - Clay__OpenScrollElement(id, layoutConfig, scrollConfig) - return true +@(require_results, deferred_none = _CloseScrollElement) +Scroll :: proc(id: c.uint32_t, layoutConfig: ^LayoutConfig, scrollConfig: ^ScrollElementConfig) -> bool { + _OpenScrollElement(id, layoutConfig, scrollConfig) + return true } -@(deferred_none = Clay__CloseFloatingElement) -Floating :: proc( - id: c.uint32_t, - layoutConfig: ^LayoutConfig, - floatingConfig: ^FloatingElementConfig, -) -> bool { - Clay__OpenFloatingElement(id, layoutConfig, floatingConfig) - return true +@(require_results, deferred_none = _CloseFloatingElement) +Floating :: proc(id: c.uint32_t, layoutConfig: ^LayoutConfig, floatingConfig: ^FloatingElementConfig) -> bool { + _OpenFloatingElement(id, layoutConfig, floatingConfig) + return true } -@(deferred_none = Clay__CloseElementWithChildren) -Border :: proc( - id: c.uint32_t, - layoutConfig: ^LayoutConfig, - borderConfig: ^BorderElementConfig, -) -> bool { - Clay__OpenBorderElement(id, layoutConfig, borderConfig) - return true +@(require_results, deferred_none = _CloseElementWithChildren) +Border :: proc(id: c.uint32_t, layoutConfig: ^LayoutConfig, borderConfig: ^BorderElementConfig) -> bool { + _OpenBorderElement(id, layoutConfig, borderConfig) + return true } -@(deferred_none = Clay__CloseElementWithChildren) -Custom :: proc( - id: c.uint32_t, - layoutConfig: ^LayoutConfig, - customConfig: ^CustomElementConfig, -) -> bool { - Clay__OpenCustomElement(id, layoutConfig, customConfig) - return true +@(require_results, deferred_none = _CloseElementWithChildren) +Custom :: proc(id: c.uint32_t, layoutConfig: ^LayoutConfig, customConfig: ^CustomElementConfig) -> bool { + _OpenCustomElement(id, layoutConfig, customConfig) + return true } Layout :: proc(config: LayoutConfig) -> ^LayoutConfig { - return Clay__LayoutConfigArray_Add(&Clay__layoutConfigs, config) + return _LayoutConfigArray_Add(&_layoutConfigs, config) } RectangleConfig :: proc(config: RectangleElementConfig) -> ^RectangleElementConfig { - return Clay__RectangleElementConfigArray_Add(&Clay__rectangleElementConfigs, config) + return _RectangleElementConfigArray_Add(&_rectangleElementConfigs, config) } TextConfig :: proc(config: TextElementConfig) -> ^TextElementConfig { - return Clay__TextElementConfigArray_Add(&Clay__textElementConfigs, config) + return _TextElementConfigArray_Add(&_textElementConfigs, config) } ImageConfig :: proc(config: ImageElementConfig) -> ^ImageElementConfig { - return Clay__ImageElementConfigArray_Add(&Clay__imageElementConfigs, config) + return _ImageElementConfigArray_Add(&_imageElementConfigs, config) } FloatingConfig :: proc(config: FloatingElementConfig) -> ^FloatingElementConfig { - return Clay__FloatingElementConfigArray_Add(&Clay__floatingElementConfigs, config) + return _FloatingElementConfigArray_Add(&_floatingElementConfigs, config) } Custom_elementConfig :: proc(config: CustomElementConfig) -> ^CustomElementConfig { - return Clay__CustomElementConfigArray_Add(&Clay__customElementConfigs, config) + return _CustomElementConfigArray_Add(&_customElementConfigs, config) } ScrollConfig :: proc(config: ScrollElementConfig) -> ^ScrollElementConfig { - return Clay__ScrollElementConfigArray_Add(&Clay__scrollElementConfigs, config) + return _ScrollElementConfigArray_Add(&_scrollElementConfigs, config) } BorderConfig :: proc(config: BorderElementConfig) -> ^BorderElementConfig { - return Clay__BorderElementConfigArray_Add(&Clay__borderElementConfigs, config) + return _BorderElementConfigArray_Add(&_borderElementConfigs, config) } BorderConfigOutside :: proc(outsideBorders: BorderData) -> ^BorderElementConfig { - return Clay__BorderElementConfigArray_Add( - &Clay__borderElementConfigs, - (BorderElementConfig) { - left = outsideBorders, - right = outsideBorders, - top = outsideBorders, - bottom = outsideBorders, - }, - ) + return _BorderElementConfigArray_Add( + &_borderElementConfigs, + (BorderElementConfig){left = outsideBorders, right = outsideBorders, top = outsideBorders, bottom = outsideBorders}, + ) } -// BorderConfig_outside_radius :: proc(width, color, radius) Clay_BorderElementConfigArray_Add(&Clay__borderElementConfigs, (Clay_BorderElementConfig ) { .left = { width, color }, .right = { width, color }, .top = { width, color }, .bottom = { width, color }, .cornerRadius = { radius, radius, radius, radius } })) -> CLAY_BORDER_CONFIG_OUTSIDE_RADIUS +BorderConfigOutsideRadius :: proc(outsideBorders: BorderData, radius: f32) -> ^BorderElementConfig { + return _BorderElementConfigArray_Add( + &_borderElementConfigs, + (BorderElementConfig){left = outsideBorders, right = outsideBorders, top = outsideBorders, bottom = outsideBorders, cornerRadius = {radius, radius, radius, radius}}, + ) +} -// BorderConfig_all :: proc(...) Clay_BorderElementConfigArray_Add(&Clay__borderElementConfigs, (Clay_BorderElementConfig ) { .left = { __VA_ARGS__ }, .right = { __VA_ARGS__ }, .top = { __VA_ARGS__ }, .bottom = { __VA_ARGS__ }, .betweenChildren = { __VA_ARGS__ } })) -> CLAY_BORDER_CONFIG_ALL +BorderConfigAll :: proc(allBorders: BorderData) -> ^BorderElementConfig { + return _BorderElementConfigArray_Add( + &_borderElementConfigs, + (BorderElementConfig){left = allBorders, right = allBorders, top = allBorders, bottom = allBorders, betweenChildren = allBorders}, + ) +} -// BorderConfig_all_radius :: proc(width, color, radius) Clay_BorderElementConfigArray_Add(&Clay__borderElementConfigs, (Clay_BorderElementConfig ) { .left = { __VA_ARGS__ }, .right = { __VA_ARGS__ }, .top = { __VA_ARGS__ }, .bottom = { __VA_ARGS__ }, .betweenChildren = { __VA_ARGS__ }, .cornerRadius = { radius, radius, radius, radius }})) -> CLAY_BORDER_CONFIG_ALL_RADIUS +BorderConfigAllRadius :: proc(allBorders: BorderData, radius: f32) -> ^BorderElementConfig { + return _BorderElementConfigArray_Add( + &_borderElementConfigs, + (BorderElementConfig){left = allBorders, right = allBorders, top = allBorders, bottom = allBorders, cornerRadius = {radius, radius, radius, radius}}, + ) +} -// Corner_radius :: proc(radius) (Clay_CornerRadius) { radius, radius, radius, radius }) -> CLAY_CORNER_RADIUS +SizingFit :: proc(sizeMinMax: SizingConstraintsMinMax) -> SizingAxis { + return SizingAxis{type = SizingType.FIT, constraints = {sizeMinMax = sizeMinMax}} +} -// Sizing_fit :: proc(...) (Clay_SizingAxis) { .type = CLAY__SIZING_TYPE_FIT, .sizeMinMax = (Clay_SizingMinMax) {__VA_ARGS__} }) -> CLAY_SIZING_FIT +SizingGrow :: proc(sizeMinMax: SizingConstraintsMinMax) -> SizingAxis { + return SizingAxis{type = SizingType.GROW, constraints = {sizeMinMax = sizeMinMax}} +} -// Sizing_grow :: proc(...) (Clay_SizingAxis) { .type = CLAY__SIZING_TYPE_GROW, .sizeMinMax = (Clay_SizingMinMax) {__VA_ARGS__} }) -> CLAY_SIZING_GROW +SizingFixed :: proc(size: c.float) -> SizingAxis { + return SizingAxis{type = SizingType.FIT, constraints = {sizeMinMax = {size, size}}} +} -// Sizing_fixed :: proc(fixedSize) (Clay_SizingAxis) { .type = CLAY__SIZING_TYPE_GROW, .sizeMinMax = { fixedSize, fixedSize } }) -> CLAY_SIZING_FIXED +SizingPercent :: proc(sizePercent: c.float) -> SizingAxis { + return SizingAxis{type = SizingType.PERCENT, constraints = {sizePercent = sizePercent}} +} -// Sizing_percent :: proc(percentOfParent) (Clay_SizingAxis) { .type = CLAY__SIZING_TYPE_PERCENT, .sizePercent = percentOfParent }) -> CLAY_SIZING_PERCENT - -ClayString :: proc(label: string) -> String { - return String{chars = raw_data(label), length = cast(c.int)len(label)} +MakeString :: proc(label: string) -> String { + return String{chars = raw_data(label), length = cast(c.int)len(label)} } ID :: proc(label: string) -> c.uint32_t { - return Clay__HashString(ClayString(label), 0) + return _HashString(MakeString(label), 0) } IDI :: proc(label: string, index: u32) -> c.uint32_t { - return Clay__HashString(ClayString(label), index) + return _HashString(MakeString(label), index) } - -// _string_length :: proc(s) ((sizeof(s) / sizeof(s[0])) - sizeof(s[0]))) -> CLAY__STRING_LENGTH diff --git a/bindings/odin/clay_renderer_raylib.odin b/bindings/odin/clay_renderer_raylib.odin new file mode 100644 index 0000000..5a01534 --- /dev/null +++ b/bindings/odin/clay_renderer_raylib.odin @@ -0,0 +1,224 @@ +package main + +import clay "clay-odin" +import "core:math" +import "vendor:raylib" + +RaylibFont :: struct { + fontId: u32, + font: raylib.Font, +} + +clayColorToRaylibColor :: proc(color: clay.Color) -> raylib.Color { + return raylib.Color{cast(u8)color.r, cast(u8)color.g, cast(u8)color.b, cast(u8)color.a} +} + +raylibFonts := [10]RaylibFont{} + +measureText :: proc "c" (text: ^clay.String, config: ^clay.TextElementConfig) -> clay.Dimensions { + // Measure string size for Font + textSize: clay.Dimensions = {0, 0} + + maxTextWidth: f32 = 0 + lineTextWidth: f32 = 0 + + textHeight: f32 = cast(f32)config.fontSize + fontToUse: raylib.Font = raylibFonts[config.fontId].font + + for i := 0; i < cast(int)text.length; i += 1 { + if (text.chars[i] == '\n') { + maxTextWidth = math.max(maxTextWidth, lineTextWidth) + lineTextWidth = 0 + continue + } + index: i32 = cast(i32)text.chars[i] - 32 + if (fontToUse.glyphs[index].advanceX != 0) { + lineTextWidth += cast(f32)fontToUse.glyphs[index].advanceX + } else { + lineTextWidth += (fontToUse.recs[index].width + cast(f32)fontToUse.glyphs[index].offsetX) + } + } + + maxTextWidth = math.max(maxTextWidth, lineTextWidth) + + textSize.width = maxTextWidth / 2 + textSize.height = textHeight + + return textSize +} + +clayRaylibRender :: proc(renderCommands: ^clay.ClayArray(clay.RenderCommand)) { + for i := 0; i < cast(int)renderCommands.length; i += 1 { + renderCommand: ^clay.RenderCommand = clay.RenderCommandArray_Get(renderCommands, cast(i32)i) + boundingBox: clay.BoundingBox = renderCommand.boundingBox + switch (renderCommand.commandType) + { + case clay.RenderCommandType.None: + { + break + } + case clay.RenderCommandType.Text: + { + // Raylib uses standard C strings so isn't compatible with cheap slices, we need to clone the string to append null terminator + text: clay.String = renderCommand.text + cloned: []u8 = make([]u8, text.length + 1) + copy(cloned[0:text.length], text.chars[0:text.length]) + cloned[text.length] = 0 + fontToUse: raylib.Font = raylibFonts[renderCommand.config.textElementConfig.fontId].font + raylib.DrawTextEx( + fontToUse, + cstring(raw_data(cloned)), + raylib.Vector2{boundingBox.x, boundingBox.y}, + cast(f32)renderCommand.config.textElementConfig.fontSize, + cast(f32)renderCommand.config.textElementConfig.letterSpacing, + clayColorToRaylibColor(renderCommand.config.textElementConfig.textColor), + ) + delete(cloned) + break + } + case clay.RenderCommandType.Image: + { + imageTexture: ^raylib.Texture2D = cast(^raylib.Texture2D)renderCommand.config.imageElementConfig.imageData + raylib.DrawTextureEx(imageTexture^, raylib.Vector2{boundingBox.x, boundingBox.y}, 0, boundingBox.width / cast(f32)imageTexture.width, raylib.WHITE) + break + } + case clay.RenderCommandType.ScissorStart: + { + raylib.BeginScissorMode( + cast(i32)math.round(boundingBox.x), + cast(i32)math.round(boundingBox.y), + cast(i32)math.round(boundingBox.width), + cast(i32)math.round(boundingBox.height), + ) + break + } + case clay.RenderCommandType.ScissorEnd: + { + raylib.EndScissorMode() + break + } + case clay.RenderCommandType.Rectangle: + { + config: ^clay.RectangleElementConfig = renderCommand.config.rectangleElementConfig + if (config.cornerRadius.topLeft > 0) { + radius: f32 = (config.cornerRadius.topLeft * 2) / (boundingBox.width > boundingBox.height ? boundingBox.height : boundingBox.width) + raylib.DrawRectangleRounded( + raylib.Rectangle{boundingBox.x, boundingBox.y, boundingBox.width, boundingBox.height}, + radius, + 8, + clayColorToRaylibColor(config.color), + ) + } else { + raylib.DrawRectangle( + cast(i32)boundingBox.x, + cast(i32)boundingBox.y, + cast(i32)boundingBox.width, + cast(i32)boundingBox.height, + clayColorToRaylibColor(config.color), + ) + } + break + } + case clay.RenderCommandType.Border: + { + config: ^clay.BorderElementConfig = renderCommand.config.borderElementConfig + // Left border + if (config.left.width > 0) { + raylib.DrawRectangle( + cast(i32)math.round(boundingBox.x), + cast(i32)math.round(boundingBox.y + config.cornerRadius.topLeft), + cast(i32)config.left.width, + cast(i32)math.round(boundingBox.height - config.cornerRadius.topLeft - config.cornerRadius.bottomLeft), + clayColorToRaylibColor(config.left.color), + ) + } + // Right border + if (config.right.width > 0) { + raylib.DrawRectangle( + cast(i32)math.round(boundingBox.x + boundingBox.width - cast(f32)config.right.width), + cast(i32)math.round(boundingBox.y + config.cornerRadius.topRight), + cast(i32)config.right.width, + cast(i32)math.round(boundingBox.height - config.cornerRadius.topRight - config.cornerRadius.bottomRight), + clayColorToRaylibColor(config.right.color), + ) + } + // Top border + if (config.top.width > 0) { + raylib.DrawRectangle( + cast(i32)math.round(boundingBox.x + config.cornerRadius.topLeft), + cast(i32)math.round(boundingBox.y), + cast(i32)math.round(boundingBox.width - config.cornerRadius.topLeft - config.cornerRadius.topRight), + cast(i32)config.top.width, + clayColorToRaylibColor(config.top.color), + ) + } + // Bottom border + if (config.bottom.width > 0) { + raylib.DrawRectangle( + cast(i32)math.round(boundingBox.x + config.cornerRadius.bottomLeft), + cast(i32)math.round(boundingBox.y + boundingBox.height - cast(f32)config.bottom.width), + cast(i32)math.round(boundingBox.width - config.cornerRadius.bottomLeft - config.cornerRadius.bottomRight), + cast(i32)config.bottom.width, + clayColorToRaylibColor(config.bottom.color), + ) + } + if (config.cornerRadius.topLeft > 0) { + raylib.DrawRing( + raylib.Vector2{math.round(boundingBox.x + config.cornerRadius.topLeft), math.round(boundingBox.y + config.cornerRadius.topLeft)}, + math.round(config.cornerRadius.topLeft - cast(f32)config.top.width), + config.cornerRadius.topLeft, + 180, + 270, + 10, + clayColorToRaylibColor(config.top.color), + ) + } + if (config.cornerRadius.topRight > 0) { + raylib.DrawRing( + raylib.Vector2{math.round(boundingBox.x + boundingBox.width - config.cornerRadius.topRight), math.round(boundingBox.y + config.cornerRadius.topRight)}, + math.round(config.cornerRadius.topRight - cast(f32)config.top.width), + config.cornerRadius.topRight, + 270, + 360, + 10, + clayColorToRaylibColor(config.top.color), + ) + } + if (config.cornerRadius.bottomLeft > 0) { + raylib.DrawRing( + raylib.Vector2 { + math.round(boundingBox.x + config.cornerRadius.bottomLeft), + math.round(boundingBox.y + boundingBox.height - config.cornerRadius.bottomLeft), + }, + math.round(config.cornerRadius.bottomLeft - cast(f32)config.top.width), + config.cornerRadius.bottomLeft, + 90, + 180, + 10, + clayColorToRaylibColor(config.bottom.color), + ) + } + if (config.cornerRadius.bottomRight > 0) { + raylib.DrawRing( + raylib.Vector2 { + math.round(boundingBox.x + boundingBox.width - config.cornerRadius.bottomRight), + math.round(boundingBox.y + boundingBox.height - config.cornerRadius.bottomRight), + }, + math.round(config.cornerRadius.bottomRight - cast(f32)config.bottom.width), + config.cornerRadius.bottomRight, + 0.1, + 90, + 10, + clayColorToRaylibColor(config.bottom.color), + ) + } + break + } + case clay.RenderCommandType.Custom: + { + // Implement custom element rendering here + break + } + } + } +} diff --git a/bindings/odin/example.odin b/bindings/odin/example.odin new file mode 100644 index 0000000..fa572a5 --- /dev/null +++ b/bindings/odin/example.odin @@ -0,0 +1,54 @@ +package main + +import clay "clay-odin" +import "core:c" +import "core:fmt" +import "vendor:raylib" + +createLayout :: proc() -> clay.ClayArray(clay.RenderCommand) { + clay.BeginLayout(1024, 768) + layoutConfig: clay.LayoutConfig = clay.LayoutConfig { + sizing = {width = {type = clay.SizingType.GROW}, height = {type = clay.SizingType.GROW}}, + padding = {16, 16}, + } + rectangleConfig: clay.RectangleElementConfig = clay.RectangleElementConfig { + cornerRadius = {topLeft = 5}, + } + + if clay.Rectangle( + clay.ID("Outer Container"), + clay.Layout({sizing = {width = {type = clay.SizingType.GROW}, height = {type = clay.SizingType.GROW}}, padding = {16, 16}}), + clay.RectangleConfig({cornerRadius = {topLeft = 5}}), + ) { + if clay.Rectangle(clay.ID("Inner Container"), &layoutConfig, &rectangleConfig) { + if clay.Rectangle(clay.ID("percentContainer"), clay.Layout({sizing = {width = clay.SizingPercent(0.5)}}), clay.RectangleConfig({})) {} + if clay.Rectangle(clay.ID("growContainer"), clay.Layout({sizing = {width = clay.SizingGrow({max = 200})}}), clay.RectangleConfig({})) {} + clay.Text(clay.ID("textfield"), clay.MakeString("Texti"), clay.TextConfig({fontId = 0, fontSize = 24, textColor = {255, 255, 255, 255}})) + } + } + + return clay.EndLayout(1024, 768) +} + +main :: proc() { + minMemorySize: c.uint32_t = clay.MinMemorySize() + memory := make([^]u8, minMemorySize) + arena: clay.Arena = clay.CreateArenaWithCapacityAndMemory(minMemorySize, memory) + clay.SetMeasureTextFunction(measureText) + clay.Initialize(arena) + + raylib.InitWindow(1024, 768, "Raylib Odin Example") + + raylibFonts[0] = RaylibFont { + font = raylib.LoadFontEx("resources/Roboto-Regular.ttf", 32, nil, 0), + fontId = 0, + } + raylib.SetTextureFilter(raylibFonts[0].font.texture, raylib.TextureFilter.TRILINEAR) + + for !raylib.WindowShouldClose() { + renderCommands: clay.ClayArray(clay.RenderCommand) = createLayout() + raylib.BeginDrawing() + clayRaylibRender(&renderCommands) + raylib.EndDrawing() + } +} diff --git a/bindings/odin/main.odin b/bindings/odin/main.odin deleted file mode 100644 index fd1e403..0000000 --- a/bindings/odin/main.odin +++ /dev/null @@ -1,45 +0,0 @@ -package main - -import clay "clay-odin" -import "core:c" -import "core:fmt" - -measureText :: proc(text: [^]clay.String, config: [^]clay.TextElementConfig) -> clay.Dimensions { - return clay.Dimensions{20, 20} -} - -main :: proc() { - minMemorySize: c.uint32_t = clay.MinMemorySize() - memory := make([^]u8, minMemorySize) - arena: clay.Arena = clay.CreateArenaWithCapacityAndMemory(minMemorySize, memory) - clay.Initialize(arena) - clay.BeginLayout(1024, 768) - layoutConfig: clay.LayoutConfig = clay.LayoutConfig { - sizing = {width = {type = clay.SizingType.GROW}, height = {type = clay.SizingType.GROW}}, - padding = {16, 16}, - } - rectangleConfig: clay.RectangleElementConfig = clay.RectangleElementConfig { - cornerRadius = {topLeft = 5}, - } - - if clay.Rectangle( - clay.ID("Outer Container"), - clay.Layout( - { - sizing = { - width = {type = clay.SizingType.GROW}, - height = {type = clay.SizingType.GROW}, - }, - padding = {16, 16}, - }, - ), - clay.RectangleConfig({cornerRadius = {topLeft = 5}}), - ) { - if clay.Rectangle(clay.ID("Inner Container"), &layoutConfig, &rectangleConfig) { - - } - } - - renderCommands: clay.ClayArray(clay.RenderCommand) = clay.EndLayout(1024, 768) - x: int = 5 -} diff --git a/bindings/odin/odinfmt.json b/bindings/odin/odinfmt.json new file mode 100644 index 0000000..ee3d563 --- /dev/null +++ b/bindings/odin/odinfmt.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://raw.githubusercontent.com/DanielGavin/ols/master/misc/odinfmt.schema.json", + "character_width": 180, + "sort_imports": true, + "tabs": false +} \ No newline at end of file diff --git a/bindings/odin/resources/Roboto-Regular.ttf b/bindings/odin/resources/Roboto-Regular.ttf new file mode 100644 index 0000000..ddf4bfa Binary files /dev/null and b/bindings/odin/resources/Roboto-Regular.ttf differ