From 3f07ca0ff6fee02282259c50ecaa0fb3d6e7a503 Mon Sep 17 00:00:00 2001 From: Leo dev Date: Wed, 26 Nov 2025 22:05:39 +0100 Subject: [PATCH] Imrpoved component structure --- examples/components/mod.rs | 4 ++++ examples/components/threads.rs | 5 +++-- examples/cube.rs | 39 ++++++++++++++++++++++++++++++++-- src/entity.rs | 27 ++++++++++++++++++----- src/lib.rs | 27 +++++++++++++++++++++++ 5 files changed, 93 insertions(+), 9 deletions(-) diff --git a/examples/components/mod.rs b/examples/components/mod.rs index 74b9827..712a1c3 100644 --- a/examples/components/mod.rs +++ b/examples/components/mod.rs @@ -10,6 +10,10 @@ impl Component for Velocity { apply_velocity(tick, self.0.x, &mut position.x); apply_velocity(tick, self.0.y, &mut position.y); } + + fn as_any_mut(&mut self) -> &mut dyn std::any::Any { + self + } } fn apply_velocity(tick: u16, velocity: i32, x: &mut u16) -> bool { diff --git a/examples/components/threads.rs b/examples/components/threads.rs index 10a5312..6aab9eb 100644 --- a/examples/components/threads.rs +++ b/examples/components/threads.rs @@ -19,10 +19,11 @@ pub fn tick(engine: &Arc) { } pub fn key(engine: &Arc) { + crossterm::terminal::enable_raw_mode().unwrap(); + engine.thread("Main.key", |engine| { loop { - // Pass an event to the thread - + engine.emit_event(crossterm::event::read().unwrap()); } }); } diff --git a/examples/cube.rs b/examples/cube.rs index c13362b..58e651b 100644 --- a/examples/cube.rs +++ b/examples/cube.rs @@ -3,8 +3,6 @@ pub mod components; use osmium::{renderer::Point, terminal}; fn main() { - terminal::hide_cursor().unwrap(); - let engine = osmium::init(); let my_rect = engine.entity(|r| { @@ -15,6 +13,43 @@ fn main() { my_rect.component(components::Velocity(Point { x: 0, y: 0 })); + components::threads::tick(&engine); + components::threads::key(&engine); + + engine.on_event({ + let my_rect = my_rect.clone(); + move |e: &crossterm::event::Event| { + if let Some(key_event) = e.as_key_event() { + match key_event.code { + crossterm::event::KeyCode::Right => { + my_rect.update_component(|c: &mut components::Velocity| { + c.0.x = 100; + }); + } + crossterm::event::KeyCode::Left => { + my_rect.update_component(|c: &mut components::Velocity| { + c.0.x = -100; + }); + } + + crossterm::event::KeyCode::Down => { + my_rect.update_component(|c: &mut components::Velocity| { + c.0.y = 100; + }); + } + crossterm::event::KeyCode::Up => { + my_rect.update_component(|c: &mut components::Velocity| { + c.0.y = -100; + }); + } + _ => {} + } + } + } + }); + + terminal::hide_cursor().unwrap(); + engine.start(); terminal::show_cursor().unwrap(); diff --git a/src/entity.rs b/src/entity.rs index 304e38e..0e4e028 100644 --- a/src/entity.rs +++ b/src/entity.rs @@ -1,4 +1,8 @@ -use std::sync::{Arc, Mutex, MutexGuard}; +use std::{ + any::{Any, TypeId}, + collections::HashMap, + sync::{Arc, Mutex, MutexGuard}, +}; use crate::{Renderer, renderer::Point}; @@ -9,11 +13,13 @@ pub trait Component: Send + Sync { fn init(&mut self, entity: &Arc) {} #[allow(unused_variables)] fn tick(&mut self, entity: &Arc, tick: u16) {} + + fn as_any_mut(&mut self) -> &mut dyn Any; } pub struct Entity { pos: Mutex, - components: Mutex>>, + components: Mutex>>, render: Box, } @@ -21,13 +27,24 @@ impl Entity { pub fn new(render: F) -> Arc { Arc::new(Self { pos: Mutex::new(Point { x: 0, y: 0 }), - components: Mutex::new(Vec::new()), + components: Mutex::new(HashMap::new()), render: Box::new(render), }) } pub fn component(self: &Arc, c: C) { - self.components.lock().unwrap().push(Box::new(c)); + self.components + .lock() + .unwrap() + .insert(TypeId::of::(), Box::new(c)); + } + + pub fn update_component(self: &Arc, f: F) { + if let Some(c) = self.components.lock().unwrap().get_mut(&TypeId::of::()) { + if let Some(c) = c.as_any_mut().downcast_mut::() { + f(c) + } + } } pub fn render(self: &Arc, renderer: &mut Renderer) { @@ -35,7 +52,7 @@ impl Entity { } pub fn tick(self: &Arc, tick: u16) { - for comp in self.components.lock().unwrap().iter_mut() { + for comp in self.components.lock().unwrap().values_mut() { comp.tick(self, tick); } } diff --git a/src/lib.rs b/src/lib.rs index e582792..089a115 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,6 +3,7 @@ pub mod renderer; pub mod terminal; use std::{ + any::{Any, TypeId}, collections::HashMap, sync::{Arc, Mutex}, }; @@ -13,12 +14,14 @@ pub fn init() -> Arc { Arc::new(Engine { threads: Mutex::new(HashMap::new()), entities: Mutex::new(Vec::new()), + event_cb: Mutex::new(HashMap::new()), }) } pub struct Engine { threads: Mutex) + Send + Sync>>>, entities: Mutex>>, + event_cb: Mutex>>>, } pub fn sleep(ms: u64) { @@ -46,6 +49,30 @@ impl Engine { .clone() } + pub fn on_event( + self: &Arc, + callback: F, + ) { + self.event_cb + .lock() + .unwrap() + .entry(TypeId::of::()) + .or_insert_with(|| Vec::new()) + .push(Arc::new(move |e| { + if let Some(e) = e.downcast_ref() { + callback(e); + } + })); + } + + pub fn emit_event(self: &Arc, event: E) { + if let Some(callbacks) = self.event_cb.lock().unwrap().get(&TypeId::of::()) { + for cb in callbacks { + cb(&event) + } + } + } + pub fn render(self: &Arc) { terminal::clear().unwrap();