mirror of
https://github.com/nicbarker/clay.git
synced 2025-11-01 15:26:17 +00:00
Clean up SDL code and fix sloppy mistakes
This commit is contained in:
parent
eb8368216a
commit
6824a942a7
|
|
@ -100,7 +100,7 @@ video_demo_layout :: proc(data: ^Video_Demo_Data) -> clay.ClayArray(clay.RenderC
|
|||
// Child elements go inside braces
|
||||
if clay.UI(clay.ID("HeaderBar"))(
|
||||
{
|
||||
layout = {sizing = {height = clay.SizingFixed(60), width = clay.SizingFixed(0)}, padding = {16, 16, 0, 0}, childGap = 16, childAlignment = {y = .Center}},
|
||||
layout = {sizing = {height = clay.SizingFixed(60), width = clay.SizingGrow()}, padding = {16, 16, 0, 0}, childGap = 16, childAlignment = {y = .Center}},
|
||||
backgroundColor = contentBackgroundColor,
|
||||
cornerRadius = clay.CornerRadiusAll(8),
|
||||
},
|
||||
|
|
@ -154,7 +154,7 @@ video_demo_layout :: proc(data: ^Video_Demo_Data) -> clay.ClayArray(clay.RenderC
|
|||
clay.TextDynamic(document.title, clay.TextConfig({fontId = VIDEO_DEMO_FONT_ID_BODY, fontSize = 20, textColor = {255, 255, 255, 255}}))
|
||||
}
|
||||
} else {
|
||||
clickData := new_clone((Sidebar_Click_Data) {
|
||||
clickData := new_clone(Sidebar_Click_Data {
|
||||
requestedDocumentIndex = i,
|
||||
selectedDocumentIndex = &data.selectedDocumentIndex,
|
||||
}, context.temp_allocator)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
Odin doesn't directly package SDL, so on Windows, you'll want to copy `SDL3.dll` and `SDL3_ttf.dll` into this directory. On Linux and Mac, you should install SDL3 via your package manager
|
||||
Odin doesn't directly package SDL, so on Windows, you'll want to copy `SDL3.dll` and `SDL3_ttf.dll` into this directory from odin's `vendor/sdl3` directory located next to the compiler. You can use `odin root` to figure out where your compiler is installed. On Linux and Mac, you should install SDL3 via your package manager
|
||||
|
||||
## Running on Windows
|
||||
In an embdedded termninal, missing dependencies will fail silently on Windows, so if you have any unexplainable crashes, make sure the DLLs are in your current working directory (the path you run the command from). It's easiest to just copy them next to this file, and run from here as well.
|
||||
|
|
@ -10,7 +10,7 @@ import "vendor:sdl3/ttf"
|
|||
|
||||
App_State :: struct {
|
||||
window: ^sdl.Window,
|
||||
rendererData: Clay_SDL3RendererData,
|
||||
rendererData: Clay_SDL_Render_Data,
|
||||
}
|
||||
|
||||
state: App_State
|
||||
|
|
@ -22,7 +22,7 @@ errorHandler :: proc "c" (errorData: clay.ErrorData) {
|
|||
}
|
||||
|
||||
load_font :: proc(data: []byte, size: f32, id: u16, fonts: ^[dynamic]^ttf.Font) {
|
||||
font_stream := sdl.IOFromConstMem(raw_data(ROBOTO), uint(len(ROBOTO)))
|
||||
font_stream := sdl.IOFromConstMem(raw_data(data), uint(len(data)))
|
||||
font := ttf.OpenFontIO(font_stream, true, size * 2)
|
||||
assign_at(fonts, int(id), font)
|
||||
}
|
||||
|
|
@ -38,7 +38,7 @@ measure_text :: proc "c" (text: clay.StringSlice, config: ^clay.TextElementConfi
|
|||
sdl.LogError(i32(sdl.LogCategory.ERROR), "Failed to measure text: %s", sdl.GetError())
|
||||
}
|
||||
|
||||
return clay.Dimensions{f32(width), f32(height)}
|
||||
return {f32(width), f32(height)}
|
||||
}
|
||||
// Load at compile time, directly into the binary
|
||||
ROBOTO := #load("./Roboto-Regular.ttf")
|
||||
|
|
@ -58,9 +58,9 @@ main :: proc() {
|
|||
|
||||
state.window = window
|
||||
state.rendererData.renderer = renderer
|
||||
state.rendererData.textEngine = ttf.CreateRendererTextEngine(renderer)
|
||||
state.rendererData.text_engine = ttf.CreateRendererTextEngine(renderer)
|
||||
|
||||
minMemorySize := (uint)(clay.MinMemorySize())
|
||||
minMemorySize := uint(clay.MinMemorySize())
|
||||
arena: clay.Arena = clay.CreateArenaWithCapacityAndMemory(minMemorySize, make([^]u8, minMemorySize))
|
||||
clay.Initialize(arena, {1280, 720}, {handler = errorHandler})
|
||||
clay.SetMeasureTextFunction(measure_text, &state.rendererData.fonts)
|
||||
|
|
@ -78,12 +78,10 @@ main :: proc() {
|
|||
window_width, window_height: i32
|
||||
|
||||
for !done {
|
||||
defer free_all(context.temp_allocator)
|
||||
|
||||
scrollDelta: clay.Vector2
|
||||
|
||||
for (sdl.PollEvent(&event)) {
|
||||
if (event.type == .QUIT) {
|
||||
for sdl.PollEvent(&event) {
|
||||
if event.type == .QUIT {
|
||||
done = true
|
||||
} else if event.type == .MOUSE_WHEEL {
|
||||
scrollDelta.x = event.wheel.x
|
||||
|
|
@ -99,10 +97,8 @@ main :: proc() {
|
|||
|
||||
clay.SetLayoutDimensions({width = f32(window_width), height = f32(window_height)})
|
||||
|
||||
mouseX: f32 = 0
|
||||
mouseY: f32 = 0
|
||||
mouseState := sdl.GetMouseState(&mouseX, &mouseY)
|
||||
mousePosition := (clay.Vector2){mouseX, mouseY}
|
||||
mousePosition : clay.Vector2
|
||||
mouseState := sdl.GetMouseState(&mousePosition.x, &mousePosition.y)
|
||||
clay.SetPointerState(mousePosition, .LEFT in mouseState)
|
||||
|
||||
clay.UpdateScrollContainers(false, scrollDelta, f32(deltaTime))
|
||||
|
|
@ -112,7 +108,7 @@ main :: proc() {
|
|||
|
||||
sdl.SetRenderDrawColor(renderer, 0, 0, 0, 255)
|
||||
sdl.RenderClear(renderer)
|
||||
sdl_Clay_RenderClayCommands(&state.rendererData, &commands)
|
||||
sdl_render_clay_commands(&state.rendererData, &commands)
|
||||
|
||||
sdl.RenderPresent(renderer)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,16 +3,17 @@ package video_demo_sdl
|
|||
|
||||
import clay "../../clay-odin"
|
||||
import "core:math"
|
||||
import "core:math/linalg"
|
||||
import sdl "vendor:sdl3"
|
||||
import "vendor:sdl3/ttf"
|
||||
|
||||
Clay_SDL3RendererData :: struct {
|
||||
renderer: ^sdl.Renderer,
|
||||
textEngine: ^ttf.TextEngine,
|
||||
fonts: [dynamic]^ttf.Font,
|
||||
Clay_SDL_Render_Data :: struct {
|
||||
renderer: ^sdl.Renderer,
|
||||
text_engine: ^ttf.TextEngine,
|
||||
fonts: [dynamic]^ttf.Font,
|
||||
}
|
||||
|
||||
// SDL_ttf works in pts, but clay expects pixels.
|
||||
// SDL_ttf works in pts, but clay expects pixels.
|
||||
// 0.85 looks correct from what I've seen, but this calculation is probably incorrect.
|
||||
px_to_pt :: proc "contextless" (pixels: f32) -> f32 {
|
||||
return pixels * 0.85
|
||||
|
|
@ -24,432 +25,287 @@ px_to_pt :: proc "contextless" (pixels: f32) -> f32 {
|
|||
NUM_CIRCLE_SEGMENTS :: 16
|
||||
|
||||
//all rendering is performed by a single SDL call, avoiding multiple RenderRect + plumbing choice for circles.
|
||||
sdl_Clay_RenderFillRoundedRect :: proc(
|
||||
rendererData: ^Clay_SDL3RendererData,
|
||||
rect: sdl.FRect,
|
||||
cornerRadius: f32,
|
||||
_color: clay.Color,
|
||||
) {
|
||||
color := sdl.FColor(_color / 255)
|
||||
@(private = "file")
|
||||
fill_rounded_rect :: proc(rendererData: ^Clay_SDL_Render_Data, rect: sdl.FRect, cornerRadius: f32, _color: clay.Color) {
|
||||
color := sdl.FColor(_color / 255)
|
||||
|
||||
indexCount: i32 = 0
|
||||
vertexCount: i32 = 0
|
||||
indexCount: i32 = 0
|
||||
vertexCount: i32 = 0
|
||||
|
||||
minRadius := sdl.min(rect.w, rect.h) / 2
|
||||
clampedRadius := sdl.min(cornerRadius, minRadius)
|
||||
minRadius := min(rect.w, rect.h) / 2
|
||||
clampedRadius := min(cornerRadius, minRadius)
|
||||
|
||||
numCircleSegments := sdl.max(NUM_CIRCLE_SEGMENTS, i32(clampedRadius * 0.5))
|
||||
numCircleSegments := max(NUM_CIRCLE_SEGMENTS, i32(clampedRadius * 0.5))
|
||||
|
||||
totalVertices := 4 + (4 * (numCircleSegments * 2)) + 2 * 4
|
||||
totalIndices := 6 + (4 * (numCircleSegments * 3)) + 6 * 4
|
||||
totalVertices := 4 + (4 * (numCircleSegments * 2)) + 2 * 4
|
||||
totalIndices := 6 + (4 * (numCircleSegments * 3)) + 6 * 4
|
||||
|
||||
// Maybe instrinsics.alloca these?
|
||||
vertices := make([]sdl.Vertex, totalVertices, allocator = context.temp_allocator)
|
||||
indices := make([]i32, totalIndices, allocator = context.temp_allocator)
|
||||
// Maybe instrinsics.alloca these?
|
||||
vertices := make([]sdl.Vertex, totalVertices, allocator = context.temp_allocator)
|
||||
indices := make([]i32, totalIndices, allocator = context.temp_allocator)
|
||||
|
||||
//define center rectangle
|
||||
vertices[vertexCount + 0] = (sdl.Vertex) {
|
||||
{rect.x + clampedRadius, rect.y + clampedRadius},
|
||||
color,
|
||||
{0, 0},
|
||||
} //0 center TL
|
||||
vertices[vertexCount + 1] = (sdl.Vertex) {
|
||||
{rect.x + rect.w - clampedRadius, rect.y + clampedRadius},
|
||||
color,
|
||||
{1, 0},
|
||||
} //1 center TR
|
||||
vertices[vertexCount + 2] = (sdl.Vertex) {
|
||||
{rect.x + rect.w - clampedRadius, rect.y + rect.h - clampedRadius},
|
||||
color,
|
||||
{1, 1},
|
||||
} //2 center BR
|
||||
vertices[vertexCount + 3] = (sdl.Vertex) {
|
||||
{rect.x + clampedRadius, rect.y + rect.h - clampedRadius},
|
||||
color,
|
||||
{0, 1},
|
||||
} //3 center BL
|
||||
//define center rectangle
|
||||
vertices[vertexCount + 0] = {{rect.x + clampedRadius, rect.y + clampedRadius}, color, {0, 0}} //0 center TL
|
||||
vertices[vertexCount + 1] = {{rect.x + rect.w - clampedRadius, rect.y + clampedRadius}, color, {1, 0}} //1 center TR
|
||||
vertices[vertexCount + 2] = {{rect.x + rect.w - clampedRadius, rect.y + rect.h - clampedRadius}, color, {1, 1}} //2 center BR
|
||||
vertices[vertexCount + 3] = {{rect.x + clampedRadius, rect.y + rect.h - clampedRadius}, color, {0, 1}} //3 center BL
|
||||
|
||||
vertexCount += 4
|
||||
vertexCount += 4
|
||||
|
||||
indices[indexCount + 0] = 0
|
||||
indices[indexCount + 1] = 1
|
||||
indices[indexCount + 2] = 3
|
||||
indices[indexCount + 3] = 1
|
||||
indices[indexCount + 4] = 2
|
||||
indices[indexCount + 5] = 3
|
||||
indices[indexCount + 0] = 0
|
||||
indices[indexCount + 1] = 1
|
||||
indices[indexCount + 2] = 3
|
||||
indices[indexCount + 3] = 1
|
||||
indices[indexCount + 4] = 2
|
||||
indices[indexCount + 5] = 3
|
||||
|
||||
indexCount += 6
|
||||
indexCount += 6
|
||||
|
||||
//define rounded corners as triangle fans
|
||||
step := (f32(math.PI) / 2) / f32(numCircleSegments)
|
||||
for i in 0 ..< numCircleSegments {
|
||||
angle1 := f32(i) * step
|
||||
angle2 := (f32(i) + 1) * step
|
||||
//define rounded corners as triangle fans
|
||||
step := (f32(math.PI) / 2) / f32(numCircleSegments)
|
||||
for i in 0 ..< numCircleSegments {
|
||||
angle1 := f32(i) * step
|
||||
angle2 := (f32(i) + 1) * step
|
||||
|
||||
for j in i32(0) ..< 4 { // Iterate over four corners
|
||||
cx, cy, signX, signY: f32
|
||||
for j in i32(0) ..< 4 { // Iterate over four corners
|
||||
cx, cy, signX, signY: f32
|
||||
|
||||
switch (j) {
|
||||
case 0:
|
||||
cx = rect.x + clampedRadius
|
||||
cy = rect.y + clampedRadius
|
||||
signX = -1
|
||||
signY = -1
|
||||
// Top-left
|
||||
case 1:
|
||||
cx = rect.x + rect.w - clampedRadius
|
||||
cy = rect.y + clampedRadius
|
||||
signX = 1
|
||||
signY = -1 // Top-right
|
||||
case 2:
|
||||
cx = rect.x + rect.w - clampedRadius
|
||||
cy = rect.y + rect.h - clampedRadius
|
||||
signX = 1
|
||||
signY = 1 // Bottom-right
|
||||
case 3:
|
||||
cx = rect.x + clampedRadius
|
||||
cy = rect.y + rect.h - clampedRadius
|
||||
signX = -1
|
||||
signY = 1 // Bottom-left
|
||||
case:
|
||||
return
|
||||
}
|
||||
switch j {
|
||||
case 0:
|
||||
cx = rect.x + clampedRadius
|
||||
cy = rect.y + clampedRadius
|
||||
signX = -1
|
||||
signY = -1
|
||||
// Top-left
|
||||
case 1:
|
||||
cx = rect.x + rect.w - clampedRadius
|
||||
cy = rect.y + clampedRadius
|
||||
signX = 1
|
||||
signY = -1 // Top-right
|
||||
case 2:
|
||||
cx = rect.x + rect.w - clampedRadius
|
||||
cy = rect.y + rect.h - clampedRadius
|
||||
signX = 1
|
||||
signY = 1 // Bottom-right
|
||||
case 3:
|
||||
cx = rect.x + clampedRadius
|
||||
cy = rect.y + rect.h - clampedRadius
|
||||
signX = -1
|
||||
signY = 1 // Bottom-left
|
||||
case:
|
||||
return
|
||||
}
|
||||
|
||||
vertices[vertexCount + 0] = (sdl.Vertex) {
|
||||
{
|
||||
cx + sdl.cosf(angle1) * clampedRadius * signX,
|
||||
cy + sdl.sinf(angle1) * clampedRadius * signY,
|
||||
},
|
||||
color,
|
||||
{0, 0},
|
||||
}
|
||||
vertices[vertexCount + 1] = (sdl.Vertex) {
|
||||
{
|
||||
cx + sdl.cosf(angle2) * clampedRadius * signX,
|
||||
cy + sdl.sinf(angle2) * clampedRadius * signY,
|
||||
},
|
||||
color,
|
||||
{0, 0},
|
||||
}
|
||||
vertices[vertexCount + 0] = {{cx + math.cos(angle1) * clampedRadius * signX, cy + math.sin(angle1) * clampedRadius * signY}, color, {0, 0}}
|
||||
vertices[vertexCount + 1] = {{cx + math.cos(angle2) * clampedRadius * signX, cy + math.sin(angle2) * clampedRadius * signY}, color, {0, 0}}
|
||||
|
||||
vertexCount += 2
|
||||
vertexCount += 2
|
||||
|
||||
indices[indexCount + 0] = j // Connect to corresponding central rectangle vertex
|
||||
indices[indexCount + 1] = vertexCount - 2
|
||||
indices[indexCount + 2] = vertexCount - 1
|
||||
indexCount += 3
|
||||
}
|
||||
}
|
||||
indices[indexCount + 0] = j // Connect to corresponding central rectangle vertex
|
||||
indices[indexCount + 1] = vertexCount - 2
|
||||
indices[indexCount + 2] = vertexCount - 1
|
||||
indexCount += 3
|
||||
}
|
||||
}
|
||||
|
||||
//Define edge rectangles
|
||||
// Top edge
|
||||
vertices[vertexCount + 0] = (sdl.Vertex){{rect.x + clampedRadius, rect.y}, color, {0, 0}} //TL
|
||||
vertices[vertexCount + 1] = (sdl.Vertex) {
|
||||
{rect.x + rect.w - clampedRadius, rect.y},
|
||||
color,
|
||||
{1, 0},
|
||||
} //TR
|
||||
//Define edge rectangles
|
||||
// Top edge
|
||||
vertices[vertexCount + 0] = {{rect.x + clampedRadius, rect.y}, color, {0, 0}} //TL
|
||||
vertices[vertexCount + 1] = {{rect.x + rect.w - clampedRadius, rect.y}, color, {1, 0}} //TR
|
||||
|
||||
vertexCount += 2
|
||||
vertexCount += 2
|
||||
|
||||
indices[indexCount + 0] = 0
|
||||
indices[indexCount + 1] = vertexCount - 2 //TL
|
||||
indices[indexCount + 2] = vertexCount - 1 //TR
|
||||
indices[indexCount + 3] = 1
|
||||
indices[indexCount + 4] = 0
|
||||
indices[indexCount + 5] = vertexCount - 1 //TR
|
||||
indexCount += 6
|
||||
// Right edge
|
||||
vertices[vertexCount + 0] = (sdl.Vertex) {
|
||||
{rect.x + rect.w, rect.y + clampedRadius},
|
||||
color,
|
||||
{1, 0},
|
||||
} //RT
|
||||
vertices[vertexCount + 1] = (sdl.Vertex) {
|
||||
{rect.x + rect.w, rect.y + rect.h - clampedRadius},
|
||||
color,
|
||||
{1, 1},
|
||||
} //RB
|
||||
vertexCount += 2
|
||||
indices[indexCount + 0] = 0
|
||||
indices[indexCount + 1] = vertexCount - 2 //TL
|
||||
indices[indexCount + 2] = vertexCount - 1 //TR
|
||||
indices[indexCount + 3] = 1
|
||||
indices[indexCount + 4] = 0
|
||||
indices[indexCount + 5] = vertexCount - 1 //TR
|
||||
indexCount += 6
|
||||
// Right edge
|
||||
vertices[vertexCount + 0] = {{rect.x + rect.w, rect.y + clampedRadius}, color, {1, 0}} //RT
|
||||
vertices[vertexCount + 1] = {{rect.x + rect.w, rect.y + rect.h - clampedRadius}, color, {1, 1}} //RB
|
||||
vertexCount += 2
|
||||
|
||||
indices[indexCount + 0] = 1
|
||||
indices[indexCount + 1] = vertexCount - 2 //RT
|
||||
indices[indexCount + 2] = vertexCount - 1 //RB
|
||||
indices[indexCount + 3] = 2
|
||||
indices[indexCount + 4] = 1
|
||||
indices[indexCount + 5] = vertexCount - 1 //RB
|
||||
indexCount += 6
|
||||
indices[indexCount + 0] = 1
|
||||
indices[indexCount + 1] = vertexCount - 2 //RT
|
||||
indices[indexCount + 2] = vertexCount - 1 //RB
|
||||
indices[indexCount + 3] = 2
|
||||
indices[indexCount + 4] = 1
|
||||
indices[indexCount + 5] = vertexCount - 1 //RB
|
||||
indexCount += 6
|
||||
|
||||
// Bottom edge
|
||||
vertices[vertexCount + 0] = (sdl.Vertex) {
|
||||
{rect.x + rect.w - clampedRadius, rect.y + rect.h},
|
||||
color,
|
||||
{1, 1},
|
||||
} //BR
|
||||
vertices[vertexCount + 1] = (sdl.Vertex) {
|
||||
{rect.x + clampedRadius, rect.y + rect.h},
|
||||
color,
|
||||
{0, 1},
|
||||
} //BL
|
||||
vertexCount += 2
|
||||
// Bottom edge
|
||||
vertices[vertexCount + 0] = {{rect.x + rect.w - clampedRadius, rect.y + rect.h}, color, {1, 1}} //BR
|
||||
vertices[vertexCount + 1] = {{rect.x + clampedRadius, rect.y + rect.h}, color, {0, 1}} //BL
|
||||
vertexCount += 2
|
||||
|
||||
indices[indexCount + 0] = 2
|
||||
indices[indexCount + 1] = vertexCount - 2 //BR
|
||||
indices[indexCount + 2] = vertexCount - 1 //BL
|
||||
indices[indexCount + 3] = 3
|
||||
indices[indexCount + 4] = 2
|
||||
indices[indexCount + 5] = vertexCount - 1 //BL
|
||||
indexCount += 6
|
||||
indices[indexCount + 0] = 2
|
||||
indices[indexCount + 1] = vertexCount - 2 //BR
|
||||
indices[indexCount + 2] = vertexCount - 1 //BL
|
||||
indices[indexCount + 3] = 3
|
||||
indices[indexCount + 4] = 2
|
||||
indices[indexCount + 5] = vertexCount - 1 //BL
|
||||
indexCount += 6
|
||||
|
||||
// Left edge
|
||||
vertices[vertexCount + 0] = (sdl.Vertex) {
|
||||
{rect.x, rect.y + rect.h - clampedRadius},
|
||||
color,
|
||||
{0, 1},
|
||||
} //LB
|
||||
vertices[vertexCount + 1] = (sdl.Vertex){{rect.x, rect.y + clampedRadius}, color, {0, 0}} //LT
|
||||
vertexCount += 2
|
||||
// Left edge
|
||||
vertices[vertexCount + 0] = {{rect.x, rect.y + rect.h - clampedRadius}, color, {0, 1}} //LB
|
||||
vertices[vertexCount + 1] = {{rect.x, rect.y + clampedRadius}, color, {0, 0}} //LT
|
||||
vertexCount += 2
|
||||
|
||||
indices[indexCount + 0] = 3
|
||||
indices[indexCount + 1] = vertexCount - 2 //LB
|
||||
indices[indexCount + 2] = vertexCount - 1 //LT
|
||||
indices[indexCount + 3] = 0
|
||||
indices[indexCount + 4] = 3
|
||||
indices[indexCount + 5] = vertexCount - 1 //LT
|
||||
indexCount += 6
|
||||
indices[indexCount + 0] = 3
|
||||
indices[indexCount + 1] = vertexCount - 2 //LB
|
||||
indices[indexCount + 2] = vertexCount - 1 //LT
|
||||
indices[indexCount + 3] = 0
|
||||
indices[indexCount + 4] = 3
|
||||
indices[indexCount + 5] = vertexCount - 1 //LT
|
||||
indexCount += 6
|
||||
|
||||
// Render everything
|
||||
sdl.RenderGeometry(
|
||||
rendererData.renderer,
|
||||
nil,
|
||||
raw_data(vertices),
|
||||
vertexCount,
|
||||
raw_data(indices),
|
||||
indexCount,
|
||||
)
|
||||
// Render everything
|
||||
sdl.RenderGeometry(rendererData.renderer, nil, raw_data(vertices), vertexCount, raw_data(indices), indexCount)
|
||||
}
|
||||
|
||||
sdl_Clay_RenderArc :: proc(
|
||||
rendererData: ^Clay_SDL3RendererData,
|
||||
center: sdl.FPoint,
|
||||
radius: f32,
|
||||
startAngle: f32,
|
||||
endAngle: f32,
|
||||
thickness: f32,
|
||||
color: clay.Color,
|
||||
) {
|
||||
sdl.SetRenderDrawColor(
|
||||
rendererData.renderer,
|
||||
u8(color.r),
|
||||
u8(color.g),
|
||||
u8(color.b),
|
||||
u8(color.a),
|
||||
)
|
||||
@(private = "file")
|
||||
render_arc :: proc(rendererData: ^Clay_SDL_Render_Data, center: sdl.FPoint, radius: f32, startAngle: f32, endAngle: f32, thickness: f32, color: clay.Color) {
|
||||
sdl.SetRenderDrawColor(rendererData.renderer, clay_to_sdl_color(color))
|
||||
|
||||
radStart := startAngle * (math.PI / 180.0)
|
||||
radEnd := endAngle * (math.PI / 180.0)
|
||||
radStart := math.to_radians(startAngle)
|
||||
radEnd := math.to_radians(endAngle)
|
||||
|
||||
numCircleSegments := sdl.max(NUM_CIRCLE_SEGMENTS, i32(radius * 1.5)) //increase circle segments for larger circles, 1.5 is arbitrary.
|
||||
numCircleSegments := max(NUM_CIRCLE_SEGMENTS, i32(radius * 1.5)) //increase circle segments for larger circles, 1.5 is arbitrary.
|
||||
|
||||
angleStep := (radEnd - radStart) / f32(numCircleSegments)
|
||||
thicknessStep: f32 = 0.4 //arbitrary value to avoid overlapping lines. Changing THICKNESS_STEP or numCircleSegments might cause artifacts.
|
||||
angleStep := (radEnd - radStart) / f32(numCircleSegments)
|
||||
thicknessStep: f32 = 0.4 //arbitrary value to avoid overlapping lines. Changing THICKNESS_STEP or numCircleSegments might cause artifacts.
|
||||
|
||||
for t := thicknessStep; t < thickness - thicknessStep; t += thicknessStep {
|
||||
points := make([]sdl.FPoint, numCircleSegments + 1, allocator = context.temp_allocator)
|
||||
clampedRadius := sdl.max(radius - t, 1)
|
||||
for t := thicknessStep; t < thickness - thicknessStep; t += thicknessStep {
|
||||
points := make([]sdl.FPoint, numCircleSegments + 1, allocator = context.temp_allocator)
|
||||
clampedRadius := max(radius - t, 1)
|
||||
|
||||
for i in 0 ..= numCircleSegments {
|
||||
angle := radStart + f32(i) * angleStep
|
||||
points[i] = (sdl.FPoint) {
|
||||
sdl.roundf(center.x + sdl.cosf(angle) * clampedRadius),
|
||||
sdl.roundf(center.y + sdl.sinf(angle) * clampedRadius),
|
||||
}
|
||||
}
|
||||
sdl.RenderLines(rendererData.renderer, raw_data(points), numCircleSegments + 1)
|
||||
}
|
||||
for i in 0 ..= numCircleSegments {
|
||||
angle := radStart + f32(i) * angleStep
|
||||
points[i] = sdl.FPoint{math.round(center.x + math.cos(angle) * clampedRadius), math.round(center.y + math.sin(angle) * clampedRadius)}
|
||||
}
|
||||
sdl.RenderLines(rendererData.renderer, raw_data(points), numCircleSegments + 1)
|
||||
}
|
||||
}
|
||||
|
||||
currentClippingRectangle: sdl.Rect
|
||||
@(private = "file")
|
||||
current_clipping_rect: sdl.Rect
|
||||
|
||||
sdl_Clay_RenderClayCommands :: proc(
|
||||
rendererData: ^Clay_SDL3RendererData,
|
||||
rcommands: ^clay.ClayArray(clay.RenderCommand),
|
||||
) {
|
||||
for i in 0 ..< rcommands.length {
|
||||
rcmd := clay.RenderCommandArray_Get(rcommands, i)
|
||||
bounding_box := rcmd.boundingBox
|
||||
rect := sdl.FRect{bounding_box.x, bounding_box.y, bounding_box.width, bounding_box.height}
|
||||
|
||||
#partial switch (rcmd.commandType) {
|
||||
case .Rectangle:
|
||||
config := &rcmd.renderData.rectangle
|
||||
sdl.SetRenderDrawBlendMode(rendererData.renderer, sdl.BLENDMODE_BLEND)
|
||||
sdl.SetRenderDrawColor(
|
||||
rendererData.renderer,
|
||||
u8(config.backgroundColor.r),
|
||||
u8(config.backgroundColor.g),
|
||||
u8(config.backgroundColor.b),
|
||||
u8(config.backgroundColor.a),
|
||||
)
|
||||
if (config.cornerRadius.topLeft > 0) {
|
||||
sdl_Clay_RenderFillRoundedRect(
|
||||
rendererData,
|
||||
rect,
|
||||
config.cornerRadius.topLeft,
|
||||
config.backgroundColor,
|
||||
)
|
||||
} else {
|
||||
sdl.RenderFillRect(rendererData.renderer, &rect)
|
||||
}
|
||||
|
||||
case .Text:
|
||||
config := &rcmd.renderData.text
|
||||
font := rendererData.fonts[config.fontId]
|
||||
ttf.SetFontSize(font, px_to_pt(f32(config.fontSize)))
|
||||
text := ttf.CreateText(
|
||||
rendererData.textEngine,
|
||||
font,
|
||||
cstring(config.stringContents.chars),
|
||||
uint(config.stringContents.length),
|
||||
)
|
||||
ttf.SetTextColor(
|
||||
text,
|
||||
u8(config.textColor.r),
|
||||
u8(config.textColor.g),
|
||||
u8(config.textColor.b),
|
||||
u8(config.textColor.a),
|
||||
)
|
||||
ttf.DrawRendererText(text, rect.x, rect.y)
|
||||
ttf.DestroyText(text)
|
||||
|
||||
case .Border:
|
||||
config := &rcmd.renderData.border
|
||||
|
||||
minRadius := sdl.min(rect.w, rect.h) / 2
|
||||
clampedRadii := clay.CornerRadius {
|
||||
topLeft = sdl.min(config.cornerRadius.topLeft, minRadius),
|
||||
topRight = sdl.min(config.cornerRadius.topRight, minRadius),
|
||||
bottomLeft = sdl.min(config.cornerRadius.bottomLeft, minRadius),
|
||||
bottomRight = sdl.min(config.cornerRadius.bottomRight, minRadius),
|
||||
}
|
||||
//edges
|
||||
sdl.SetRenderDrawColor(
|
||||
rendererData.renderer,
|
||||
u8(config.color.r),
|
||||
u8(config.color.g),
|
||||
u8(config.color.b),
|
||||
u8(config.color.a),
|
||||
)
|
||||
if (config.width.left > 0) {
|
||||
starting_y := rect.y + clampedRadii.topLeft
|
||||
length := rect.h - clampedRadii.topLeft - clampedRadii.bottomLeft
|
||||
line := sdl.FRect{rect.x - 1, starting_y, f32(config.width.left), length}
|
||||
sdl.RenderFillRect(rendererData.renderer, &line)
|
||||
}
|
||||
if (config.width.right > 0) {
|
||||
starting_x := rect.x + rect.w - f32(config.width.right) + 1
|
||||
starting_y := rect.y + clampedRadii.topRight
|
||||
length := rect.h - clampedRadii.topRight - clampedRadii.bottomRight
|
||||
line := sdl.FRect{starting_x, starting_y, f32(config.width.right), length}
|
||||
sdl.RenderFillRect(rendererData.renderer, &line)
|
||||
}
|
||||
if (config.width.top > 0) {
|
||||
starting_x := rect.x + clampedRadii.topLeft
|
||||
length := rect.w - clampedRadii.topLeft - clampedRadii.topRight
|
||||
line := sdl.FRect{starting_x, rect.y - 1, length, f32(config.width.top)}
|
||||
sdl.RenderFillRect(rendererData.renderer, &line)
|
||||
}
|
||||
if (config.width.bottom > 0) {
|
||||
starting_x := rect.x + clampedRadii.bottomLeft
|
||||
starting_y := rect.y + rect.h - f32(config.width.bottom) + 1
|
||||
length := rect.w - clampedRadii.bottomLeft - clampedRadii.bottomRight
|
||||
line := sdl.FRect{starting_x, starting_y, length, f32(config.width.bottom)}
|
||||
sdl.SetRenderDrawColor(
|
||||
rendererData.renderer,
|
||||
u8(config.color.r),
|
||||
u8(config.color.g),
|
||||
u8(config.color.b),
|
||||
u8(config.color.a),
|
||||
)
|
||||
sdl.RenderFillRect(rendererData.renderer, &line)
|
||||
}
|
||||
//corners
|
||||
if (config.cornerRadius.topLeft > 0) {
|
||||
centerX := rect.x + clampedRadii.topLeft - 1
|
||||
centerY := rect.y + clampedRadii.topLeft - 1
|
||||
sdl_Clay_RenderArc(
|
||||
rendererData,
|
||||
(sdl.FPoint){centerX, centerY},
|
||||
clampedRadii.topLeft,
|
||||
180.0,
|
||||
270.0,
|
||||
f32(config.width.top),
|
||||
config.color,
|
||||
)
|
||||
}
|
||||
if (config.cornerRadius.topRight > 0) {
|
||||
centerX := rect.x + rect.w - clampedRadii.topRight
|
||||
centerY := rect.y + clampedRadii.topRight - 1
|
||||
sdl_Clay_RenderArc(
|
||||
rendererData,
|
||||
(sdl.FPoint){centerX, centerY},
|
||||
clampedRadii.topRight,
|
||||
270.0,
|
||||
360.0,
|
||||
f32(config.width.top),
|
||||
config.color,
|
||||
)
|
||||
}
|
||||
if (config.cornerRadius.bottomLeft > 0) {
|
||||
centerX := rect.x + clampedRadii.bottomLeft - 1
|
||||
centerY := rect.y + rect.h - clampedRadii.bottomLeft
|
||||
sdl_Clay_RenderArc(
|
||||
rendererData,
|
||||
(sdl.FPoint){centerX, centerY},
|
||||
clampedRadii.bottomLeft,
|
||||
90.0,
|
||||
180.0,
|
||||
f32(config.width.bottom),
|
||||
config.color,
|
||||
)
|
||||
}
|
||||
if (config.cornerRadius.bottomRight > 0) {
|
||||
centerX := rect.x + rect.w - clampedRadii.bottomRight
|
||||
centerY := rect.y + rect.h - clampedRadii.bottomRight
|
||||
sdl_Clay_RenderArc(
|
||||
rendererData,
|
||||
(sdl.FPoint){centerX, centerY},
|
||||
clampedRadii.bottomRight,
|
||||
0.0,
|
||||
90.0,
|
||||
f32(config.width.bottom),
|
||||
config.color,
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
case .ScissorStart:
|
||||
boundingBox := rcmd.boundingBox
|
||||
currentClippingRectangle = (sdl.Rect) {
|
||||
x = i32(boundingBox.x),
|
||||
y = i32(boundingBox.y),
|
||||
w = i32(boundingBox.width),
|
||||
h = i32(boundingBox.height),
|
||||
}
|
||||
sdl.SetRenderClipRect(rendererData.renderer, ¤tClippingRectangle)
|
||||
|
||||
case .ScissorEnd:
|
||||
sdl.SetRenderClipRect(rendererData.renderer, nil)
|
||||
|
||||
|
||||
case .Image:
|
||||
texture := (^sdl.Texture)(rcmd.renderData.image.imageData)
|
||||
dest := sdl.FRect{rect.x, rect.y, rect.w, rect.h}
|
||||
sdl.RenderTexture(rendererData.renderer, texture, nil, &dest)
|
||||
|
||||
|
||||
case:
|
||||
sdl.Log("Unknown render command type: %d", rcmd.commandType)
|
||||
}
|
||||
}
|
||||
clay_to_sdl_color :: proc(color: clay.Color) -> (r, g, b, a: u8) {
|
||||
return expand_values(linalg.array_cast(color, u8))
|
||||
}
|
||||
|
||||
sdl_render_clay_commands :: proc(renderer_data: ^Clay_SDL_Render_Data, commands: ^clay.ClayArray(clay.RenderCommand)) {
|
||||
for i in 0 ..< commands.length {
|
||||
cmd := clay.RenderCommandArray_Get(commands, i)
|
||||
bounding_box := cmd.boundingBox
|
||||
rect := sdl.FRect{bounding_box.x, bounding_box.y, bounding_box.width, bounding_box.height}
|
||||
|
||||
#partial switch cmd.commandType {
|
||||
case .Rectangle:
|
||||
config := &cmd.renderData.rectangle
|
||||
sdl.SetRenderDrawBlendMode(renderer_data.renderer, sdl.BLENDMODE_BLEND)
|
||||
sdl.SetRenderDrawColor(renderer_data.renderer, clay_to_sdl_color(config.backgroundColor))
|
||||
if config.cornerRadius.topLeft > 0 {
|
||||
fill_rounded_rect(renderer_data, rect, config.cornerRadius.topLeft, config.backgroundColor)
|
||||
} else {
|
||||
sdl.RenderFillRect(renderer_data.renderer, &rect)
|
||||
}
|
||||
|
||||
case .Text:
|
||||
config := &cmd.renderData.text
|
||||
font := renderer_data.fonts[config.fontId]
|
||||
ttf.SetFontSize(font, px_to_pt(f32(config.fontSize)))
|
||||
text := ttf.CreateText(renderer_data.text_engine, font, cstring(config.stringContents.chars), uint(config.stringContents.length))
|
||||
ttf.SetTextColor(text, clay_to_sdl_color(config.textColor))
|
||||
ttf.DrawRendererText(text, rect.x, rect.y)
|
||||
ttf.DestroyText(text)
|
||||
|
||||
case .Border:
|
||||
config := &cmd.renderData.border
|
||||
|
||||
minRadius := min(rect.w, rect.h) / 2
|
||||
clampedRadii := clay.CornerRadius {
|
||||
topLeft = min(config.cornerRadius.topLeft, minRadius),
|
||||
topRight = min(config.cornerRadius.topRight, minRadius),
|
||||
bottomLeft = min(config.cornerRadius.bottomLeft, minRadius),
|
||||
bottomRight = min(config.cornerRadius.bottomRight, minRadius),
|
||||
}
|
||||
//edges
|
||||
sdl.SetRenderDrawColor(renderer_data.renderer, clay_to_sdl_color(config.color))
|
||||
if config.width.left > 0 {
|
||||
starting_y := rect.y + clampedRadii.topLeft
|
||||
length := rect.h - clampedRadii.topLeft - clampedRadii.bottomLeft
|
||||
line := sdl.FRect{rect.x - 1, starting_y, f32(config.width.left), length}
|
||||
sdl.RenderFillRect(renderer_data.renderer, &line)
|
||||
}
|
||||
if config.width.right > 0 {
|
||||
starting_x := rect.x + rect.w - f32(config.width.right) + 1
|
||||
starting_y := rect.y + clampedRadii.topRight
|
||||
length := rect.h - clampedRadii.topRight - clampedRadii.bottomRight
|
||||
line := sdl.FRect{starting_x, starting_y, f32(config.width.right), length}
|
||||
sdl.RenderFillRect(renderer_data.renderer, &line)
|
||||
}
|
||||
if config.width.top > 0 {
|
||||
starting_x := rect.x + clampedRadii.topLeft
|
||||
length := rect.w - clampedRadii.topLeft - clampedRadii.topRight
|
||||
line := sdl.FRect{starting_x, rect.y - 1, length, f32(config.width.top)}
|
||||
sdl.RenderFillRect(renderer_data.renderer, &line)
|
||||
}
|
||||
if config.width.bottom > 0 {
|
||||
starting_x := rect.x + clampedRadii.bottomLeft
|
||||
starting_y := rect.y + rect.h - f32(config.width.bottom) + 1
|
||||
length := rect.w - clampedRadii.bottomLeft - clampedRadii.bottomRight
|
||||
line := sdl.FRect{starting_x, starting_y, length, f32(config.width.bottom)}
|
||||
sdl.SetRenderDrawColor(renderer_data.renderer, clay_to_sdl_color(config.color))
|
||||
sdl.RenderFillRect(renderer_data.renderer, &line)
|
||||
}
|
||||
//corners
|
||||
if config.cornerRadius.topLeft > 0 {
|
||||
centerX := rect.x + clampedRadii.topLeft - 1
|
||||
centerY := rect.y + clampedRadii.topLeft - 1
|
||||
render_arc(renderer_data, {centerX, centerY}, clampedRadii.topLeft, 180, 270, f32(config.width.top), config.color)
|
||||
}
|
||||
if config.cornerRadius.topRight > 0 {
|
||||
centerX := rect.x + rect.w - clampedRadii.topRight
|
||||
centerY := rect.y + clampedRadii.topRight - 1
|
||||
render_arc(renderer_data, {centerX, centerY}, clampedRadii.topRight, 270, 360, f32(config.width.top), config.color)
|
||||
}
|
||||
if config.cornerRadius.bottomLeft > 0 {
|
||||
centerX := rect.x + clampedRadii.bottomLeft - 1
|
||||
centerY := rect.y + rect.h - clampedRadii.bottomLeft
|
||||
render_arc(renderer_data, {centerX, centerY}, clampedRadii.bottomLeft, 90, 180, f32(config.width.bottom), config.color)
|
||||
}
|
||||
if config.cornerRadius.bottomRight > 0 {
|
||||
centerX := rect.x + rect.w - clampedRadii.bottomRight
|
||||
centerY := rect.y + rect.h - clampedRadii.bottomRight
|
||||
render_arc(renderer_data, {centerX, centerY}, clampedRadii.bottomRight, 0, 90, f32(config.width.bottom), config.color)
|
||||
}
|
||||
|
||||
|
||||
case .ScissorStart:
|
||||
boundingBox := cmd.boundingBox
|
||||
current_clipping_rect = sdl.Rect {
|
||||
x = i32(boundingBox.x),
|
||||
y = i32(boundingBox.y),
|
||||
w = i32(boundingBox.width),
|
||||
h = i32(boundingBox.height),
|
||||
}
|
||||
sdl.SetRenderClipRect(renderer_data.renderer, ¤t_clipping_rect)
|
||||
|
||||
case .ScissorEnd:
|
||||
sdl.SetRenderClipRect(renderer_data.renderer, nil)
|
||||
|
||||
|
||||
case .Image:
|
||||
texture := (^sdl.Texture)(cmd.renderData.image.imageData)
|
||||
dest := sdl.FRect{rect.x, rect.y, rect.w, rect.h}
|
||||
sdl.RenderTexture(renderer_data.renderer, texture, nil, &dest)
|
||||
|
||||
|
||||
case:
|
||||
sdl.Log("Unknown render command type: %d", cmd.commandType)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue