engine/entity_manager/src/entity_manager.rs
2025-02-28 08:19:35 +01:00

180 lines
5.2 KiB
Rust

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<String>,
entity_file_map: HashMap<String, AssetPath>,
}
impl EntityManager {
pub fn new(entity_directory: impl Into<AssetPath>) -> Result<Self> {
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<String> {
&self.entity_file_list
}
/// Returns all found entity files with expected tags
pub fn entity_files_with_tags(&self, tags: &[EntityTags]) -> Result<Vec<EntityInfo>> {
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<EntityInfo> {
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<Vec<EntityTags>> {
// 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<EntityObject> {
// 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::<Context>(),
entity_parser.sound_map,
)?);
}
Ok(entity_object)
}
}