From 16bf55f093a2b6fe9b499da6d71c28827a6b7961 Mon Sep 17 00:00:00 2001 From: wooshings Date: Tue, 27 Oct 2026 21:26:29 -0700 Subject: [PATCH] change built-in component names --- src/componenets.odin | 8 ++++---- src/systems.odin | 16 ++++++++-------- ui/rlmu.odin | 11 +++++++++++ ui/shoal.odin | 22 ++++++++++++++++++++++ 4 files changed, 45 insertions(+), 12 deletions(-) diff --git a/src/componenets.odin b/src/componenets.odin index 90a0030..536783e 100644 --- a/src/componenets.odin +++ b/src/componenets.odin @@ -5,7 +5,7 @@ import rl "vendor:raylib" // what the app's window opens with: size, title, and the clear color. // DefaultPlugin opens the window from it at STARTUP and paints the clear // color at PRE_DRAW -WindowComponent :: struct { +Window :: struct { width: i32, height: i32, title: string, @@ -13,20 +13,20 @@ WindowComponent :: struct { } // the mouse position, refreshed every UPDATE by DefaultPlugin -CursorComponent :: struct { +Cursor :: struct { position: rl.Vector2, } // a texture DefaultPlugin draws at DRAW, placed by the same entity's // TransformComponent (so every sprite entity needs a Transform component // too) -SpriteComponent :: struct { +Sprite :: struct { texture: rl.Texture2D, } // 2D translation + rotation, read back by draw_sprite when it places the // entity's SpriteComponent -TransformComponent :: struct { +Transform :: struct { translation: rl.Vector2, rotation: f32, } diff --git a/src/systems.odin b/src/systems.odin index 7a47492..ab627c5 100644 --- a/src/systems.odin +++ b/src/systems.odin @@ -24,7 +24,7 @@ DefaultPlugin :: proc(app: ^App) { add_system(app, UPDATE, run_timers) add_system(app, UPDATE, update_cursor_position) add_system(app, PRE_DRAW, proc(world: ^World) {rl.BeginDrawing() - window, _ := single(world, WindowComponent) + window, _ := single(world, Window) rl.ClearBackground(window.background)}) add_system(app, POST_DRAW, proc() {rl.EndDrawing()}) add_system(app, DESTROY, proc() {rl.CloseWindow()}) @@ -36,25 +36,25 @@ DefaultPlugin :: proc(app: ^App) { add_component( world, display, - WindowComponent{width = 800, height = 600, title = "shoal window", background = rl.BLACK}, + Window{width = 800, height = 600, title = "shoal window", background = rl.BLACK}, ) cursor := spawn_entity(world) - add_component(world, cursor, CursorComponent) + add_component(world, cursor, Cursor) } @(private) update_cursor_position :: proc(world: ^World) { - cursor, _ := single(world, CursorComponent) + cursor, _ := single(world, Cursor) cursor.position = rl.GetMousePosition() } @(private) draw_sprite :: proc(world: ^World) { - components := slice(world, SpriteComponent) - entities := slice_entity(world, SpriteComponent) + components := slice(world, Sprite) + entities := slice_entity(world, Sprite) for &v, i in components { - sprite_transform := get_component(world, entities[i], TransformComponent) + sprite_transform := get_component(world, entities[i], Transform) rl.DrawTexture( v.texture, i32(sprite_transform.translation.x), @@ -66,7 +66,7 @@ draw_sprite :: proc(world: ^World) { @(private) startup_window :: proc(world: ^World) { - window, _ := single(world, WindowComponent) + window, _ := single(world, Window) rl.InitWindow(window.width, window.height, strings.clone_to_cstring(window.title)) rl.SetTargetFPS(60) } diff --git a/ui/rlmu.odin b/ui/rlmu.odin index e3f8a31..adb075a 100644 --- a/ui/rlmu.odin +++ b/ui/rlmu.odin @@ -22,6 +22,8 @@ rlmu_init :: proc "contextless" () { global_state = new(RLMU_State) } +// bake the default microui atlas into a raylib texture and set up the mui +// context (text metrics + clipboard callbacks). UIPlugin runs it at STARTUP init :: proc(state := global_state) { // Allocate an array of 32 bit pixel colors for the atlas used by mui // An atlas is a big image packed with multiple smaller images. Like a sprite sheet! @@ -62,11 +64,15 @@ init :: proc(state := global_state) { state.ctx.textbox_state.get_clipboard = get_clipboard } +// unload the atlas texture. UIPlugin runs it at DESTROY destroy :: proc(state := global_state) { // Free atlas texture rl.UnloadTexture(state.atlas) } +// forward this frame's raylib input (text, mouse, keys) to microui and start +// the frame. returns the context to build ui against. UIPlugin runs it at +// PRE_DRAW and hands the result to get_ctx() begin :: proc(state: ^RLMU_State = global_state) -> ^mu.Context { // Forward all input from raylib to mui // We need to tell mui what keys are pressed, where the mouse is etc so the ui can react accordingly @@ -80,6 +86,8 @@ begin :: proc(state: ^RLMU_State = global_state) -> ^mu.Context { return &state.ctx } +// tell microui the frame is finished, then replay its command list as raylib +// draw calls (and close any lingering scissor). UIPlugin runs it at POST_DRAW end :: proc(state := global_state) { // Tell mui that we're done drawing ui mu.end(&state.ctx) @@ -140,8 +148,11 @@ end :: proc(state := global_state) { rl.EndScissorMode() } +// init() with destroy() deferred to scope exit: set the ui up and tear it +// down around a block @(deferred_in = destroy) init_scope :: proc(state := global_state) -> ^mu.Context {init(state); return &state.ctx} +// begin() with end() deferred to scope exit: a whole frame of ui in one block @(deferred_in = end) begin_scope :: proc(state := global_state) -> ^mu.Context {begin(state); return &state.ctx} diff --git a/ui/shoal.odin b/ui/shoal.odin index 9a631f3..6fdbcd2 100644 --- a/ui/shoal.odin +++ b/ui/shoal.odin @@ -1,9 +1,31 @@ package ui +import ecs "../src" import ml "vendor:microui" +// the microui context UIPlugin refreshes every frame, nil until the first +// PRE_DRAW. use get_ctx() instead of touching it directly ui_ctx: ^ml.Context +// wires the ui package into the app, in frame order: +// +// STARTUP init() bakes the microui atlas into a texture +// PRE_DRAW begin() forwards raylib input, starts the frame, stashes ui_ctx +// POST_DRAW the frame's temp arena is freed, then end() renders the ui +// DESTROY destroy() unloads the atlas texture +// +// (systems within a schedule run in registration order, so POST_DRAW frees +// the arena first and renders second) +UIPlugin :: proc(app: ^ecs.App) { + ecs.add_system(app, ecs.STARTUP, proc() {init()}) + ecs.add_system(app, ecs.POST_DRAW, proc() {free_all(context.temp_allocator)}) + ecs.add_system(app, ecs.PRE_DRAW, proc() {ui_ctx = begin()}) + ecs.add_system(app, ecs.POST_DRAW, proc() {end()}) + ecs.add_system(app, ecs.DESTROY, proc() {destroy()}) +} + +// the microui context for this frame. pass it to every microui call. valid +// from PRE_DRAW onwards (nil before the first frame) get_ctx :: proc() -> ^ml.Context { return ui_ctx }