From 02b29bd093dfefd4609099b602ce13346cf68f3b Mon Sep 17 00:00:00 2001
From: tuxmain <tuxmain@zettascript.org>
Date: Fri, 26 Aug 2022 10:05:32 +0200
Subject: [PATCH] editor: move platforms

---
 src/editor.rs | 114 ++++++++++++++++++++++++++++++++++++++++----------
 1 file changed, 92 insertions(+), 22 deletions(-)

diff --git a/src/editor.rs b/src/editor.rs
index 9d1749a..08ebb43 100644
--- a/src/editor.rs
+++ b/src/editor.rs
@@ -1,3 +1,4 @@
+#![allow(clippy::type_complexity)]
 use crate::{levels::stored::*, AppState};
 
 use bevy::{
@@ -6,6 +7,7 @@ use bevy::{
 		shape::{Circle, Quad},
 		*,
 	},
+	sprite::Mesh2dHandle,
 };
 use bevy_mod_picking::*;
 
@@ -13,28 +15,39 @@ pub struct EditorPlugin;
 
 impl Plugin for EditorPlugin {
 	fn build(&self, app: &mut App) {
-		app.add_plugins(DefaultPickingPlugins)
+		app.add_event::<DragEndEvent>()
+			.add_plugins(DefaultPickingPlugins)
 			.add_system_set(SystemSet::on_enter(AppState::Editor).with_system(setup))
 			.add_system_set(
-				SystemSet::on_update(AppState::Editor).with_system(keyboard_input_system),
+				SystemSet::on_update(AppState::Editor)
+					.with_system(keyboard_input_system)
+					.with_system(follow_ends_system),
 			);
 	}
 }
 
+// Events
+
+struct DragEndEvent(Entity);
+
+// Components
+
 #[derive(Component)]
-struct Platform;
+struct Platform(Entity, Entity);
 
 #[derive(Component)]
 struct Draggable;
 
 #[derive(Component)]
-struct End;
+struct End(Entity);
+
+// Bundles
 
 #[derive(Bundle)]
 struct PlatformBundle {
 	#[bundle]
 	mesh: ColorMesh2dBundle,
-	platform: Platform,
+	//platform: Platform,
 }
 
 #[derive(Bundle)]
@@ -47,6 +60,8 @@ struct PlatformEndBundle {
 	end: End,
 }
 
