refactor and cleanup
This commit is contained in:
parent
f9a4c1d81a
commit
5f4e47f540
53
src/animation_step.rs
Normal file
53
src/animation_step.rs
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
use bevy::prelude::{Commands, Query, Transform, With};
|
||||||
|
use bevy_tweening::Animator;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
turtle::{TurtleCommands, TurtleGraphElement, TurtleShape},
|
||||||
|
turtle_movement::TurtleStep,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub(crate) fn run_animation_step(
|
||||||
|
commands: &mut Commands,
|
||||||
|
tcmd: &mut TurtleCommands,
|
||||||
|
turtle: &mut Query<&mut Animator<Transform>, With<TurtleShape>>,
|
||||||
|
) {
|
||||||
|
loop {
|
||||||
|
match tcmd.get_next() {
|
||||||
|
Some(TurtleStep {
|
||||||
|
turtle_animation: Some(turtle_animation),
|
||||||
|
line_segment: Some(graph_element_to_draw),
|
||||||
|
line_animation: Some(line_animation),
|
||||||
|
}) => {
|
||||||
|
let mut turtle = turtle.single_mut();
|
||||||
|
turtle.set_tweenable(turtle_animation);
|
||||||
|
match graph_element_to_draw {
|
||||||
|
TurtleGraphElement::TurtleLine(line) => {
|
||||||
|
commands.spawn_bundle(line).insert(line_animation);
|
||||||
|
}
|
||||||
|
TurtleGraphElement::Noop => (),
|
||||||
|
TurtleGraphElement::TurtleCircle(circle) => {
|
||||||
|
commands.spawn_bundle(circle).insert(line_animation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// In case a rotation is performed the line drawing can be skipped
|
||||||
|
Some(TurtleStep {
|
||||||
|
turtle_animation: Some(turtle_animation),
|
||||||
|
line_segment: Some(_),
|
||||||
|
line_animation: None,
|
||||||
|
}) => {
|
||||||
|
let mut turtle = turtle.single_mut();
|
||||||
|
turtle.set_tweenable(turtle_animation);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Some(_) => {
|
||||||
|
println!("without animation");
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
println!("nothing to draw");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,3 @@
|
|||||||
use std::f32::consts::PI;
|
|
||||||
|
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use bevy_prototype_lyon::prelude::*;
|
use bevy_prototype_lyon::prelude::*;
|
||||||
|
|
||||||
|
@ -4,6 +4,8 @@ use std::{
|
|||||||
ops::{Add, Div, Mul, Neg, Rem, Sub},
|
ops::{Add, Div, Mul, Neg, Rem, Sub},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use crate::turtle::Precision;
|
||||||
|
|
||||||
#[derive(Inspectable, Copy, Clone, Debug, PartialEq, Eq)]
|
#[derive(Inspectable, Copy, Clone, Debug, PartialEq, Eq)]
|
||||||
pub enum AngleUnit<T: Default> {
|
pub enum AngleUnit<T: Default> {
|
||||||
Degrees(T),
|
Degrees(T),
|
||||||
@ -43,7 +45,7 @@ impl<T: Default + Clone + Mul<T, Output = T>> Mul<T> for Angle<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Angle<f32> {
|
impl Angle<Precision> {
|
||||||
pub fn limit_smaller_than_full_circle(self) -> Self {
|
pub fn limit_smaller_than_full_circle(self) -> Self {
|
||||||
match self.value {
|
match self.value {
|
||||||
AngleUnit::Degrees(v) => Self {
|
AngleUnit::Degrees(v) => Self {
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
use bevy_inspector_egui::Inspectable;
|
use bevy_inspector_egui::Inspectable;
|
||||||
|
|
||||||
|
use crate::turtle::Precision;
|
||||||
|
|
||||||
#[derive(Inspectable, Default, Copy, Clone, Debug)]
|
#[derive(Inspectable, Default, Copy, Clone, Debug)]
|
||||||
pub struct Length(pub f32);
|
pub struct Length(pub Precision);
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
|
mod animation_step;
|
||||||
mod datatypes;
|
mod datatypes;
|
||||||
mod debug;
|
mod debug;
|
||||||
mod paths;
|
mod paths;
|
||||||
mod primitives;
|
mod primitives;
|
||||||
mod turtle;
|
mod turtle;
|
||||||
mod turtle_movement;
|
mod turtle_movement;
|
||||||
mod turtle_shapes;
|
|
||||||
use bevy::{prelude::*, window::close_on_esc};
|
use bevy::{prelude::*, window::close_on_esc};
|
||||||
|
|
||||||
use bevy_prototype_lyon::prelude::*;
|
use bevy_prototype_lyon::prelude::*;
|
||||||
|
@ -2,3 +2,4 @@ pub mod animation;
|
|||||||
pub mod bundles;
|
pub mod bundles;
|
||||||
pub mod components;
|
pub mod components;
|
||||||
pub mod turtle_primitives;
|
pub mod turtle_primitives;
|
||||||
|
pub mod turtle_shapes;
|
||||||
|
@ -5,7 +5,7 @@ use bevy_prototype_lyon::{
|
|||||||
};
|
};
|
||||||
use bevy_tweening::Lens;
|
use bevy_tweening::Lens;
|
||||||
|
|
||||||
use crate::datatypes::angle::Angle;
|
use crate::{datatypes::angle::Angle, turtle::Precision};
|
||||||
|
|
||||||
pub(crate) struct LineAnimationLens {
|
pub(crate) struct LineAnimationLens {
|
||||||
start: Vec2,
|
start: Vec2,
|
||||||
@ -29,8 +29,8 @@ pub(crate) struct CircleAnimationLens {
|
|||||||
pub start_pos: Vec2,
|
pub start_pos: Vec2,
|
||||||
pub center: Vec2,
|
pub center: Vec2,
|
||||||
pub radii: Vec2,
|
pub radii: Vec2,
|
||||||
pub start: Angle<f32>,
|
pub start: Angle<Precision>,
|
||||||
pub end: Angle<f32>,
|
pub end: Angle<Precision>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Lens<Path> for CircleAnimationLens {
|
impl Lens<Path> for CircleAnimationLens {
|
||||||
@ -54,7 +54,7 @@ impl Lens<Path> for CircleAnimationLens {
|
|||||||
pub(crate) struct CircleMovementLens {
|
pub(crate) struct CircleMovementLens {
|
||||||
pub center: Vec2,
|
pub center: Vec2,
|
||||||
pub start: Transform,
|
pub start: Transform,
|
||||||
pub end: Angle<f32>,
|
pub end: Angle<Precision>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Lens<Transform> for CircleMovementLens {
|
impl Lens<Transform> for CircleMovementLens {
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
use bevy::prelude::{Bundle, Color, Component, Name, Transform, Vec2};
|
use bevy::prelude::{Bundle, Color, Component, Name, Transform, Vec2};
|
||||||
|
use bevy_inspector_egui::Inspectable;
|
||||||
use bevy_prototype_lyon::{
|
use bevy_prototype_lyon::{
|
||||||
entity::ShapeBundle,
|
entity::ShapeBundle,
|
||||||
prelude::{DrawMode, FillMode, GeometryBuilder, PathBuilder, StrokeMode},
|
prelude::{DrawMode, FillMode, GeometryBuilder, PathBuilder, StrokeMode},
|
||||||
@ -7,18 +8,21 @@ use bevy_prototype_lyon::{
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
datatypes::angle::Angle,
|
datatypes::angle::Angle,
|
||||||
turtle::{Colors, TurtleCommand, TurtleCommands},
|
turtle::{Colors, Precision, TurtleCommand, TurtleCommands},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Bundle)]
|
use super::turtle_shapes;
|
||||||
pub(crate) struct TurtleDrawLine {
|
|
||||||
|
#[derive(Bundle, Inspectable, Default)]
|
||||||
|
pub struct TurtleDrawLine {
|
||||||
#[bundle]
|
#[bundle]
|
||||||
|
#[inspectable(ignore)]
|
||||||
line: ShapeBundle,
|
line: ShapeBundle,
|
||||||
name: Name,
|
name: Name,
|
||||||
marker: LineMarker,
|
marker: LineMarker,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Component, Default)]
|
#[derive(Component, Default, Inspectable)]
|
||||||
struct LineMarker;
|
struct LineMarker;
|
||||||
|
|
||||||
impl TurtleDrawLine {
|
impl TurtleDrawLine {
|
||||||
@ -38,23 +42,24 @@ impl TurtleDrawLine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Bundle)]
|
#[derive(Bundle, Inspectable, Default)]
|
||||||
|
|
||||||
pub(crate) struct TurtleDrawCircle {
|
pub struct TurtleDrawCircle {
|
||||||
#[bundle]
|
#[bundle]
|
||||||
|
#[inspectable(ignore)]
|
||||||
line: ShapeBundle,
|
line: ShapeBundle,
|
||||||
name: Name,
|
name: Name,
|
||||||
marker: CircleMarker,
|
marker: CircleMarker,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Component, Default)]
|
#[derive(Component, Default, Inspectable)]
|
||||||
struct CircleMarker;
|
struct CircleMarker;
|
||||||
|
|
||||||
impl TurtleDrawCircle {
|
impl TurtleDrawCircle {
|
||||||
pub(crate) fn new(
|
pub(crate) fn new(
|
||||||
center: Vec2,
|
center: Vec2,
|
||||||
radii: Vec2,
|
radii: Vec2,
|
||||||
angle: Angle<f32>,
|
angle: Angle<Precision>,
|
||||||
index: u64,
|
index: u64,
|
||||||
start: Vec2,
|
start: Vec2,
|
||||||
end: Vec2,
|
end: Vec2,
|
||||||
@ -89,6 +94,8 @@ pub struct Turtle {
|
|||||||
colors: Colors,
|
colors: Colors,
|
||||||
commands: TurtleCommands,
|
commands: TurtleCommands,
|
||||||
name: Name,
|
name: Name,
|
||||||
|
#[bundle]
|
||||||
|
shape: ShapeBundle,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Turtle {
|
impl Default for Turtle {
|
||||||
@ -97,6 +104,14 @@ impl Default for Turtle {
|
|||||||
colors: Colors::default(),
|
colors: Colors::default(),
|
||||||
commands: TurtleCommands::new(vec![]),
|
commands: TurtleCommands::new(vec![]),
|
||||||
name: Name::new("Turtle"),
|
name: Name::new("Turtle"),
|
||||||
|
shape: GeometryBuilder::build_as(
|
||||||
|
&turtle_shapes::turtle(),
|
||||||
|
DrawMode::Outlined {
|
||||||
|
fill_mode: FillMode::color(Color::MIDNIGHT_BLUE),
|
||||||
|
outline_mode: StrokeMode::new(Color::BLACK, 1.0),
|
||||||
|
},
|
||||||
|
Transform::identity(),
|
||||||
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,31 +3,33 @@ use std::f32::consts::PI;
|
|||||||
use bevy::prelude::Vec2;
|
use bevy::prelude::Vec2;
|
||||||
use bevy_prototype_lyon::prelude::{Path, PathBuilder};
|
use bevy_prototype_lyon::prelude::{Path, PathBuilder};
|
||||||
|
|
||||||
|
use crate::turtle::Precision;
|
||||||
|
|
||||||
pub fn turtle() -> Path {
|
pub fn turtle() -> Path {
|
||||||
let polygon = &[
|
let polygon: &[[Precision; 2]; 23] = &[
|
||||||
[-2.5f32, 14.0f32],
|
[-2.5, 14.0],
|
||||||
[-1.25f32, 10.0f32],
|
[-1.25, 10.0],
|
||||||
[-4.0f32, 7.0f32],
|
[-4.0, 7.0],
|
||||||
[-7.0f32, 9.0f32],
|
[-7.0, 9.0],
|
||||||
[-9.0f32, 8.0f32],
|
[-9.0, 8.0],
|
||||||
[-6.0f32, 5.0f32],
|
[-6.0, 5.0],
|
||||||
[-7.0f32, 1.0f32],
|
[-7.0, 1.0],
|
||||||
[-5.0f32, -3.0f32],
|
[-5.0, -3.0],
|
||||||
[-8.0f32, -6.0f32],
|
[-8.0, -6.0],
|
||||||
[-6.0f32, -8.0f32],
|
[-6.0, -8.0],
|
||||||
[-4.0f32, -5.0f32],
|
[-4.0, -5.0],
|
||||||
[0.0f32, -7.0f32],
|
[0.0, -7.0],
|
||||||
[4.0f32, -5.0f32],
|
[4.0, -5.0],
|
||||||
[6.0f32, -8.0f32],
|
[6.0, -8.0],
|
||||||
[8.0f32, -6.0f32],
|
[8.0, -6.0],
|
||||||
[5.0f32, -3.0f32],
|
[5.0, -3.0],
|
||||||
[7.0f32, 1.0f32],
|
[7.0, 1.0],
|
||||||
[6.0f32, 5.0f32],
|
[6.0, 5.0],
|
||||||
[9.0f32, 8.0f32],
|
[9.0, 8.0],
|
||||||
[7.0f32, 9.0f32],
|
[7.0, 9.0],
|
||||||
[4.0f32, 7.0f32],
|
[4.0, 7.0],
|
||||||
[1.25f32, 10.0f32],
|
[1.25, 10.0],
|
||||||
[2.5f32, 14.0f32],
|
[2.5, 14.0],
|
||||||
];
|
];
|
||||||
let mut turtle_path = PathBuilder::new();
|
let mut turtle_path = PathBuilder::new();
|
||||||
turtle_path.line_to(Vec2::new(1.0, 1.0));
|
turtle_path.line_to(Vec2::new(1.0, 1.0));
|
148
src/turtle.rs
148
src/turtle.rs
@ -11,12 +11,10 @@ use bevy_tweening::{
|
|||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
use crate::paths::{circle_star::circle_star, geometry_task::geometry_task};
|
use crate::paths::{circle_star::circle_star, geometry_task::geometry_task};
|
||||||
use crate::{
|
use crate::{
|
||||||
|
animation_step::run_animation_step,
|
||||||
datatypes::{angle::Angle, length::Length},
|
datatypes::{angle::Angle, length::Length},
|
||||||
primitives::{
|
primitives::bundles::{Turtle, TurtleDrawCircle, TurtleDrawLine},
|
||||||
animation::{CircleAnimationLens, LineAnimationLens},
|
turtle_movement::TurtleStep,
|
||||||
bundles::{Turtle, TurtleDrawCircle, TurtleDrawLine},
|
|
||||||
},
|
|
||||||
turtle_shapes,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct TurtlePlugin;
|
pub struct TurtlePlugin;
|
||||||
@ -66,7 +64,7 @@ impl TurtleCommands {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl TurtleCommands {
|
impl TurtleCommands {
|
||||||
fn get_next(&mut self) -> Option<(Option<Tween<Transform>>, Option<TurtleGraphElement>)> {
|
pub(crate) fn get_next(&mut self) -> Option<TurtleStep> {
|
||||||
let index = self.state.index;
|
let index = self.state.index;
|
||||||
let next_index = index + 1;
|
let next_index = index + 1;
|
||||||
|
|
||||||
@ -86,11 +84,21 @@ impl TurtleCommands {
|
|||||||
}
|
}
|
||||||
TurtleCommand::PenUp => {
|
TurtleCommand::PenUp => {
|
||||||
self.state.drawing = false;
|
self.state.drawing = false;
|
||||||
(None, None)
|
|
||||||
|
TurtleStep {
|
||||||
|
turtle_animation: None,
|
||||||
|
line_segment: None,
|
||||||
|
line_animation: None,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
TurtleCommand::PenDown => {
|
TurtleCommand::PenDown => {
|
||||||
self.state.drawing = true;
|
self.state.drawing = true;
|
||||||
(None, None)
|
|
||||||
|
TurtleStep {
|
||||||
|
turtle_animation: None,
|
||||||
|
line_segment: None,
|
||||||
|
line_animation: None,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
TurtleCommand::Circle { radius, angle } => {
|
TurtleCommand::Circle { radius, angle } => {
|
||||||
crate::turtle_movement::turtle_circle(&mut self.state, radius.0 as f32, *angle)
|
crate::turtle_movement::turtle_circle(&mut self.state, radius.0 as f32, *angle)
|
||||||
@ -107,17 +115,8 @@ impl TurtleCommands {
|
|||||||
|
|
||||||
#[derive(Inspectable, Default)]
|
#[derive(Inspectable, Default)]
|
||||||
pub enum TurtleGraphElement {
|
pub enum TurtleGraphElement {
|
||||||
TurtleLine {
|
TurtleLine(TurtleDrawLine),
|
||||||
start: Vec2,
|
TurtleCircle(TurtleDrawCircle),
|
||||||
end: Vec2,
|
|
||||||
},
|
|
||||||
TurtleCircle {
|
|
||||||
start: Vec2,
|
|
||||||
end: Vec2,
|
|
||||||
center: Vec2,
|
|
||||||
radii: Vec2,
|
|
||||||
angle: Angle<f32>,
|
|
||||||
},
|
|
||||||
#[default]
|
#[default]
|
||||||
Noop,
|
Noop,
|
||||||
}
|
}
|
||||||
@ -159,17 +158,9 @@ fn setup(mut commands: Commands) {
|
|||||||
));
|
));
|
||||||
commands.spawn_bundle(Camera2dBundle::default());
|
commands.spawn_bundle(Camera2dBundle::default());
|
||||||
let mut turtle_bundle = Turtle::default();
|
let mut turtle_bundle = Turtle::default();
|
||||||
turtle_bundle.set_commands(geometry_task());
|
turtle_bundle.set_commands(circle_star());
|
||||||
commands
|
commands
|
||||||
.spawn_bundle(turtle_bundle)
|
.spawn_bundle(turtle_bundle)
|
||||||
.insert_bundle(GeometryBuilder::build_as(
|
|
||||||
&turtle_shapes::turtle(),
|
|
||||||
DrawMode::Outlined {
|
|
||||||
fill_mode: FillMode::color(Color::MIDNIGHT_BLUE),
|
|
||||||
outline_mode: StrokeMode::new(Color::BLACK, 1.0),
|
|
||||||
},
|
|
||||||
Transform::identity(),
|
|
||||||
))
|
|
||||||
.insert(animator)
|
.insert(animator)
|
||||||
.insert(TurtleShape);
|
.insert(TurtleShape);
|
||||||
}
|
}
|
||||||
@ -182,117 +173,26 @@ fn draw_lines(
|
|||||||
) {
|
) {
|
||||||
for ev in query_event.iter() {
|
for ev in query_event.iter() {
|
||||||
let mut tcmd = tcmd.single_mut();
|
let mut tcmd = tcmd.single_mut();
|
||||||
loop {
|
run_animation_step(&mut commands, &mut tcmd, &mut turtle)
|
||||||
match tcmd.get_next() {
|
|
||||||
Some((Some(turtle_animation), Some(graph_element_to_draw))) => {
|
|
||||||
let mut turtle = turtle.single_mut();
|
|
||||||
turtle.set_tweenable(turtle_animation);
|
|
||||||
match graph_element_to_draw {
|
|
||||||
TurtleGraphElement::TurtleLine { start, end } => {
|
|
||||||
let line_animator = Animator::new(Tween::new(
|
|
||||||
EaseFunction::QuadraticInOut,
|
|
||||||
TweeningType::Once,
|
|
||||||
Duration::from_millis(tcmd.state.speed),
|
|
||||||
LineAnimationLens::new(start, end),
|
|
||||||
));
|
|
||||||
commands
|
|
||||||
.spawn_bundle(TurtleDrawLine::new(start, end, tcmd.state.index))
|
|
||||||
.insert(line_animator);
|
|
||||||
}
|
|
||||||
TurtleGraphElement::Noop => println!("No drawing!"),
|
|
||||||
TurtleGraphElement::TurtleCircle {
|
|
||||||
center,
|
|
||||||
radii,
|
|
||||||
angle,
|
|
||||||
start,
|
|
||||||
end,
|
|
||||||
} => {
|
|
||||||
let line_animator = Animator::new(Tween::new(
|
|
||||||
EaseFunction::QuadraticInOut,
|
|
||||||
TweeningType::Once,
|
|
||||||
Duration::from_millis(tcmd.state.speed),
|
|
||||||
CircleAnimationLens {
|
|
||||||
start_pos: start,
|
|
||||||
center,
|
|
||||||
radii,
|
|
||||||
start: Angle::degrees(0.),
|
|
||||||
end: angle,
|
|
||||||
},
|
|
||||||
));
|
|
||||||
commands
|
|
||||||
.spawn_bundle(TurtleDrawCircle::new(
|
|
||||||
center,
|
|
||||||
radii,
|
|
||||||
Angle::degrees(0.),
|
|
||||||
tcmd.state.index,
|
|
||||||
start,
|
|
||||||
end,
|
|
||||||
))
|
|
||||||
.insert(line_animator);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Some((_, _)) => {
|
|
||||||
println!("without animation");
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
println!("nothing to draw");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn keypresses(
|
fn keypresses(
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
keys: Res<Input<KeyCode>>,
|
keys: Res<Input<KeyCode>>,
|
||||||
mut qry: Query<&mut Animator<Transform>, With<TurtleShape>>,
|
|
||||||
mut tcmd: Query<&mut TurtleCommands>,
|
mut tcmd: Query<&mut TurtleCommands>,
|
||||||
|
mut turtle: Query<&mut Animator<Transform>, With<TurtleShape>>,
|
||||||
) {
|
) {
|
||||||
if keys.just_pressed(KeyCode::W) {
|
if keys.just_pressed(KeyCode::W) {
|
||||||
let mut tcmd = tcmd.single_mut();
|
let mut tcmd = tcmd.single_mut();
|
||||||
tcmd.state = TurtleState {
|
tcmd.state = TurtleState {
|
||||||
start: Vec2::ZERO,
|
start: Vec2::ZERO,
|
||||||
heading: Angle::degrees(0.),
|
heading: Angle::degrees(0.),
|
||||||
speed: 2000,
|
speed: 500,
|
||||||
index: 0,
|
index: 0,
|
||||||
drawing: true,
|
drawing: true,
|
||||||
};
|
};
|
||||||
if let Some((Some(turtle_animation), Some(graph_element_to_draw))) = tcmd.get_next() {
|
|
||||||
let mut shap = qry.single_mut();
|
run_animation_step(&mut commands, &mut tcmd, &mut turtle);
|
||||||
shap.set_tweenable(turtle_animation);
|
|
||||||
match graph_element_to_draw {
|
|
||||||
TurtleGraphElement::TurtleLine { start, end } => {
|
|
||||||
let line_animator = Animator::new(Tween::new(
|
|
||||||
EaseFunction::QuadraticInOut,
|
|
||||||
TweeningType::Once,
|
|
||||||
Duration::from_millis(tcmd.state.speed),
|
|
||||||
LineAnimationLens::new(start, end),
|
|
||||||
));
|
|
||||||
commands
|
|
||||||
.spawn_bundle(TurtleDrawLine::new(start, end, tcmd.state.index))
|
|
||||||
.insert(line_animator);
|
|
||||||
}
|
|
||||||
TurtleGraphElement::Noop => (),
|
|
||||||
TurtleGraphElement::TurtleCircle {
|
|
||||||
center,
|
|
||||||
radii,
|
|
||||||
angle,
|
|
||||||
start,
|
|
||||||
end,
|
|
||||||
} => {
|
|
||||||
commands.spawn_bundle(TurtleDrawCircle::new(
|
|
||||||
center,
|
|
||||||
radii,
|
|
||||||
angle,
|
|
||||||
tcmd.state.index,
|
|
||||||
start,
|
|
||||||
end,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,78 +1,89 @@
|
|||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use bevy::prelude::{Quat, Transform, Vec2, Vec3};
|
use bevy::prelude::{Quat, Transform, Vec2, Vec3};
|
||||||
|
use bevy_prototype_lyon::prelude::Path;
|
||||||
use bevy_tweening::{
|
use bevy_tweening::{
|
||||||
lens::{TransformPositionLens, TransformRotateZLens},
|
lens::{TransformPositionLens, TransformRotateZLens},
|
||||||
EaseFunction, Tween, TweeningType,
|
Animator, EaseFunction, Tween, TweeningType,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
datatypes::angle::Angle,
|
datatypes::angle::Angle,
|
||||||
primitives::animation::CircleMovementLens,
|
primitives::{
|
||||||
turtle::{TurtleGraphElement, TurtleState},
|
animation::{CircleAnimationLens, CircleMovementLens, LineAnimationLens},
|
||||||
|
bundles::{TurtleDrawCircle, TurtleDrawLine},
|
||||||
|
},
|
||||||
|
turtle::{Precision, TurtleGraphElement, TurtleState},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn turtle_turn(
|
pub struct TurtleStep {
|
||||||
state: &mut TurtleState,
|
pub turtle_animation: Option<Tween<Transform>>,
|
||||||
angle_to_turn: Angle<f32>,
|
pub line_segment: Option<TurtleGraphElement>,
|
||||||
) -> (Option<Tween<Transform>>, Option<TurtleGraphElement>) {
|
pub line_animation: Option<Animator<Path>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn turtle_turn(state: &mut TurtleState, angle_to_turn: Angle<Precision>) -> TurtleStep {
|
||||||
let start = state.heading;
|
let start = state.heading;
|
||||||
let end = state.heading + angle_to_turn;
|
let end = state.heading + angle_to_turn;
|
||||||
let animation = Tween::new(
|
let animation = Tween::new(
|
||||||
// Use a quadratic easing on both endpoints
|
|
||||||
EaseFunction::QuadraticInOut,
|
EaseFunction::QuadraticInOut,
|
||||||
TweeningType::Once,
|
TweeningType::Once,
|
||||||
// Animation time
|
|
||||||
Duration::from_millis(state.speed),
|
Duration::from_millis(state.speed),
|
||||||
// Rotate the turtle
|
|
||||||
TransformRotateZLens {
|
TransformRotateZLens {
|
||||||
start: start.to_radians().value(),
|
start: start.to_radians().value(),
|
||||||
end: end.to_radians().value(),
|
end: end.to_radians().value(),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.with_completed_event(state.index as u64);
|
.with_completed_event(state.index as u64);
|
||||||
// Dont move and draw
|
// Don't draw as the position does not change
|
||||||
let line = TurtleGraphElement::Noop;
|
let line = TurtleGraphElement::Noop;
|
||||||
// Update the state
|
// Update the state
|
||||||
state.heading = end.limit_smaller_than_full_circle();
|
state.heading = end.limit_smaller_than_full_circle();
|
||||||
(Some(animation), Some(line))
|
TurtleStep {
|
||||||
|
turtle_animation: Some(animation),
|
||||||
|
line_segment: Some(line),
|
||||||
|
line_animation: None,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn turtle_move(
|
pub fn turtle_move(state: &mut TurtleState, length: Precision) -> TurtleStep {
|
||||||
state: &mut TurtleState,
|
|
||||||
length: f32,
|
|
||||||
) -> (Option<Tween<Transform>>, Option<TurtleGraphElement>) {
|
|
||||||
let start = state.start;
|
let start = state.start;
|
||||||
let end = state.start + (Vec2::from_angle(state.heading.to_radians().value()) * length);
|
let end = state.start + (Vec2::from_angle(state.heading.to_radians().value()) * length);
|
||||||
let turtle_movement_animation = Tween::new(
|
let turtle_movement_animation = Tween::new(
|
||||||
// accelerate and decelerate
|
|
||||||
EaseFunction::QuadraticInOut,
|
EaseFunction::QuadraticInOut,
|
||||||
TweeningType::Once,
|
TweeningType::Once,
|
||||||
// later to be controlled by speed
|
|
||||||
Duration::from_millis(state.speed),
|
Duration::from_millis(state.speed),
|
||||||
// set the start and end of the animation
|
|
||||||
TransformPositionLens {
|
TransformPositionLens {
|
||||||
start: start.extend(0.),
|
start: start.extend(0.),
|
||||||
end: end.extend(0.),
|
end: end.extend(0.),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.with_completed_event(state.index as u64);
|
.with_completed_event(state.index as u64);
|
||||||
// The line for animating and drawing
|
|
||||||
let line = if state.drawing {
|
let line = if state.drawing {
|
||||||
TurtleGraphElement::TurtleLine { start, end }
|
TurtleGraphElement::TurtleLine(TurtleDrawLine::new(start, end, state.index))
|
||||||
} else {
|
} else {
|
||||||
TurtleGraphElement::Noop
|
TurtleGraphElement::Noop
|
||||||
};
|
};
|
||||||
|
let line_animator = Animator::new(Tween::new(
|
||||||
|
EaseFunction::QuadraticInOut,
|
||||||
|
TweeningType::Once,
|
||||||
|
Duration::from_millis(state.speed),
|
||||||
|
LineAnimationLens::new(start, end),
|
||||||
|
));
|
||||||
state.start = end;
|
state.start = end;
|
||||||
(Some(turtle_movement_animation), Some(line))
|
TurtleStep {
|
||||||
|
turtle_animation: Some(turtle_movement_animation),
|
||||||
|
line_segment: Some(line),
|
||||||
|
line_animation: Some(line_animator),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn turtle_circle(
|
pub fn turtle_circle(
|
||||||
state: &mut TurtleState,
|
state: &mut TurtleState,
|
||||||
radius: f32,
|
radius: Precision,
|
||||||
angle: Angle<f32>,
|
angle: Angle<Precision>,
|
||||||
) -> (Option<Tween<Transform>>, Option<TurtleGraphElement>) {
|
) -> TurtleStep {
|
||||||
let radius_tuple = Vec2::ONE * radius.abs();
|
let radii = Vec2::ONE * radius.abs();
|
||||||
let left_right = Angle::degrees(if radius >= 0. { 90. } else { -90. });
|
let left_right = Angle::degrees(if radius >= 0. { 90. } else { -90. });
|
||||||
let center = state.start
|
let center = state.start
|
||||||
+ (Vec2::new(radius.abs(), 0.).rotate(Vec2::from_angle(
|
+ (Vec2::new(radius.abs(), 0.).rotate(Vec2::from_angle(
|
||||||
@ -80,12 +91,9 @@ pub fn turtle_circle(
|
|||||||
)));
|
)));
|
||||||
|
|
||||||
let turtle_movement_animation = Tween::new(
|
let turtle_movement_animation = Tween::new(
|
||||||
// accelerate and decelerate
|
|
||||||
EaseFunction::QuadraticInOut,
|
EaseFunction::QuadraticInOut,
|
||||||
TweeningType::Once,
|
TweeningType::Once,
|
||||||
// later to be controlled by speed
|
|
||||||
Duration::from_millis(state.speed),
|
Duration::from_millis(state.speed),
|
||||||
// set the start and end of the animation
|
|
||||||
CircleMovementLens {
|
CircleMovementLens {
|
||||||
start: Transform {
|
start: Transform {
|
||||||
translation: state.start.extend(0.),
|
translation: state.start.extend(0.),
|
||||||
@ -97,23 +105,39 @@ pub fn turtle_circle(
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
.with_completed_event(state.index as u64);
|
.with_completed_event(state.index as u64);
|
||||||
// The line for animating and drawing
|
|
||||||
let line = if state.drawing {
|
|
||||||
TurtleGraphElement::TurtleCircle {
|
|
||||||
center,
|
|
||||||
radii: radius_tuple,
|
|
||||||
angle,
|
|
||||||
start: state.start,
|
|
||||||
end: state.start,
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
TurtleGraphElement::Noop
|
|
||||||
};
|
|
||||||
let end_pos = center
|
let end_pos = center
|
||||||
+ Vec2::new(radius.abs(), 0.).rotate(Vec2::from_angle(
|
+ Vec2::new(radius.abs(), 0.).rotate(Vec2::from_angle(
|
||||||
(state.heading + angle - left_right).to_radians().value(),
|
(state.heading + angle - left_right).to_radians().value(),
|
||||||
));
|
));
|
||||||
|
let line = if state.drawing {
|
||||||
|
TurtleGraphElement::TurtleCircle(TurtleDrawCircle::new(
|
||||||
|
center,
|
||||||
|
radii,
|
||||||
|
Angle::degrees(0.),
|
||||||
|
state.index,
|
||||||
|
state.start,
|
||||||
|
end_pos,
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
TurtleGraphElement::Noop
|
||||||
|
};
|
||||||
|
let line_animator = Animator::new(Tween::new(
|
||||||
|
EaseFunction::QuadraticInOut,
|
||||||
|
TweeningType::Once,
|
||||||
|
Duration::from_millis(state.speed),
|
||||||
|
CircleAnimationLens {
|
||||||
|
start_pos: state.start,
|
||||||
|
center,
|
||||||
|
radii,
|
||||||
|
start: Angle::degrees(0.),
|
||||||
|
end: angle,
|
||||||
|
},
|
||||||
|
));
|
||||||
state.start = end_pos;
|
state.start = end_pos;
|
||||||
state.heading = state.heading + angle;
|
state.heading = state.heading + angle;
|
||||||
(Some(turtle_movement_animation), Some(line))
|
TurtleStep {
|
||||||
|
turtle_animation: Some(turtle_movement_animation),
|
||||||
|
line_segment: Some(line),
|
||||||
|
line_animation: Some(line_animator),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user