Newer
Older
use std::fmt::Debug;
use crate::assets::LevelIndex;
use crate::ldtk::EntityInstance;
use crate::{get_ldtk_tile_scale, LdtkLayer, LdtkLevel};
#[derive(SystemParam)]
pub struct MapQuery<'w, 's> {
active: Option<Res<'w, ActiveLevel>>,
index: Res<'w, LevelIndex>,
#[system_param(ignore)]
_e: PhantomData<&'s ()>,
}
pub struct InstanceRef<'a> {
pub entity: &'a EntityInstance,
}
impl<'a> InstanceRef<'a> {
pub fn x(&self) -> i64 {
self.entity.px[0]
}
pub fn y(&self) -> i64 {
self.entity.px[1]
}
pub fn width(&self) -> i64 {
self.entity.width
}
pub fn height(&self) -> i64 {
self.entity.height
}
pub fn get_type(&self) -> &'a String {
&self.entity.identifier
}
pub fn try_get_typed_id<T: FromStr>(&self) -> Result<T, T::Err> {
T::from_str(self.get_type().as_str())
}
pub fn property(&self, name: impl ToString) -> serde_json::Value {
let target = name.to_string();
for field in &self.entity.field_instances {
if field.identifier == target {
return field
.value
.as_ref()
.unwrap_or(serde_json::Value::Null);
}
}
serde_json::Value::Null
}
}
#[derive(Copy, Clone, Debug)]
pub struct CameraBounds {
pub left: f32,
pub top: f32,
pub bottom: f32,
pub right: f32,
}
impl CameraBounds {
pub fn get_min_x(&self, camera_width: f32) -> f32 {
self.left + (camera_width / 2.0) // - (get_ldtk_tile_scale() / 2.0)
self.right - (camera_width / 2.0) // - (get_ldtk_tile_scale() / 2.0)
self.bottom + (camera_height / 2.0) // - (get_ldtk_tile_scale() / 2.0)
self.top - (camera_height / 2.0) // - (get_ldtk_tile_scale() / 2.0)
}
}
impl<'w, 's> MapQuery<'w, 's> {
// --- We put our logic in static accessors because we might source a level other
// --- than the currently active one. 'active' methods are a convenience to
// --- call the static accessors on whatever the current level is
pub fn for_each_layer_of(level: &LdtkLevel, mut cb: impl FnMut(&LdtkLayer)) {
for layer in level.layers() {
pub fn get_layers_of(level: &LdtkLevel) -> impl DoubleEndedIterator<Item = &LdtkLayer> {
level.layers()
}
pub fn get_entities_of(level: &LdtkLevel) -> Vec<&EntityInstance> {
.layers()
.flat_map(|layer| layer.as_ref().entity_instances.iter())
.collect()
pub fn get_instance_refs_of(level: &LdtkLevel) -> Vec<InstanceRef> {
.layers()
.flat_map(|layer| {
layer
.as_ref()
.entity_instances
level: &LdtkLevel,
entity_type: impl ToString,
) -> Vec<&EntityInstance> {
let e_type = entity_type.to_string();
level
.layers()
.flat_map(|layer| layer.as_ref().entity_instances.iter())
.filter(|inst| inst.identifier == e_type)
.collect()
pub fn get_filtered_instance_refs_of(
level: &LdtkLevel,
entity_type: impl ToString,
) -> Vec<InstanceRef> {
let e_type = entity_type.to_string();
level
.layers()
.flat_map(|layer| {
layer
.as_ref()
.entity_instances
.iter()
.map(|inst| InstanceRef { entity: inst })
})
.filter(|inst| inst.entity.identifier == e_type)
.collect()
}
pub fn get_owned_entities_of(level: &LdtkLevel) -> Vec<EntityInstance> {
.flat_map(|layer| layer.as_ref().entity_instances.iter().cloned())
pub fn get_camera_bounds_of(level: &LdtkLevel) -> CameraBounds {
let level = level.level_ref();
CameraBounds {
left: 0.0,
top: level.px_hei as f32,
bottom: 0.0,
right: level.px_wid as f32,
}
}
pub fn active_level_is(&self, name: impl ToString) -> bool {
.map(|active_level| active_level.map == name.to_string())
.unwrap_or(false)
}
pub fn get_active_level_name(&self) -> Option<&String> {
self.active.as_ref().map(|m| &m.map)
}
pub fn get_active_level(&self) -> Option<&LdtkLevel> {
self.get_active_level_name()
.and_then(|index| self.index.get(index))
}
pub fn get_entities(&self) -> Vec<&EntityInstance> {
self.get_active_level()
.map(MapQuery::get_entities_of)
pub fn get_instance_refs(&self) -> Vec<InstanceRef> {
self.get_active_level()
.map(MapQuery::get_instance_refs_of)
.unwrap_or_default()
}
pub fn get_camera_bounds(&self) -> Option<CameraBounds> {
self.get_active_level().map(MapQuery::get_camera_bounds_of)
}
pub fn for_each_layer(&self, cb: impl FnMut(&LdtkLayer)) {