1#![doc = include_str!("../README.md")]
2#![warn(missing_docs)]
3
4use std::marker::PhantomData;
5
6use bevy_ecs::prelude::*;
7use moonshine_util::Static;
8
9pub mod load;
11
12pub mod save;
14
15pub mod prelude {
17 pub use crate::load::{
18 load_on, load_on_default_event, LoadError, LoadEvent, LoadInput, LoadWorld, Loaded,
19 TriggerLoad, Unload,
20 };
21
22 pub use crate::save::{
23 save_on, save_on_default_event, Save, SaveError, SaveEvent, SaveOutput, SaveWorld, Saved,
24 TriggerSave,
25 };
26
27 pub use bevy_ecs::{
28 entity::{EntityMapper, MapEntities},
29 reflect::ReflectMapEntities,
30 };
31}
32
33pub trait MapComponent<T: Component>: 'static + Clone + Send + Sync {
45 type Output: Component;
47
48 fn map_component(&self, component: &T) -> Self::Output;
50}
51
52impl<F: Fn(&T) -> U, T: Component, U: Component> MapComponent<T> for F
53where
54 F: 'static + Clone + Send + Sync,
55{
56 type Output = U;
57
58 fn map_component(&self, component: &T) -> Self::Output {
59 self(component)
60 }
61}
62
63#[derive(Default)]
65pub struct SceneMapper(Vec<ComponentMapperDyn>);
66
67impl SceneMapper {
68 pub fn map<T: Component>(mut self, m: impl MapComponent<T>) -> Self {
70 self.0.push(Box::new(ComponentMapperImpl::new(m)));
71 self
72 }
73
74 pub(crate) fn apply(&mut self, mut entity: EntityWorldMut) {
75 for mapper in &mut self.0 {
76 mapper.apply(&mut entity);
77 }
78 }
79
80 pub(crate) fn replace(&mut self, mut entity: EntityWorldMut) {
81 for mapper in &mut self.0 {
82 mapper.replace(&mut entity);
83 }
84 }
85
86 pub(crate) fn undo(&mut self, mut entity: EntityWorldMut) {
87 for mapper in &mut self.0 {
88 mapper.undo(&mut entity);
89 }
90 }
91}
92
93trait ComponentMapper: Static {
94 fn apply(&mut self, entity: &mut EntityWorldMut);
95
96 fn replace(&mut self, entity: &mut EntityWorldMut);
97
98 fn undo(&mut self, entity: &mut EntityWorldMut);
99}
100
101struct ComponentMapperImpl<T: Component, M: MapComponent<T>>(M, PhantomData<T>);
102
103impl<T: Component, M: MapComponent<T>> ComponentMapperImpl<T, M> {
104 fn new(m: M) -> Self {
105 Self(m, PhantomData)
106 }
107}
108
109impl<T: Component, M: MapComponent<T>> ComponentMapper for ComponentMapperImpl<T, M> {
110 fn apply(&mut self, entity: &mut EntityWorldMut) {
111 if let Some(component) = entity.get::<T>() {
112 entity.insert(self.0.map_component(component));
113 }
114 }
115
116 fn replace(&mut self, entity: &mut EntityWorldMut) {
117 if let Some(component) = entity.take::<T>() {
118 entity.insert(self.0.map_component(&component));
119 }
120 }
121
122 fn undo(&mut self, entity: &mut EntityWorldMut) {
123 entity.remove::<M::Output>();
124 }
125}
126
127type ComponentMapperDyn = Box<dyn ComponentMapper>;