+// Functions
+
 fn spawn_platform(
 	commands: &mut Commands,
 	meshes: &mut ResMut<Assets<Mesh>>,
@@ -55,7 +70,7 @@ fn spawn_platform(
 	transform: Transform,
 	size: Vec2,
 ) {
-	commands
+	let platform = commands
 		.spawn_bundle(PlatformBundle {
 			mesh: ColorMesh2dBundle {
 				mesh: meshes.add(Mesh::from(Quad { size, flip: false })).into(),
@@ -63,10 +78,11 @@ fn spawn_platform(
 				transform,
 				..default()
 			},
-			platform: Platform,
 		})
-		.with_children(|c| {
-			c.spawn_bundle(PlatformEndBundle {
+		.id();
+	let ends = Platform(
+		commands
+			.spawn_bundle(PlatformEndBundle {
 				mesh: ColorMesh2dBundle {
 					mesh: meshes
 						.add(Mesh::from(Circle {
@@ -75,14 +91,20 @@ fn spawn_platform(
 						}))
 						.into(),
 					material: materials.add(ColorMaterial::from(Color::rgba(1., 1., 0., 0.7))),
-					transform: Transform::from_xyz(-size.x / 2., -size.y / 2., 0.5),
+					transform: Transform::from_xyz(
+						transform.translation.x - size.x / 2.,
+						transform.translation.y - size.y / 2.,
+						0.5,
+					),
 					..default()
 				},
 				pickable: PickableBundle::default(),
 				draggable: Draggable,
-				end: End,
-			});
-			c.spawn_bundle(PlatformEndBundle {
+				end: End(platform),
+			})
+			.id(),
+		commands
+			.spawn_bundle(PlatformEndBundle {
 				mesh: ColorMesh2dBundle {
 					mesh: meshes
 						.add(Mesh::from(Circle {
@@ -91,14 +113,20 @@ fn spawn_platform(
 						}))
 						.into(),
 					material: materials.add(ColorMaterial::from(Color::rgba(1., 1., 0., 0.7))),
-					transform: Transform::from_xyz(size.x / 2., size.y / 2., 0.5),
+					transform: Transform::from_xyz(
+						transform.translation.x + size.x / 2.,
+						transform.translation.y + size.y / 2.,
+						0.5,
+					),
 					..default()
 				},
 				pickable: PickableBundle::default(),
 				draggable: Draggable,
-				end: End,
-			});
-		});
+				end: End(platform),
+			})
+			.id(),
+	);
+	commands.entity(platform).insert(ends);
 }
 
 pub fn spawn_stored_level(
@@ -122,6 +150,8 @@ pub fn spawn_stored_level(
 	}
 }
 
+// Systems
+
 fn setup(
 	mut commands: Commands,
 	mut meshes: ResMut<Assets<Mesh>>,
@@ -154,20 +184,60 @@ fn setup(
 
 fn keyboard_input_system(
 	keyboard_input: Res<Input<KeyCode>>,
-	mut drag_query: Query<(&mut Transform, &Selection), With<Draggable>>,
+	mut drag_query: Query<(&mut Transform, &Selection, Option<&End>), With<Draggable>>,
+	mut drag_end_event: EventWriter<DragEndEvent>,
 ) {
-	let drag = 8.
-		* Vec3 {
+	let drag = if keyboard_input.pressed(KeyCode::LShift) || keyboard_input.pressed(KeyCode::RShift)
+	{
+		Vec3 {
 			x: (keyboard_input.pressed(KeyCode::Right) as i8
 				- keyboard_input.pressed(KeyCode::Left) as i8) as _,
 			y: (keyboard_input.pressed(KeyCode::Up) as i8
 				- keyboard_input.pressed(KeyCode::Down) as i8) as _,
 			z: 0.,
-		};
+		}
+	} else {
+		Vec3 {
+			x: (keyboard_input.just_pressed(KeyCode::Right) as i8
+				- keyboard_input.just_pressed(KeyCode::Left) as i8) as _,
+			y: (keyboard_input.just_pressed(KeyCode::Up) as i8
+				- keyboard_input.just_pressed(KeyCode::Down) as i8) as _,
+			z: 0.,
+		}
+	} * 8.;
 	if drag != Vec3::ZERO {
-		for (mut transform, selection) in drag_query.iter_mut() {
+		for (mut transform, selection, end) in drag_query.iter_mut() {
 			if selection.selected() {
 				transform.translation += drag;
+				if let Some(End(entity)) = end {
+					drag_end_event.send(DragEndEvent(*entity));
+				}
+			}
+		}
+	}
+}
+
+fn follow_ends_system(
+	mut meshes: ResMut<Assets<Mesh>>,
+	mut platform_query: Query<(&mut Transform, &mut Mesh2dHandle, &Platform)>,
+	end_query: Query<&Transform, Without<Platform>>,
+	mut drag_end_event: EventReader<DragEndEvent>,
+) {
+	for DragEndEvent(entity) in drag_end_event.iter() {
+		if let Ok((mut transform, mut mesh, Platform(end1, end2))) = platform_query.get_mut(*entity)
+		{
+			if let (Ok(end1), Ok(end2)) = (end_query.get(*end1), end_query.get(*end2)) {
+				transform.translation.x = (end1.translation.x + end2.translation.x) / 2.;
+				transform.translation.y = (end1.translation.y + end2.translation.y) / 2.;
+				*mesh = meshes
+					.add(Mesh::from(Quad {
+						size: Vec2 {
+							x: (end2.translation.x - end1.translation.x).abs(),
+							y: (end2.translation.y - end1.translation.y).abs(),
+						},
+						flip: false,
+					}))
+					.into();
 			}
 		}
 	}