mirror of
				https://github.com/nicbarker/clay.git
				synced 2025-11-04 08:36:17 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			201 lines
		
	
	
		
			7.4 KiB
		
	
	
	
		
			Odin
		
	
	
	
	
	
			
		
		
	
	
			201 lines
		
	
	
		
			7.4 KiB
		
	
	
	
		
			Odin
		
	
	
	
	
	
package main
 | 
						|
 | 
						|
import clay "../../clay-odin"
 | 
						|
import "core:math"
 | 
						|
import "core:strings"
 | 
						|
import rl "vendor:raylib"
 | 
						|
 | 
						|
Raylib_Font :: struct {
 | 
						|
    fontId: u16,
 | 
						|
    font:   rl.Font,
 | 
						|
}
 | 
						|
 | 
						|
clay_color_to_rl_color :: proc(color: clay.Color) -> rl.Color {
 | 
						|
    return {u8(color.r), u8(color.g), u8(color.b), u8(color.a)}
 | 
						|
}
 | 
						|
 | 
						|
raylib_fonts := [dynamic]Raylib_Font{}
 | 
						|
 | 
						|
measure_text :: proc "c" (text: clay.StringSlice, config: ^clay.TextElementConfig, userData: rawptr) -> clay.Dimensions {
 | 
						|
    line_width: f32 = 0
 | 
						|
 | 
						|
    font := raylib_fonts[config.fontId].font
 | 
						|
 | 
						|
    for i in 0 ..< text.length {
 | 
						|
        glyph_index := text.chars[i] - 32
 | 
						|
 | 
						|
        glyph := font.glyphs[glyph_index]
 | 
						|
 | 
						|
        if glyph.advanceX != 0 {
 | 
						|
            line_width += f32(glyph.advanceX)
 | 
						|
        } else {
 | 
						|
            line_width += font.recs[glyph_index].width + f32(glyph.offsetX)
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    return {width = line_width / 2, height = f32(config.fontSize)}
 | 
						|
}
 | 
						|
 | 
						|
clay_raylib_render :: proc(render_commands: ^clay.ClayArray(clay.RenderCommand), allocator := context.temp_allocator) {
 | 
						|
    for i in 0 ..< render_commands.length {
 | 
						|
        render_command := clay.RenderCommandArray_Get(render_commands, i)
 | 
						|
        bounds := render_command.boundingBox
 | 
						|
 | 
						|
        switch render_command.commandType {
 | 
						|
        case .None: // None
 | 
						|
        case .Text:
 | 
						|
            config := render_command.renderData.text
 | 
						|
 | 
						|
            text := string(config.stringContents.chars[:config.stringContents.length])
 | 
						|
 | 
						|
            // Raylib uses C strings instead of Odin strings, so we need to clone
 | 
						|
            // Assume this will be freed elsewhere since we default to the temp allocator
 | 
						|
            cstr_text := strings.clone_to_cstring(text, allocator)
 | 
						|
 | 
						|
            font := raylib_fonts[config.fontId].font
 | 
						|
            rl.DrawTextEx(font, cstr_text, {bounds.x, bounds.y}, f32(config.fontSize), f32(config.letterSpacing), clay_color_to_rl_color(config.textColor))
 | 
						|
        case .Image:
 | 
						|
            config := render_command.renderData.image
 | 
						|
            tint := config.backgroundColor
 | 
						|
            if tint == 0 {
 | 
						|
                tint = {255, 255, 255, 255}
 | 
						|
            }
 | 
						|
 | 
						|
            imageTexture := (^rl.Texture2D)(config.imageData)
 | 
						|
            rl.DrawTextureEx(imageTexture^, {bounds.x, bounds.y}, 0, bounds.width / f32(imageTexture.width), clay_color_to_rl_color(tint))
 | 
						|
        case .ScissorStart:
 | 
						|
            rl.BeginScissorMode(i32(math.round(bounds.x)), i32(math.round(bounds.y)), i32(math.round(bounds.width)), i32(math.round(bounds.height)))
 | 
						|
        case .ScissorEnd:
 | 
						|
            rl.EndScissorMode()
 | 
						|
        case .Rectangle:
 | 
						|
            config := render_command.renderData.rectangle
 | 
						|
            if config.cornerRadius.topLeft > 0 {
 | 
						|
                radius: f32 = (config.cornerRadius.topLeft * 2) / min(bounds.width, bounds.height)
 | 
						|
                draw_rect_rounded(bounds.x, bounds.y, bounds.width, bounds.height, radius, config.backgroundColor)
 | 
						|
            } else {
 | 
						|
                draw_rect(bounds.x, bounds.y, bounds.width, bounds.height, config.backgroundColor)
 | 
						|
            }
 | 
						|
        case .Border:
 | 
						|
            config := render_command.renderData.border
 | 
						|
            // Left border
 | 
						|
            if config.width.left > 0 {
 | 
						|
                draw_rect(
 | 
						|
                    bounds.x,
 | 
						|
                    bounds.y + config.cornerRadius.topLeft,
 | 
						|
                    f32(config.width.left),
 | 
						|
                    bounds.height - config.cornerRadius.topLeft - config.cornerRadius.bottomLeft,
 | 
						|
                    config.color,
 | 
						|
                )
 | 
						|
            }
 | 
						|
            // Right border
 | 
						|
            if config.width.right > 0 {
 | 
						|
                draw_rect(
 | 
						|
                    bounds.x + bounds.width - f32(config.width.right),
 | 
						|
                    bounds.y + config.cornerRadius.topRight,
 | 
						|
                    f32(config.width.right),
 | 
						|
                    bounds.height - config.cornerRadius.topRight - config.cornerRadius.bottomRight,
 | 
						|
                    config.color,
 | 
						|
                )
 | 
						|
            }
 | 
						|
            // Top border
 | 
						|
            if config.width.top > 0 {
 | 
						|
                draw_rect(
 | 
						|
                    bounds.x + config.cornerRadius.topLeft,
 | 
						|
                    bounds.y,
 | 
						|
                    bounds.width - config.cornerRadius.topLeft - config.cornerRadius.topRight,
 | 
						|
                    f32(config.width.top),
 | 
						|
                    config.color,
 | 
						|
                )
 | 
						|
            }
 | 
						|
            // Bottom border
 | 
						|
            if config.width.bottom > 0 {
 | 
						|
                draw_rect(
 | 
						|
                    bounds.x + config.cornerRadius.bottomLeft,
 | 
						|
                    bounds.y + bounds.height - f32(config.width.bottom),
 | 
						|
                    bounds.width - config.cornerRadius.bottomLeft - config.cornerRadius.bottomRight,
 | 
						|
                    f32(config.width.bottom),
 | 
						|
                    config.color,
 | 
						|
                )
 | 
						|
            }
 | 
						|
 | 
						|
            // Rounded Borders
 | 
						|
            if config.cornerRadius.topLeft > 0 {
 | 
						|
                draw_arc(
 | 
						|
                    bounds.x + config.cornerRadius.topLeft, 
 | 
						|
                    bounds.y + config.cornerRadius.topLeft,
 | 
						|
                    config.cornerRadius.topLeft - f32(config.width.top),
 | 
						|
                    config.cornerRadius.topLeft,
 | 
						|
                    180,
 | 
						|
                    270,
 | 
						|
                    config.color,
 | 
						|
                )
 | 
						|
            }
 | 
						|
            if config.cornerRadius.topRight > 0 {
 | 
						|
                draw_arc(
 | 
						|
                    bounds.x + bounds.width - config.cornerRadius.topRight,
 | 
						|
                    bounds.y + config.cornerRadius.topRight,
 | 
						|
                    config.cornerRadius.topRight - f32(config.width.top),
 | 
						|
                    config.cornerRadius.topRight,
 | 
						|
                    270,
 | 
						|
                    360,
 | 
						|
                    config.color,
 | 
						|
                )
 | 
						|
            }
 | 
						|
            if config.cornerRadius.bottomLeft > 0 {
 | 
						|
                draw_arc(
 | 
						|
                    bounds.x + config.cornerRadius.bottomLeft,
 | 
						|
                    bounds.y + bounds.height - config.cornerRadius.bottomLeft,
 | 
						|
                    config.cornerRadius.bottomLeft - f32(config.width.top),
 | 
						|
                    config.cornerRadius.bottomLeft,
 | 
						|
                    90,
 | 
						|
                    180,
 | 
						|
                    config.color,
 | 
						|
                )
 | 
						|
            }
 | 
						|
            if config.cornerRadius.bottomRight > 0 {
 | 
						|
                draw_arc(
 | 
						|
                    bounds.x + bounds.width - config.cornerRadius.bottomRight, 
 | 
						|
                    bounds.y + bounds.height - config.cornerRadius.bottomRight,
 | 
						|
                    config.cornerRadius.bottomRight - f32(config.width.bottom),
 | 
						|
                    config.cornerRadius.bottomRight,
 | 
						|
                    0.1,
 | 
						|
                    90,
 | 
						|
                    config.color,
 | 
						|
                )
 | 
						|
            }
 | 
						|
        case clay.RenderCommandType.Custom:
 | 
						|
            // Implement custom element rendering here
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
// Helper procs, mainly for repeated conversions
 | 
						|
 | 
						|
@(private = "file")
 | 
						|
draw_arc :: proc(x, y: f32, inner_rad, outer_rad: f32,start_angle, end_angle: f32, color: clay.Color){
 | 
						|
    rl.DrawRing(
 | 
						|
        {math.round(x),math.round(y)},
 | 
						|
        math.round(inner_rad),
 | 
						|
        outer_rad,
 | 
						|
        start_angle,
 | 
						|
        end_angle,
 | 
						|
        10,
 | 
						|
        clay_color_to_rl_color(color),
 | 
						|
    )
 | 
						|
}
 | 
						|
 | 
						|
@(private = "file")
 | 
						|
draw_rect :: proc(x, y, w, h: f32, color: clay.Color) {
 | 
						|
    rl.DrawRectangle(
 | 
						|
        i32(math.round(x)), 
 | 
						|
        i32(math.round(y)), 
 | 
						|
        i32(math.round(w)), 
 | 
						|
        i32(math.round(h)), 
 | 
						|
        clay_color_to_rl_color(color)
 | 
						|
    )
 | 
						|
}
 | 
						|
 | 
						|
@(private = "file")
 | 
						|
draw_rect_rounded :: proc(x,y,w,h: f32, radius: f32, color: clay.Color){
 | 
						|
    rl.DrawRectangleRounded({x,y,w,h},radius,8,clay_color_to_rl_color(color))
 | 
						|
} |