use super::{ffi, DataHandle, Entity, World};
use std::collections::HashMap;
pub struct WorldReflection {
_id: DataHandle,
strings: HashMap<ffi::DataHandle, String>,
parameters: HashMap<ffi::DataHandle, Vec<ffi::ParameterMetaDataEntry>>,
components: Vec<ffi::ComponentMetaDataEntry>,
}
impl WorldReflection {
pub fn create() -> Self {
let data = World::create_data(ffi::CreateDataType::ComponentsMetaData, &[]);
let mut strings = HashMap::new();
let mut parameters_all = HashMap::new();
let root = data.read::<ffi::ComponentsMetaDataEntry>();
let components = DataHandle::from_ffi(root.components);
let components = components.read_vec::<ffi::ComponentMetaDataEntry>();
for c in &components {
let parameters = DataHandle::from_ffi(c.parameters);
let parameters = parameters.read_vec::<ffi::ParameterMetaDataEntry>();
let c_name = DataHandle::from_ffi(c.name).read_str();
let _ = strings.insert(c.name, c_name);
for p in ¶meters {
let p_name = DataHandle::from_ffi(p.name).read_str();
let _ = strings.insert(p.name, p_name);
}
let _ = parameters_all.insert(c.parameters, parameters);
}
Self {
_id: data,
strings,
parameters: parameters_all,
components,
}
}
pub fn get() -> &'static Self {
unsafe {
static mut REFLECTION: Option<WorldReflection> = None;
if REFLECTION.is_none() {
REFLECTION = Some(Self::create());
}
REFLECTION.as_ref().unwrap()
}
}
pub fn components(&self) -> &[ffi::ComponentMetaDataEntry] {
&self.components
}
pub fn components_for_entity(&self, entity: Entity) -> Vec<ffi::ComponentMetaDataEntry> {
let components = World::get_components_vec(entity);
let mut ret_components = self.components.clone();
ret_components.retain(|c| components.contains(&c.component_type));
ret_components
}
pub fn parameters(&self, data: ffi::DataHandle) -> &[ffi::ParameterMetaDataEntry] {
if let Some(parameters) = self.parameters.get(&data) {
parameters
} else {
&[]
}
}
pub fn string(&self, data: ffi::DataHandle) -> &str {
if let Some(string) = self.strings.get(&data) {
string
} else {
""
}
}
pub fn parameter(
&self,
component_type: ffi::ComponentType,
parameter_id: u32,
) -> Option<&ffi::ParameterMetaDataEntry> {
for component in self.components() {
if component_type == component.component_type {
for p in self.parameters(component.parameters) {
if p.parameter_id == parameter_id {
return Some(p);
}
}
}
}
None
}
}