use std::any::Any;
use bevy::prelude::*;
use jackdaw_api_internal::snapshot::{ActiveSnapshotter, SceneSnapshot, SceneSnapshotter};
use jackdaw_avian_integration::PhysicsOverlayConfig;
use jackdaw_jsn::SceneJsnAst;
use crate::brush::EditMode;
use crate::gizmos::{GizmoMode, GizmoSpace};
use crate::snapping::SnapSettings;
use crate::view_modes::ViewModeSettings;
use crate::viewport_overlays::OverlaySettings;
use crate::viewport_select::GroupEditState;
pub(super) fn plugin(app: &mut App) {
app.insert_resource(ActiveSnapshotter(Box::new(JsnAstSnapshotter)));
}
pub struct JsnAstSnapshotter;
impl SceneSnapshotter for JsnAstSnapshotter {
fn capture(&self, world: &mut World) -> Box<dyn SceneSnapshot> {
Box::new(JsnAstSnapshot {
ast: crate::scene_io::build_snapshot_ast(world),
editor_state: EditorStateSnapshot::capture(world),
})
}
}
pub struct JsnAstSnapshot {
ast: SceneJsnAst,
editor_state: EditorStateSnapshot,
}
impl SceneSnapshot for JsnAstSnapshot {
fn apply(&self, world: &mut World) {
crate::scene_io::apply_ast_to_world(world, &self.ast);
self.editor_state.apply(world);
}
fn equals(&self, other: &dyn SceneSnapshot) -> bool {
other
.as_any()
.downcast_ref::<Self>()
.is_some_and(|o| self.ast == o.ast && self.editor_state == o.editor_state)
}
fn clone_box(&self) -> Box<dyn SceneSnapshot> {
Box::new(Self {
ast: self.ast.clone(),
editor_state: self.editor_state.clone(),
})
}
fn as_any(&self) -> &dyn Any {
self
}
}
#[derive(Clone, PartialEq)]
struct EditorStateSnapshot {
edit_mode: EditMode,
gizmo_mode: GizmoMode,
gizmo_space: GizmoSpace,
snap_settings: SnapSettings,
view_mode: ViewModeSettings,
overlays: OverlaySettings,
physics_overlays: PhysicsOverlayConfig,
active_group: Option<Entity>,
}
impl EditorStateSnapshot {
fn capture(world: &World) -> Self {
Self {
edit_mode: *world.resource::<EditMode>(),
gizmo_mode: *world.resource::<GizmoMode>(),
gizmo_space: *world.resource::<GizmoSpace>(),
snap_settings: world.resource::<SnapSettings>().clone(),
view_mode: world.resource::<ViewModeSettings>().clone(),
overlays: world.resource::<OverlaySettings>().clone(),
physics_overlays: world.resource::<PhysicsOverlayConfig>().clone(),
active_group: world.resource::<GroupEditState>().active_group,
}
}
fn apply(&self, world: &mut World) {
*world.resource_mut::<EditMode>() = self.edit_mode;
*world.resource_mut::<GizmoMode>() = self.gizmo_mode;
*world.resource_mut::<GizmoSpace>() = self.gizmo_space;
*world.resource_mut::<SnapSettings>() = self.snap_settings.clone();
*world.resource_mut::<ViewModeSettings>() = self.view_mode.clone();
*world.resource_mut::<OverlaySettings>() = self.overlays.clone();
*world.resource_mut::<PhysicsOverlayConfig>() = self.physics_overlays.clone();
let valid_group = self.active_group.filter(|e| world.get_entity(*e).is_ok());
world.resource_mut::<GroupEditState>().active_group = valid_group;
}
}