use std::sync::Arc;
use std::path::PathBuf;
use crate::core::{SystemError, InputState};
use super::world::World;
use super::asset::AssetManager;
use super::scene::manifest::{load_project_manifest, ProjectManifest};
use super::scene::SceneManager;
use super::input::InputManager;
pub struct Engine {
pub world: World,
pub input_manager: InputManager,
pub asset_manager: AssetManager,
scene_manager: Option<SceneManager>,
project_root: PathBuf,
project_manifest: Option<ProjectManifest>,
initialized: bool,
}
impl Engine {
pub fn new<P: Into<PathBuf>>(project_root: P) -> Self {
let project_root = project_root.into();
let project_yaml = project_root.join("project.yaml");
let manifest = load_project_manifest(&project_yaml)
.map_err(|e| SystemError::RuntimeError(format!("Failed: {}", e)))
.unwrap();
log::info!("✅ Project loaded: {} v{}", manifest.name, manifest.version);
let asset_root = manifest.config.as_ref()
.and_then(|c| c.asset_root.as_ref())
.map(|s| s.as_str())
.unwrap_or("assets");
let asset_root_path = project_root.join(asset_root);
Self {
world: World::new(),
input_manager: InputManager::new(),
asset_manager: AssetManager::new(asset_root_path),
scene_manager: Some(SceneManager::new(project_root.clone())),
project_root,
project_manifest: Some(manifest),
initialized: false,
}
}
pub async fn initialize(&mut self, window: Arc<winit::window::Window>) -> Result<(), SystemError> {
self.world.initialize(window).await?;
if let Some(manifest) = &self.project_manifest {
if let Some(config) = &manifest.config {
let entry_scene = &config.entry_scene;
log::info!("🎬 Loading entry scene: {}", entry_scene);
if let Some(scene_manager) = &mut self.scene_manager {
scene_manager.load_scene(entry_scene, &mut self.world)
.map_err(|e| SystemError::RuntimeError(format!("Failed to load entry scene: {}", e)))?;
}
}
}
self.initialized = true;
log::info!("✅ MoltRun Engine 초기화 완료");
Ok(())
}
pub fn update(&mut self, delta_time: f32) -> Result<(), SystemError> {
if !self.initialized {
return Err(SystemError::RuntimeError("Engine not initialized. Call initialize() first.".to_string()));
}
self.input_manager.begin_frame();
self.world.update(delta_time, self.input_manager.state(), &mut self.asset_manager)?;
self.input_manager.end_frame();
Ok(())
}
pub fn asset_manager(&self) -> &AssetManager {
&self.asset_manager
}
pub fn asset_manager_mut(&mut self) -> &mut AssetManager {
&mut self.asset_manager
}
pub fn shutdown(&mut self) -> Result<(), SystemError> {
if self.initialized {
self.world.shutdown()?;
self.initialized = false;
log::info!("MoltRun Engine 종료됨");
}
Ok(())
}
pub fn is_initialized(&self) -> bool {
self.initialized
}
pub fn project_manifest(&self) -> Option<&ProjectManifest> {
self.project_manifest.as_ref()
}
pub fn project_root(&self) -> &PathBuf {
&self.project_root
}
pub fn scene_manager_mut(&mut self) -> Option<&mut SceneManager> {
self.scene_manager.as_mut()
}
pub fn load_scene(&mut self, scene_name: &str) -> Result<(), SystemError> {
if let Some(scene_manager) = &mut self.scene_manager {
scene_manager.load_scene(scene_name, &mut self.world)
.map_err(|e| SystemError::RuntimeError(format!("Failed to load scene: {}", e)))?;
}
Ok(())
}
pub fn handle_window_event(&mut self, event: &winit::event::WindowEvent) {
self.input_manager.process_window_event(event);
}
pub fn input_state(&self) -> &InputState {
self.input_manager.state()
}
pub fn reload_current_scene(&mut self) -> Result<(), SystemError> {
if let Some(scene_manager) = &mut self.scene_manager {
if let Some(scene_name) = scene_manager.current_scene().map(|s| s.to_string()) {
scene_manager.load_scene(&scene_name, &mut self.world)
.map_err(|e| SystemError::RuntimeError(format!("Failed to reload scene: {}", e)))?;
Ok(())
} else {
Err(SystemError::RuntimeError("No scene loaded".to_string()))
}
} else {
Err(SystemError::RuntimeError("SceneManager not available".to_string()))
}
}
}
impl Default for Engine {
fn default() -> Self {
Self::new(".")
}
}