use std::collections::HashMap; use anyhow::Result; use assetpath::AssetPath; use engine::prelude::*; use crate::{animation_info::AnimationInfo, hitbox::HitBox}; use super::{entity_info::EntityInfo, entity_tags::EntityTags, entityparser::EntityParser}; pub struct EntityManager { entity_directory: AssetPath, resource_base_path: String, entity_file_list: Vec, entity_file_map: HashMap, } impl EntityManager { pub fn new(entity_directory: impl Into) -> Result { let entity_directory = entity_directory.into(); let resource_base_path = entity_directory.prefix().unwrap().to_string(); let mut me = Self { entity_directory, resource_base_path, entity_file_list: Vec::new(), entity_file_map: HashMap::new(), }; me.update_files()?; Ok(me) } /// Updates the lists of all '.gltf' and '.ent' files pub fn update_files(&mut self) -> Result<()> { let (entity_file_list, entity_file_map) = search_file_names(&self.entity_directory, ".ent")?; self.entity_file_list = entity_file_list; self.entity_file_map = entity_file_map; Ok(()) } /// Returns all entity files pub fn entity_files(&self) -> &Vec { &self.entity_file_list } /// Returns all found entity files with expected tags pub fn entity_files_with_tags(&self, tags: &[EntityTags]) -> Result> { let mut entity_files = Vec::new(); if tags.is_empty() { return Ok(entity_files); } for entity_file in self.entity_file_list.iter() { // load entity file let file = self.load_entity_file(entity_file); let entity_parser = EntityParser::parse(file)?; // check for tags for tag in tags.iter() { if entity_parser.tags.contains(tag) { entity_files.push(EntityInfo { file_name: entity_file.clone(), hitbox_radius: if entity_parser.enable_hitbox { Some(entity_parser.hitbox_radius) } else { None }, tags: entity_parser.tags, }); break; } } } Ok(entity_files) } pub fn entity_info(&self, entity_file: &str) -> Result { let file = self.load_entity_file(entity_file); let entity_parser = EntityParser::parse(file)?; Ok(EntityInfo { file_name: entity_file.to_string(), hitbox_radius: if entity_parser.enable_hitbox { Some(entity_parser.hitbox_radius) } else { None }, tags: entity_parser.tags, }) } pub fn get_tags(&self, entity_file: &str) -> Result> { // load entity file let file = self.load_entity_file(entity_file); let entity_parser = EntityParser::parse(file)?; Ok(entity_parser.tags) } fn load_entity_file(&self, entity_file: &str) -> &AssetPath { match self.entity_file_map.get(entity_file) { Some(file) => file, None => { // return Err(EngineError::FileNotFound( // "Entity".to_string(), // entity_file.to_string(), // )) todo!(); } } } } impl AssetLoader for EntityManager { /// Loads an entity file and creates an Entity fn load_entity( &mut self, assets: &mut AssetHandler<'_>, entity_file: &str, ) -> Result { // load entity file let file = self.load_entity_file(entity_file); #[allow(unused_mut)] let mut entity_parser = EntityParser::parse(file)?; // load asset let mut entity_object = assets.create_entity(&entity_parser.gltf_file_name)?; #[cfg(debug_assertions)] { entity_object.debug_name = Some(entity_file.to_string()); } if entity_parser.enable_hitbox { entity_object.insert_component(HitBox::new( entity_parser.hitbox_radius, entity_parser.hitbox_height, )); } entity_parser .animation_map .retain(|_animation_type, indices| !indices.is_empty()); if !entity_parser.animation_map.is_empty() { entity_object.insert_component(AnimationInfo::new( entity_parser.animations, entity_parser.animation_map, )); } if !entity_parser.sound_map.is_empty() { for audio_path in entity_parser.sound_map.values_mut() { if !audio_path.is_empty() { audio_path.set_prefix(&self.resource_base_path); } } entity_object.insert_component(Audio::new( assets.world().resources.get_mut::(), entity_parser.sound_map, )?); } Ok(entity_object) } }