use std::any::{Any, TypeId};
use std::fmt::Debug;
use super::entity::Entity;
use super::input::InputState;
use crate::runtime::{AssetManager, Camera};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct SystemId(u64);
impl SystemId {
pub fn new(id: u64) -> Self {
SystemId(id)
}
pub fn from_str(name: &str) -> Self {
use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher};
let mut hasher = DefaultHasher::new();
name.hash(&mut hasher);
SystemId(hasher.finish())
}
pub fn from_type<T: 'static>() -> Self {
use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher};
let type_id = TypeId::of::<T>();
let mut hasher = DefaultHasher::new();
type_id.hash(&mut hasher);
SystemId(hasher.finish())
}
pub fn as_u64(&self) -> u64 {
self.0
}
}
pub struct SystemContext<'a> {
pub delta_time: f32,
pub frame_number: u64,
pub total_time: f32,
pub entities: &'a mut Vec<Entity>,
pub input: &'a InputState,
pub camera: &'a Camera,
pub asset_manager: &'a mut AssetManager,
}
impl<'a> SystemContext<'a> {
pub fn new(
delta_time: f32,
frame_number: u64,
total_time: f32,
entities: &'a mut Vec<Entity>,
input: &'a InputState,
camera: &'a Camera,
asset_manager: &'a mut AssetManager,
) -> Self {
Self {
delta_time,
frame_number,
total_time,
entities,
input,
camera,
asset_manager,
}
}
}
pub trait System: Any + Send + Sync {
fn id(&self) -> SystemId;
fn initialize(&mut self) -> Result<(), SystemError> {
Ok(())
}
fn update(&mut self, context: &mut SystemContext) -> Result<(), SystemError>;
fn shutdown(&mut self) -> Result<(), SystemError> {
Ok(())
}
fn name(&self) -> &'static str {
std::any::type_name::<Self>()
}
fn is_enabled(&self) -> bool {
true
}
fn set_enabled(&mut self, enabled: bool) {
let _ = enabled;
}
fn as_any(&self) -> &dyn Any;
fn as_any_mut(&mut self) -> &mut dyn Any;
}
#[derive(Debug, Clone)]
pub enum SystemError {
InitializationFailed(String),
UpdateFailed(String),
ShutdownFailed(String),
RuntimeError(String),
}
impl std::fmt::Display for SystemError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
SystemError::InitializationFailed(msg) => write!(f, "System initialization failed: {}", msg),
SystemError::UpdateFailed(msg) => write!(f, "System update failed: {}", msg),
SystemError::ShutdownFailed(msg) => write!(f, "System shutdown failed: {}", msg),
SystemError::RuntimeError(msg) => write!(f, "System runtime error: {}", msg),
}
}
}
impl std::error::Error for SystemError {}