use bevy::prelude::{Bundle, Color, Component, Name, Quat, Transform, Vec2}; use bevy_prototype_lyon::{ entity::ShapeBundle, prelude::{DrawMode, FillMode, GeometryBuilder, Path, PathBuilder, ShapePath, StrokeMode}, shapes::{self, Line}, }; use bevy_tweening::Lens; use crate::turtle::Angle; pub(crate) struct LineAnimationLens { start: Vec2, end: Vec2, } impl LineAnimationLens { pub(crate) fn new(start: Vec2, end: Vec2) -> Self { Self { start, end } } } impl Lens<Path> for LineAnimationLens { fn lerp(&mut self, target: &mut Path, ratio: f32) { let line = shapes::Line(self.start, self.start + ((self.end - self.start) * ratio)); *target = ShapePath::build_as(&line); } } #[derive(Bundle)] pub(crate) struct TurtleDrawLine { #[bundle] line: ShapeBundle, name: Name, marker: LineMarker, } #[derive(Component, Default)] struct LineMarker; impl TurtleDrawLine { pub(crate) fn new(start: Vec2, _end: Vec2, index: u64) -> Self { Self { line: GeometryBuilder::build_as( &Line(start, start), DrawMode::Outlined { fill_mode: FillMode::color(Color::MIDNIGHT_BLUE), outline_mode: StrokeMode::new(Color::BLACK, 1.0), }, Transform::identity(), ), name: Name::new(format!("Line {}", index)), marker: LineMarker, } } } pub(crate) struct CircleAnimationLens { pub start_pos: Vec2, pub center: Vec2, pub radii: Vec2, pub start: Angle, pub end: Angle, } impl Lens<Path> for CircleAnimationLens { fn lerp(&mut self, target: &mut Path, ratio: f32) { let mut path_builder = PathBuilder::new(); path_builder.move_to(self.start_pos); // The center point of the radius, then the radii in x and y direction, then the angle that will be drawn, then the x_rotation ? path_builder.arc( self.center, self.radii, (self.start.0 + ((self.end.0 - self.start.0) * ratio)).to_radians(), 0., ); let line = path_builder.build(); *target = ShapePath::build_as(&line); } } pub(crate) struct CircleMovementLens { pub center: Vec2, pub start: Transform, pub end: Angle, } impl Lens<Transform> for CircleMovementLens { fn lerp(&mut self, target: &mut Transform, ratio: f32) { let angle = self.end.0 * ratio; let mut rotated = self.start; rotated.rotate_around( self.center.extend(0.), Quat::from_rotation_z(angle.to_radians()), ); *target = rotated; } } #[derive(Bundle)] pub(crate) struct TurtleDrawCircle { #[bundle] line: ShapeBundle, name: Name, marker: CircleMarker, } #[derive(Component, Default)] struct CircleMarker; impl TurtleDrawCircle { pub(crate) fn new( center: Vec2, radii: Vec2, angle: Angle, index: u64, start: Vec2, end: Vec2, ) -> Self { let mut path_builder = PathBuilder::new(); path_builder.move_to(start); // The center point of the radius, then the radii in x and y direction, then the angle that will be drawn, then the x_rotation ? path_builder.arc(center, radii, angle.0.to_radians(), 0.); /* println!("The radiuses: {}", radii); path_builder.move_to(Vec2::ZERO); path_builder.line_to(center); path_builder.line_to(Vec2::new(radii.x, 0.) + center); path_builder.move_to(center); path_builder.line_to(Vec2::new(0., radii.y) + center); path_builder.move_to(center); path_builder.line_to( center + Vec2::new(radii.x.abs(), 0.).rotate(Vec2::from_angle(angle.0.to_radians())), ); path_builder.move_to(center); */ let line = path_builder.build(); println!("Draw Circle: {} {} {:?}", center, radii, angle); Self { line: GeometryBuilder::build_as( &line, DrawMode::Outlined { fill_mode: FillMode::color(Color::rgba(0., 0., 0., 0.)), outline_mode: StrokeMode::new(Color::BLACK, 1.0), }, Transform::identity(), ), name: Name::new(format!("Circle {}", index)), marker: CircleMarker, } } }