use std::collections::HashMap;
use std::path::PathBuf;
use crate::core::{EntityId, SystemError};
use crate::runtime::World;
use super::solver::{ManifestSolver, SolverError, ResolvedScene};
use super::factory::{ComponentRegistry, FactoryError};
use super::manifest::{load_scene_manifest, ManifestLoaderError};
#[derive(Debug, thiserror::Error)]
pub enum SceneError {
#[error("Manifest loader error: {0}")]
ManifestLoader(#[from] ManifestLoaderError),
#[error("Solver error: {0}")]
Solver(#[from] SolverError),
#[error("Factory error: {0}")]
Factory(#[from] FactoryError),
#[error("System error: {0}")]
System(#[from] SystemError),
#[error("Scene not found: {0}")]
SceneNotFound(String),
}
pub struct SceneManager {
manifest_solver: ManifestSolver,
component_registry: ComponentRegistry,
current_scene: Option<String>,
scene_entities: HashMap<String, Vec<EntityId>>,
}
impl SceneManager {
pub fn new<P: Into<PathBuf>>(base_path: P) -> Self {
Self {
manifest_solver: ManifestSolver::new(base_path),
component_registry: ComponentRegistry::new(),
current_scene: None,
scene_entities: HashMap::new(),
}
}
pub fn load_scene(&mut self, scene_name: &str, world: &mut World) -> Result<(), SceneError> {
self.unload_current_scene(world)?;
let scene_path = format!("world/scenes/{}.yaml", scene_name);
let scene_manifest = load_scene_manifest(scene_path)?;
let resolved = self.manifest_solver.resolve_scene(&scene_manifest)?;
let entity_ids = self.instantiate_entities(&resolved, world)?;
self.scene_entities.insert(scene_name.to_string(), entity_ids);
self.current_scene = Some(scene_name.to_string());
Ok(())
}
pub fn unload_current_scene(&mut self, world: &mut World) -> Result<(), SceneError> {
if let Some(current_scene) = &self.current_scene {
if let Some(entity_ids) = self.scene_entities.remove(current_scene) {
for entity_id in entity_ids {
world.destroy_entity(entity_id);
}
}
self.current_scene = None;
}
Ok(())
}
pub fn transition_to_scene(&mut self, scene_name: &str, world: &mut World) -> Result<(), SceneError> {
self.load_scene(scene_name, world)
}
pub fn current_scene(&self) -> Option<&str> {
self.current_scene.as_deref()
}
fn instantiate_entities(&self, resolved: &ResolvedScene, world: &mut World) -> Result<Vec<EntityId>, SceneError> {
let mut entity_ids = Vec::new();
for (_entity_name, components) in &resolved.entities {
let entity_id = world.create_entity();
if let Some(entity) = world.get_entity_mut(entity_id) {
for (component_name, component_data) in components.iter() {
let component = self.component_registry.create(component_name, component_data)?;
entity.add_component_boxed(component);
}
}
entity_ids.push(entity_id);
}
Ok(entity_ids)
}
}