use std::{
fmt::{self, Debug},
sync::Arc,
};
use crate::prelude::*;
use bevy::{ecs::system::SystemParam, prelude::*};
#[allow(unused_imports)]
use crate::tiled::{
helpers::{get_layer_from_map, get_object_from_map, get_tile_from_map, get_tileset_from_map},
layer::TiledLayer,
map::{asset::TiledMapAsset, TiledMap},
object::TiledObject,
tile::{TiledTile, TiledTilemap},
world::{asset::TiledWorldAsset, TiledWorld},
};
#[derive(Message, EntityEvent, Clone, Copy, PartialEq, Debug, Reflect, Component)]
#[entity_event(auto_propagate, propagate = &'static ChildOf)]
#[reflect(Component, Debug, Clone)]
pub struct TiledEvent<E: Debug + Clone + Copy + Reflect> {
pub entity: Entity,
pub origin: Entity,
pub event: E,
world: Option<(Entity, AssetId<TiledWorldAsset>)>,
map: Option<(Entity, AssetId<TiledMapAsset>)>,
layer: Option<(Entity, u32)>,
tilemap: Option<(Entity, u32)>,
tile: Option<(Entity, TilePos, tiled::TileId)>,
object: Option<(Entity, u32)>,
}
impl<E> TiledEvent<E>
where
E: Debug + Clone + Copy + Reflect,
{
pub fn new(origin: Entity, event: E) -> Self {
Self {
entity: origin,
origin,
event,
world: None,
map: None,
layer: None,
tilemap: None,
tile: None,
object: None,
}
}
pub fn transmute<O>(&self, origin: Option<Entity>, event: O) -> TiledEvent<O>
where
O: Debug + Clone + Copy + Reflect,
{
TiledEvent::<O> {
entity: self.entity,
origin: origin.unwrap_or(self.origin),
event,
world: self.world,
map: self.map,
layer: self.layer,
tilemap: self.tilemap,
tile: self.tile,
object: self.object,
}
}
pub fn with_world(&mut self, entity: Entity, asset_id: AssetId<TiledWorldAsset>) -> &mut Self {
self.world = Some((entity, asset_id));
self
}
pub fn with_map(&mut self, entity: Entity, asset_id: AssetId<TiledMapAsset>) -> &mut Self {
self.map = Some((entity, asset_id));
self
}
pub fn with_layer(&mut self, entity: Entity, layer_id: u32) -> &mut Self {
self.layer = Some((entity, layer_id));
self
}
pub fn with_object(&mut self, entity: Entity, object_id: u32) -> &mut Self {
self.object = Some((entity, object_id));
self
}
pub fn with_tilemap(&mut self, entity: Entity, tileset_id: u32) -> &mut Self {
self.tilemap = Some((entity, tileset_id));
self
}
pub fn with_tile(
&mut self,
entity: Entity,
position: TilePos,
tile_id: tiled::TileId,
) -> &mut Self {
self.tile = Some((entity, position, tile_id));
self
}
pub fn send(&self, commands: &mut Commands, message_writer: &mut MessageWriter<TiledEvent<E>>) {
commands.trigger(*self);
message_writer.write(*self);
}
}
impl<'a, E> TiledEvent<E>
where
E: Debug + Clone + Copy + Reflect,
{
pub fn get_world_entity(&self) -> Option<Entity> {
self.world.map(|(e, _)| e)
}
pub fn get_world_asset(
&self,
assets: &'a Res<Assets<TiledWorldAsset>>,
) -> Option<&'a TiledWorldAsset> {
self.world.and_then(|(_, id)| assets.get(id))
}
pub fn get_world(&self, assets: &'a Res<Assets<TiledWorldAsset>>) -> Option<&'a tiled::World> {
self.get_world_asset(assets).map(|w| &w.world)
}
pub fn get_map_entity(&self) -> Option<Entity> {
self.map.map(|(e, _)| e)
}
pub fn get_map_asset(
&self,
assets: &'a Res<Assets<TiledMapAsset>>,
) -> Option<&'a TiledMapAsset> {
self.map.and_then(|(_, id)| assets.get(id))
}
pub fn get_map(&self, assets: &'a Res<Assets<TiledMapAsset>>) -> Option<&'a tiled::Map> {
self.get_map_asset(assets).map(|m| &m.map)
}
pub fn get_layer_entity(&self) -> Option<Entity> {
self.layer.map(|(e, _)| e)
}
pub fn get_layer_id(&self) -> Option<u32> {
self.layer.map(|(_, id)| id)
}
pub fn get_layer(&self, assets: &'a Res<Assets<TiledMapAsset>>) -> Option<tiled::Layer<'a>> {
self.get_map(assets).and_then(|map| {
self.get_layer_id()
.and_then(|id| get_layer_from_map(map, id))
})
}
pub fn get_tilemap_entity(&self) -> Option<Entity> {
self.tilemap.map(|(e, _)| e)
}
pub fn get_tilemap_tileset_id(&self) -> Option<u32> {
self.tilemap.map(|(_, id)| id)
}
pub fn get_tilemap_tileset(
&self,
assets: &'a Res<Assets<TiledMapAsset>>,
) -> Option<&'a Arc<tiled::Tileset>> {
self.get_map(assets).and_then(|map| {
self.get_tilemap_tileset_id()
.and_then(|id| get_tileset_from_map(map, id))
})
}
pub fn get_tile_entity(&self) -> Option<Entity> {
self.tile.map(|(e, _, _)| e)
}
pub fn get_tile_pos(&self) -> Option<TilePos> {
self.tile.map(|(_, pos, _)| pos)
}
pub fn get_tile_id(&self) -> Option<tiled::TileId> {
self.tile.map(|(_, _, id)| id)
}
pub fn get_tile(&self, assets: &'a Res<Assets<TiledMapAsset>>) -> Option<tiled::Tile<'a>> {
self.get_map(assets).and_then(|map| {
self.get_tilemap_tileset_id().and_then(|tileset_id| {
self.get_tile_id()
.and_then(|id| get_tile_from_map(map, tileset_id, id))
})
})
}
pub fn get_object_entity(&self) -> Option<Entity> {
self.object.map(|(e, _)| e)
}
pub fn get_object_id(&self) -> Option<u32> {
self.object.map(|(_, id)| id)
}
pub fn get_object(&self, assets: &'a Res<Assets<TiledMapAsset>>) -> Option<tiled::Object<'a>> {
self.get_map(assets).and_then(|map| {
self.get_object_id()
.and_then(|id| get_object_from_map(map, id))
})
}
}
#[derive(Clone, Copy, PartialEq, Debug, Reflect)]
#[reflect(Clone, PartialEq)]
pub struct WorldCreated;
#[derive(Clone, Copy, PartialEq, Debug, Reflect)]
#[reflect(Clone, PartialEq)]
pub struct MapCreated;
#[derive(Clone, Copy, PartialEq, Debug, Reflect)]
#[reflect(Clone, PartialEq)]
pub struct LayerCreated;
#[derive(Clone, Copy, PartialEq, Debug, Reflect)]
#[reflect(Clone, PartialEq)]
pub struct TilemapCreated;
#[derive(Clone, Copy, PartialEq, Debug, Reflect)]
#[reflect(Clone, PartialEq)]
pub struct TileCreated;
#[derive(Clone, Copy, PartialEq, Debug, Reflect)]
#[reflect(Clone, PartialEq)]
pub struct ObjectCreated;
#[derive(SystemParam)]
pub(crate) struct TiledMessageWriters<'w> {
pub world_created: MessageWriter<'w, TiledEvent<WorldCreated>>,
pub map_created: MessageWriter<'w, TiledEvent<MapCreated>>,
pub layer_created: MessageWriter<'w, TiledEvent<LayerCreated>>,
pub tilemap_created: MessageWriter<'w, TiledEvent<TilemapCreated>>,
pub tile_created: MessageWriter<'w, TiledEvent<TileCreated>>,
pub object_created: MessageWriter<'w, TiledEvent<ObjectCreated>>,
}
impl fmt::Debug for TiledMessageWriters<'_> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("TiledMessageWriters").finish()
}
}
pub(crate) fn plugin(app: &mut App) {
app.add_message::<TiledEvent<WorldCreated>>()
.register_type::<TiledEvent<WorldCreated>>();
app.add_message::<TiledEvent<MapCreated>>()
.register_type::<TiledEvent<MapCreated>>();
app.add_message::<TiledEvent<LayerCreated>>()
.register_type::<TiledEvent<LayerCreated>>();
app.add_message::<TiledEvent<TilemapCreated>>()
.register_type::<TiledEvent<TilemapCreated>>();
app.add_message::<TiledEvent<TileCreated>>()
.register_type::<TiledEvent<TileCreated>>();
app.add_message::<TiledEvent<ObjectCreated>>()
.register_type::<TiledEvent<ObjectCreated>>();
}