353 lines
9.6 KiB
Odin
353 lines
9.6 KiB
Odin
package examples
|
|
|
|
import "../../draw"
|
|
import "../../vendor/clay"
|
|
import "core:math"
|
|
import "core:os"
|
|
import sdl "vendor:sdl3"
|
|
|
|
JETBRAINS_MONO_REGULAR_RAW :: #load("fonts/JetBrainsMono-Regular.ttf")
|
|
JETBRAINS_MONO_REGULAR: draw.Font_Id = max(draw.Font_Id) // Max so we crash if registration is forgotten
|
|
|
|
hellope_shapes :: proc() {
|
|
if !sdl.Init({.VIDEO}) do os.exit(1)
|
|
window := sdl.CreateWindow("Hellope!", 500, 500, {.HIGH_PIXEL_DENSITY})
|
|
gpu := sdl.CreateGPUDevice(draw.PLATFORM_SHADER_FORMAT, true, nil)
|
|
if !sdl.ClaimWindowForGPUDevice(gpu, window) do os.exit(1)
|
|
if !draw.init(gpu, window) do os.exit(1)
|
|
|
|
spin_angle: f32 = 0
|
|
|
|
for {
|
|
defer free_all(context.temp_allocator)
|
|
ev: sdl.Event
|
|
for sdl.PollEvent(&ev) {
|
|
if ev.type == .QUIT do return
|
|
}
|
|
spin_angle += 1
|
|
base_layer := draw.begin({width = 500, height = 500})
|
|
|
|
// Background
|
|
draw.rectangle(base_layer, {0, 0, 500, 500}, {40, 40, 40, 255})
|
|
|
|
// ----- Shapes without rotation (existing demo) -----
|
|
draw.rectangle(base_layer, {20, 20, 200, 120}, {80, 120, 200, 255})
|
|
draw.rectangle_lines(base_layer, {20, 20, 200, 120}, draw.WHITE, thickness = 2)
|
|
draw.rectangle(base_layer, {240, 20, 240, 120}, {200, 80, 80, 255}, roundness = 0.3)
|
|
draw.rectangle_gradient(
|
|
base_layer,
|
|
{20, 160, 460, 60},
|
|
{255, 0, 0, 255},
|
|
{0, 255, 0, 255},
|
|
{0, 0, 255, 255},
|
|
{255, 255, 0, 255},
|
|
)
|
|
|
|
// ----- Rotation demos -----
|
|
|
|
// Rectangle rotating around its center
|
|
rect := draw.Rectangle{100, 320, 80, 50}
|
|
draw.rectangle(
|
|
base_layer,
|
|
rect,
|
|
{100, 200, 100, 255},
|
|
origin = draw.center_of(rect),
|
|
rotation = spin_angle,
|
|
)
|
|
draw.rectangle_lines(
|
|
base_layer,
|
|
rect,
|
|
draw.WHITE,
|
|
thickness = 2,
|
|
origin = draw.center_of(rect),
|
|
rotation = spin_angle,
|
|
)
|
|
|
|
// Rounded rectangle rotating around its center
|
|
rrect := draw.Rectangle{230, 300, 100, 80}
|
|
draw.rectangle(
|
|
base_layer,
|
|
rrect,
|
|
{200, 100, 200, 255},
|
|
roundness = 0.4,
|
|
origin = draw.center_of(rrect),
|
|
rotation = spin_angle,
|
|
)
|
|
|
|
// Ellipse rotating around its center (tilted ellipse)
|
|
draw.ellipse(base_layer, {410, 340}, 50, 30, {255, 200, 50, 255}, rotation = spin_angle)
|
|
|
|
// Circle orbiting a point (moon orbiting planet)
|
|
// Convention B: center = pivot point (planet), origin = offset from moon center to pivot.
|
|
// Moon's visual center at rotation=0: planet_pos - origin = (100, 450) - (0, 40) = (100, 410).
|
|
planet_pos := [2]f32{100, 450}
|
|
draw.circle(base_layer, planet_pos, 8, {200, 200, 200, 255}) // planet (stationary)
|
|
draw.circle(base_layer, planet_pos, 5, {100, 150, 255, 255}, origin = {0, 40}, rotation = spin_angle) // moon orbiting
|
|
|
|
// Ring arc rotating in place
|
|
draw.ring(base_layer, {250, 450}, 15, 30, 0, 270, {100, 100, 220, 255}, rotation = spin_angle)
|
|
|
|
// Triangle rotating around its center
|
|
tv1 := [2]f32{350, 420}
|
|
tv2 := [2]f32{420, 480}
|
|
tv3 := [2]f32{340, 480}
|
|
draw.triangle(
|
|
base_layer,
|
|
tv1,
|
|
tv2,
|
|
tv3,
|
|
{220, 180, 60, 255},
|
|
origin = draw.center_of(tv1, tv2, tv3),
|
|
rotation = spin_angle,
|
|
)
|
|
|
|
// Polygon rotating around its center (already had rotation; now with origin for orbit)
|
|
draw.polygon(base_layer, {460, 450}, 6, 30, {180, 100, 220, 255}, rotation = spin_angle)
|
|
draw.polygon_lines(base_layer, {460, 450}, 6, 30, draw.WHITE, rotation = spin_angle, thickness = 2)
|
|
|
|
draw.end(gpu, window)
|
|
}
|
|
}
|
|
|
|
hellope_text :: proc() {
|
|
HELLOPE_ID :: 1
|
|
ROTATING_SENTENCE_ID :: 2
|
|
MEASURED_ID :: 3
|
|
CORNER_SPIN_ID :: 4
|
|
|
|
if !sdl.Init({.VIDEO}) do os.exit(1)
|
|
window := sdl.CreateWindow("Hellope!", 600, 600, {.HIGH_PIXEL_DENSITY})
|
|
gpu := sdl.CreateGPUDevice(draw.PLATFORM_SHADER_FORMAT, true, nil)
|
|
if !sdl.ClaimWindowForGPUDevice(gpu, window) do os.exit(1)
|
|
if !draw.init(gpu, window) do os.exit(1)
|
|
JETBRAINS_MONO_REGULAR = draw.register_font(JETBRAINS_MONO_REGULAR_RAW)
|
|
|
|
FONT_SIZE :: u16(24)
|
|
spin_angle: f32 = 0
|
|
|
|
for {
|
|
defer free_all(context.temp_allocator)
|
|
ev: sdl.Event
|
|
for sdl.PollEvent(&ev) {
|
|
if ev.type == .QUIT do return
|
|
}
|
|
spin_angle += 0.5
|
|
base_layer := draw.begin({width = 600, height = 600})
|
|
|
|
// Grey background
|
|
draw.rectangle(base_layer, {0, 0, 600, 600}, {127, 127, 127, 255})
|
|
|
|
// ----- Text API demos -----
|
|
|
|
// Cached text with id — TTF_Text reused across frames (good for text-heavy apps)
|
|
draw.text(
|
|
base_layer,
|
|
"Hellope!",
|
|
{300, 80},
|
|
JETBRAINS_MONO_REGULAR,
|
|
FONT_SIZE,
|
|
color = draw.WHITE,
|
|
origin = draw.center_of("Hellope!", JETBRAINS_MONO_REGULAR, FONT_SIZE),
|
|
id = HELLOPE_ID,
|
|
)
|
|
|
|
// Rotating sentence — verifies multi-word text rotation around center
|
|
draw.text(
|
|
base_layer,
|
|
"Hellope World!",
|
|
{300, 250},
|
|
JETBRAINS_MONO_REGULAR,
|
|
FONT_SIZE,
|
|
color = {255, 200, 50, 255},
|
|
origin = draw.center_of("Hellope World!", JETBRAINS_MONO_REGULAR, FONT_SIZE),
|
|
rotation = spin_angle,
|
|
id = ROTATING_SENTENCE_ID,
|
|
)
|
|
|
|
// Uncached text (no id) — created and destroyed each frame, simplest usage
|
|
draw.text(
|
|
base_layer,
|
|
"Top-left anchored",
|
|
{20, 450},
|
|
JETBRAINS_MONO_REGULAR,
|
|
FONT_SIZE,
|
|
color = draw.WHITE,
|
|
)
|
|
|
|
// Measure text for manual layout
|
|
size := draw.measure_text("Measured!", JETBRAINS_MONO_REGULAR, FONT_SIZE)
|
|
draw.rectangle(base_layer, {300 - size.x / 2, 380, size.x, size.y}, {60, 60, 60, 200})
|
|
draw.text(
|
|
base_layer,
|
|
"Measured!",
|
|
{300, 380},
|
|
JETBRAINS_MONO_REGULAR,
|
|
FONT_SIZE,
|
|
color = draw.WHITE,
|
|
origin = draw.top_of("Measured!", JETBRAINS_MONO_REGULAR, FONT_SIZE),
|
|
id = MEASURED_ID,
|
|
)
|
|
|
|
// Rotating text anchored at top-left (no origin offset) — spins around top-left corner
|
|
draw.text(
|
|
base_layer,
|
|
"Corner spin",
|
|
{150, 530},
|
|
JETBRAINS_MONO_REGULAR,
|
|
FONT_SIZE,
|
|
color = {100, 200, 255, 255},
|
|
rotation = spin_angle,
|
|
id = CORNER_SPIN_ID,
|
|
)
|
|
|
|
draw.end(gpu, window)
|
|
}
|
|
}
|
|
|
|
hellope_clay :: proc() {
|
|
if !sdl.Init({.VIDEO}) do os.exit(1)
|
|
window := sdl.CreateWindow("Hellope!", 500, 500, {.HIGH_PIXEL_DENSITY})
|
|
gpu := sdl.CreateGPUDevice(draw.PLATFORM_SHADER_FORMAT, true, nil)
|
|
if !sdl.ClaimWindowForGPUDevice(gpu, window) do os.exit(1)
|
|
if !draw.init(gpu, window) do os.exit(1)
|
|
JETBRAINS_MONO_REGULAR = draw.register_font(JETBRAINS_MONO_REGULAR_RAW)
|
|
|
|
text_config := clay.TextElementConfig {
|
|
fontId = JETBRAINS_MONO_REGULAR,
|
|
fontSize = 36,
|
|
textColor = {255, 255, 255, 255},
|
|
}
|
|
|
|
for {
|
|
defer free_all(context.temp_allocator)
|
|
ev: sdl.Event
|
|
for sdl.PollEvent(&ev) {
|
|
if ev.type == .QUIT do return
|
|
}
|
|
base_layer := draw.begin({width = 500, height = 500})
|
|
clay.SetLayoutDimensions({width = base_layer.bounds.width, height = base_layer.bounds.height})
|
|
clay.BeginLayout()
|
|
if clay.UI()(
|
|
{
|
|
id = clay.ID("outer"),
|
|
layout = {
|
|
sizing = {clay.SizingGrow({}), clay.SizingGrow({})},
|
|
childAlignment = {x = .Center, y = .Center},
|
|
},
|
|
backgroundColor = {127, 127, 127, 255},
|
|
},
|
|
) {
|
|
clay.Text("Hellope!", &text_config)
|
|
}
|
|
clay_batch := draw.ClayBatch {
|
|
bounds = base_layer.bounds,
|
|
cmds = clay.EndLayout(),
|
|
}
|
|
draw.prepare_clay_batch(base_layer, &clay_batch, {0, 0})
|
|
draw.end(gpu, window)
|
|
}
|
|
}
|
|
|
|
hellope_custom :: proc() {
|
|
if !sdl.Init({.VIDEO}) do os.exit(1)
|
|
window := sdl.CreateWindow("Hellope Custom!", 600, 400, {.HIGH_PIXEL_DENSITY})
|
|
gpu := sdl.CreateGPUDevice(draw.PLATFORM_SHADER_FORMAT, true, nil)
|
|
if !sdl.ClaimWindowForGPUDevice(gpu, window) do os.exit(1)
|
|
if !draw.init(gpu, window) do os.exit(1)
|
|
JETBRAINS_MONO_REGULAR = draw.register_font(JETBRAINS_MONO_REGULAR_RAW)
|
|
|
|
text_config := clay.TextElementConfig {
|
|
fontId = JETBRAINS_MONO_REGULAR,
|
|
fontSize = 24,
|
|
textColor = {255, 255, 255, 255},
|
|
}
|
|
|
|
gauge := Gauge {
|
|
value = 0.73,
|
|
color = {50, 200, 100, 255},
|
|
}
|
|
gauge2 := Gauge {
|
|
value = 0.45,
|
|
color = {200, 100, 50, 255},
|
|
}
|
|
spin_angle: f32 = 0
|
|
|
|
for {
|
|
defer free_all(context.temp_allocator)
|
|
ev: sdl.Event
|
|
for sdl.PollEvent(&ev) {
|
|
if ev.type == .QUIT do return
|
|
}
|
|
|
|
spin_angle += 1
|
|
gauge.value = (math.sin(spin_angle * 0.02) + 1) * 0.5
|
|
gauge2.value = (math.cos(spin_angle * 0.03) + 1) * 0.5
|
|
|
|
base_layer := draw.begin({width = 600, height = 400})
|
|
clay.SetLayoutDimensions({width = base_layer.bounds.width, height = base_layer.bounds.height})
|
|
clay.BeginLayout()
|
|
|
|
if clay.UI()(
|
|
{
|
|
id = clay.ID("outer"),
|
|
layout = {
|
|
sizing = {clay.SizingGrow({}), clay.SizingGrow({})},
|
|
childAlignment = {x = .Center, y = .Center},
|
|
layoutDirection = .TopToBottom,
|
|
childGap = 20,
|
|
},
|
|
backgroundColor = {50, 50, 50, 255},
|
|
},
|
|
) {
|
|
if clay.UI()({id = clay.ID("title"), layout = {sizing = {clay.SizingFit({}), clay.SizingFit({})}}}) {
|
|
clay.Text("Custom Draw Demo", &text_config)
|
|
}
|
|
|
|
if clay.UI()(
|
|
{
|
|
id = clay.ID("gauge"),
|
|
layout = {sizing = {clay.SizingFixed(300), clay.SizingFixed(30)}},
|
|
custom = {customData = &gauge},
|
|
backgroundColor = {80, 80, 80, 255},
|
|
},
|
|
) {}
|
|
|
|
if clay.UI()(
|
|
{
|
|
id = clay.ID("gauge2"),
|
|
layout = {sizing = {clay.SizingFixed(300), clay.SizingFixed(30)}},
|
|
custom = {customData = &gauge2},
|
|
backgroundColor = {80, 80, 80, 255},
|
|
},
|
|
) {}
|
|
}
|
|
|
|
clay_batch := draw.ClayBatch {
|
|
bounds = base_layer.bounds,
|
|
cmds = clay.EndLayout(),
|
|
}
|
|
draw.prepare_clay_batch(base_layer, &clay_batch, {0, 0}, custom_draw = draw_custom)
|
|
draw.end(gpu, window)
|
|
}
|
|
|
|
Gauge :: struct {
|
|
value: f32,
|
|
color: draw.Color,
|
|
}
|
|
|
|
draw_custom :: proc(layer: ^draw.Layer, bounds: draw.Rectangle, render_data: clay.CustomRenderData) {
|
|
gauge := cast(^Gauge)render_data.customData
|
|
|
|
// Background from clay's backgroundColor
|
|
draw.rectangle(layer, bounds, draw.color_from_clay(render_data.backgroundColor), roundness = 0.25)
|
|
|
|
// Fill bar
|
|
fill := bounds
|
|
fill.width *= gauge.value
|
|
draw.rectangle(layer, fill, gauge.color, roundness = 0.25)
|
|
|
|
// Border
|
|
draw.rectangle_lines(layer, bounds, draw.WHITE, thickness = 2, roundness = 0.25)
|
|
}
|
|
}
|