o3 refactor
This commit is contained in:
parent
341d531db3
commit
049f522bb1
19 changed files with 508 additions and 214 deletions
|
|
@ -2,3 +2,11 @@
|
|||
name = "raidillon_core"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
glam = "0.30.4"
|
||||
hecs = "0.10.5"
|
||||
raidillon_render = { path = "../raidillon_render" }
|
||||
glium = { version = "0.35.0", features = ["glutin_backend", "simple_window_builder"] }
|
||||
raidillon_ecs = { path = "../raidillon_ecs" }
|
||||
anyhow = "1.0.98"
|
||||
|
|
|
|||
42
raidillon_core/src/assets.rs
Normal file
42
raidillon_core/src/assets.rs
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
use std::collections::HashMap;
|
||||
use raidillon_render::model::Model;
|
||||
use glium::glutin::surface::WindowSurface;
|
||||
use glium::Display;
|
||||
use raidillon_render::gltf_loader;
|
||||
use raidillon_ecs::ModelId;
|
||||
use raidillon_render::render_system::ModelProvider;
|
||||
use anyhow::Result;
|
||||
|
||||
pub struct AssetManager {
|
||||
models: Vec<Model>,
|
||||
model_cache: HashMap<String, ModelId>,
|
||||
}
|
||||
|
||||
impl AssetManager {
|
||||
pub fn new() -> Self {
|
||||
Self { models: Vec::new(), model_cache: HashMap::new() }
|
||||
}
|
||||
|
||||
/// Load or retrieve a cached model, returning its `ModelId`.
|
||||
pub fn load_model<P: AsRef<str>>(&mut self, path: P, display: &Display<WindowSurface>) -> Result<ModelId> {
|
||||
let path_str = path.as_ref();
|
||||
if let Some(&id) = self.model_cache.get(path_str) {
|
||||
return Ok(id);
|
||||
}
|
||||
let model = gltf_loader::load_gltf(path_str, display)?;
|
||||
let id = ModelId(self.models.len());
|
||||
self.models.push(model);
|
||||
self.model_cache.insert(path_str.to_string(), id);
|
||||
Ok(id)
|
||||
}
|
||||
|
||||
pub fn get_model(&self, id: ModelId) -> Option<&Model> {
|
||||
self.models.get(id.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl ModelProvider for AssetManager {
|
||||
fn get_model(&self, id: ModelId) -> Option<&Model> {
|
||||
self.get_model(id)
|
||||
}
|
||||
}
|
||||
59
raidillon_core/src/events.rs
Normal file
59
raidillon_core/src/events.rs
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
use std::any::TypeId;
|
||||
use std::collections::HashMap;
|
||||
|
||||
/// Core event enumeration.
|
||||
/// Generic over the `Action` type to keep the engine agnostic to concrete
|
||||
/// game-specific input enumerations.
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum GameEvent<A> {
|
||||
InputAction(A),
|
||||
CameraMove { position: glam::Vec3, front: glam::Vec3 },
|
||||
WindowResize { width: u32, height: u32 },
|
||||
EntitySpawned(hecs::Entity),
|
||||
}
|
||||
|
||||
pub trait EventHandler<A>: 'static {
|
||||
fn handle(&mut self, event: &GameEvent<A>);
|
||||
}
|
||||
|
||||
pub struct EventBus<A> {
|
||||
events: Vec<GameEvent<A>>,
|
||||
subscribers: HashMap<TypeId, Vec<Box<dyn EventHandler<A>>>>,
|
||||
}
|
||||
|
||||
impl<A: 'static + Clone> EventBus<A> {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
events: Vec::new(),
|
||||
subscribers: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn subscribe<H: EventHandler<A> + 'static>(&mut self, handler: H) {
|
||||
self.subscribers
|
||||
.entry(TypeId::of::<H>())
|
||||
.or_default()
|
||||
.push(Box::new(handler));
|
||||
}
|
||||
|
||||
pub fn emit(&mut self, event: GameEvent<A>) {
|
||||
self.events.push(event);
|
||||
}
|
||||
|
||||
/// Process all queued events, dispatching them to every registered
|
||||
/// subscriber.
|
||||
pub fn process(&mut self) {
|
||||
let events = std::mem::take(&mut self.events);
|
||||
for ev in &events {
|
||||
for subs in self.subscribers.values_mut() {
|
||||
for h in subs {
|
||||
h.handle(ev);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn drain(&mut self) -> Vec<GameEvent<A>> {
|
||||
std::mem::take(&mut self.events)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,3 +1,14 @@
|
|||
pub mod time;
|
||||
|
||||
pub use time::Time;
|
||||
|
||||
pub mod events;
|
||||
|
||||
pub use events::{EventBus, GameEvent, EventHandler};
|
||||
|
||||
pub mod assets;
|
||||
|
||||
pub use assets::AssetManager;
|
||||
|
||||
pub mod systems;
|
||||
pub use systems::{System, SystemRegistry};
|
||||
|
|
|
|||
33
raidillon_core/src/systems.rs
Normal file
33
raidillon_core/src/systems.rs
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
use hecs::World;
|
||||
|
||||
use crate::{AssetManager, EventBus};
|
||||
|
||||
/// A game/engine system that updates every frame.
|
||||
pub trait System<A> {
|
||||
/// Update the system for the current frame.
|
||||
///
|
||||
/// * `world` – mutable ECS world
|
||||
/// * `assets` – read-only resource manager
|
||||
/// * `events` – event bus for publishing/consuming game events
|
||||
/// * `dt` – time delta in seconds
|
||||
fn update(&mut self, world: &mut World, assets: &AssetManager, events: &mut EventBus<A>, dt: f32);
|
||||
}
|
||||
|
||||
/// Stores and updates a collection of boxed systems.
|
||||
pub struct SystemRegistry<A> {
|
||||
systems: Vec<Box<dyn System<A>>>,
|
||||
}
|
||||
|
||||
impl<A> SystemRegistry<A> {
|
||||
pub fn new() -> Self { Self { systems: Vec::new() } }
|
||||
|
||||
pub fn add_system<S: System<A> + 'static>(&mut self, sys: S) {
|
||||
self.systems.push(Box::new(sys));
|
||||
}
|
||||
|
||||
pub fn update_all(&mut self, world: &mut World, assets: &AssetManager, events: &mut EventBus<A>, dt: f32) {
|
||||
for s in &mut self.systems {
|
||||
s.update(world, assets, events, dt);
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue