UNDO/REDO FINALLY DONE

This commit is contained in:
RustyStriker 2022-09-08 20:23:50 +03:00
parent 718a2c3f06
commit 9652ae1a08
6 changed files with 142 additions and 21 deletions

View file

@ -1,15 +1,16 @@
use bevy::math::Vec3Swizzles;
use bevy::prelude::*;
use bevy_prototype_lyon::prelude::*;
use crate::{ShapeData, ImageData};
use crate::{ShapeData, ImageData, CreateShape, PointSize};
#[derive(Debug, Clone)]
pub enum UndoItem {
Base,
CreateShape { entity: Entity },
DeleteShape { sd: ShapeData, transform: Transform },
DeleteShape { transform: Transform, edges: Vec<Vec2>, name: String, note: String, shape: CreateShape, dm: DrawMode, old_entity: Entity },
MoveItem { shape: Entity, from: Vec2, to: Vec2 },
MoveDot { shape_data: Entity, dot: Entity, from: Vec2, to: Vec2 },
MoveDot { shape_data: Entity, dot: usize, from: Vec2, to: Vec2 },
Rotate { entity: Entity, from: f32, to: f32 },
NameChange { entity: Entity, from: String },
NoteChange { entity: Entity, from: String },
@ -74,25 +75,90 @@ pub fn undo_redo_sys(
mut coms: Commands,
mut stack: ResMut<UndoStack>,
keyboard: Res<Input<KeyCode>>,
p_size: Res<PointSize>,
mut shapes: Query<&mut ShapeData>,
mut transforms: Query<&mut Transform>,
global_transforms: Query<&GlobalTransform>,
mut images: Query<(&mut ImageData, &Handle<Image>)>,
mut paths: Query<&mut bevy_prototype_lyon::prelude::Path>,
draw_modes: Query<&DrawMode>,
) {
if keyboard.just_pressed(KeyCode::Z) && keyboard.pressed(KeyCode::LControl) {
let item = if keyboard.pressed(KeyCode::LShift) { stack.unpop() } else { stack.pop() };
if let Some(item) = item {
match item {
UndoItem::Base => bevy::log::error!("POP/UNPOP: Got UndoItem::Base as a result!"),
UndoItem::CreateShape { entity: _ } => {
bevy::log::error!("NOT IMPLEMENTED : CreateShape");
UndoItem::CreateShape { entity } => {
let transform = transforms.get(*entity).map(|t| *t).unwrap_or_default();
let mut sd = shapes.get_mut(*entity).unwrap();
let mut name = String::new();
let mut note = String::new();
std::mem::swap(&mut name, &mut sd.name);
std::mem::swap(&mut note, &mut sd.note);
let edges = sd.edges.iter().map(|e| transforms.get(*e).unwrap().translation.xy()).collect::<Vec<Vec2>>();
let dm = *draw_modes.get(*entity).unwrap();
let shape = sd.shape;
coms.entity(*entity).despawn_recursive();
*item = UndoItem::DeleteShape { transform, edges, name, note, shape, dm, old_entity: *entity };
},
UndoItem::DeleteShape {
sd: _,
transform: _,
transform,
edges,
name,
note,
shape,
dm,
old_entity,
} => {
bevy::log::error!("NOT IMPLEMENTED : DeleteShape");
let main_shape = spawn_main_shape(&mut coms, *dm, *transform, *shape, edges.clone());
let dots_dm = DrawMode::Fill(FillMode::color(Color::RED));
let dot_shape = shapes::Circle { radius: p_size.0, center: Vec2::ZERO };
let center = coms.spawn_bundle(GeometryBuilder::build_as(
&dot_shape,
dots_dm,
Transform::from_xyz(0.0, 0.0, 0.5)
)).id();
let edges = edges.iter().map(|v| {
coms.spawn_bundle(GeometryBuilder::build_as(
&dot_shape,
dots_dm,
Transform::from_translation(v.extend(0.5))
)).id()
}).collect::<Vec<Entity>>();
let mut nname = String::new();
let mut nnote = String::new();
std::mem::swap(&mut nname, name);
std::mem::swap(&mut nnote, note);
let mut main_shape = coms.entity(main_shape);
edges.iter().for_each(|e| { main_shape.add_child(*e); });
let sd = ShapeData { name: nname, shape: *shape, main_shape: main_shape.id(), edges, center: Some(center), note: nnote };
main_shape
.insert(sd)
.add_child(center);
let oe = *old_entity;
*item = UndoItem::CreateShape { entity: main_shape.id() };
let f = |ne: &mut Entity| { if *ne == oe { *ne = main_shape.id(); }};
for i in stack.items.iter_mut() {
match i {
UndoItem::CreateShape { entity } => f(entity),
UndoItem::MoveDot { shape_data, ..} => f(shape_data),
UndoItem::MoveItem { shape, .. } => f(shape),
UndoItem::Rotate { entity, .. } => f(entity),
UndoItem::NameChange { entity, .. } => f(entity),
UndoItem::NoteChange { entity, .. } => f(entity),
UndoItem::ChangeZ { entity, .. } => f(entity),
UndoItem::ReScale { entity, .. } => f(entity),
_ => {},
}
}
},
UndoItem::MoveItem { shape, from, to } => {
if let Ok(mut t) = transforms.get_mut(*shape) {
@ -103,13 +169,14 @@ pub fn undo_redo_sys(
*to = t;
},
UndoItem::MoveDot { shape_data, dot, from, to } => {
let gt = global_transforms.get(*dot).unwrap();
let sd = shapes.get(*shape_data).unwrap();
let dot = sd.edges[*dot];
let gt = global_transforms.get(dot).unwrap();
let rot = gt.to_scale_rotation_translation().1;
let ang = rot.to_euler(EulerRot::XYZ).2;
let delta = Mat2::from_angle(-ang) * (*from - gt.translation().xy());
if let Ok(mut t) = transforms.get_mut(*dot) {
if let Ok(mut t) = transforms.get_mut(dot) {
t.translation += delta.extend(0.0);
}
// We need to recalculate the center, and update the points to be the new relevant point from the center
@ -217,4 +284,31 @@ pub fn undo_redo_sys(
bevy::log::info!("Nothing to pop/unpop!");
}
}
}
fn spawn_main_shape(coms: &mut Commands, dm: DrawMode, trans: Transform, shape: CreateShape, edges: Vec<Vec2>) -> Entity {
match shape {
CreateShape::Triangle => {
coms.spawn_bundle(GeometryBuilder::build_as(
&shapes::Polygon { points: edges, closed: true },
dm,
trans
)).id()
},
CreateShape::Square => {
coms.spawn_bundle(GeometryBuilder::build_as(
&shapes::Rectangle { extents: (edges[0] - edges[1]).abs(), ..Default::default() },
dm,
trans
)).id()
},
CreateShape::Circle => {
coms.spawn_bundle(GeometryBuilder::build_as(
&shapes::Circle { radius: edges[0].length(), center: Vec2::ZERO },
dm,
trans
)).id()
},
CreateShape::Capsule => unimplemented!("I should prob get rid of this..."),
}
}