use bevy::{
ecs::entity::EntityMap,
prelude::*,
};
use crate::{
reflect::CloneReflect,
Rollbacks,
SaveableRegistry,
};
pub(crate) struct Capture {
pub(crate) resources: Vec<Box<dyn Reflect>>,
pub(crate) scene: DynamicScene,
}
impl Capture {
pub fn apply(&self, world: &mut World) {
world.clear_entities();
world.clear_trackers();
let _s = self.scene.write_to_world(world, &mut EntityMap::default());
let registry_arc = world.resource::<AppTypeRegistry>().clone();
let registry = registry_arc.read();
for reflect in &self.resources {
if let Some(reg) = registry.get_with_name(reflect.type_name()) {
if let Some(res) = reg.data::<ReflectResource>() {
res.apply(world, reflect.as_reflect());
}
}
}
}
}
impl Clone for Capture {
fn clone(&self) -> Self {
Self {
resources: self.resources.clone_value(),
scene: self.scene.clone_value(),
}
}
}
pub struct Snapshot {
pub(crate) capture: Capture,
pub(crate) rollbacks: Rollbacks,
}
impl Snapshot {
pub fn retain<F>(&mut self, f: F)
where
F: FnMut(&Box<dyn Reflect>) -> bool,
{
self.capture.resources.retain(f);
}
pub fn apply(&self, world: &mut World) {
self.capture.apply(world);
world.insert_resource(self.rollbacks.clone());
}
pub fn into_rollback(mut self, world: &mut World) -> RollbackSnapshot {
let saveables = world.resource::<SaveableRegistry>();
self.retain(|reg| saveables.can_rollback(reg.type_name()));
RollbackSnapshot {
capture: self.capture,
}
}
}
#[derive(Clone)]
pub struct RollbackSnapshot {
pub(crate) capture: Capture,
}
impl RollbackSnapshot {
pub fn rollback(&self, world: &mut World) {
self.capture.apply(world);
}
}