first circle try

This commit is contained in:
Franz Dietrich 2022-08-19 19:08:02 +02:00
parent 62ca3eb79d
commit 7a543685d3
6 changed files with 360 additions and 162 deletions

91
Cargo.lock generated
View File

@ -110,9 +110,9 @@ dependencies = [
[[package]] [[package]]
name = "anyhow" name = "anyhow"
version = "1.0.60" version = "1.0.62"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c794e162a5eff65c72ef524dfe393eb923c354e350bb78b9c7383df13f3bc142" checksum = "1485d4d2cc45e7b201ee3767015c96faa5904387c9d87c6efdd0fb511f12d305"
[[package]] [[package]]
name = "approx" name = "approx"
@ -165,9 +165,9 @@ dependencies = [
[[package]] [[package]]
name = "async-channel" name = "async-channel"
version = "1.6.1" version = "1.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2114d64672151c0c5eaa5e131ec84a74f06e1e559830dabba01ca30605d66319" checksum = "e14485364214912d3b19cc3435dde4df66065127f05fa0d75c712f36f12c2f28"
dependencies = [ dependencies = [
"concurrent-queue", "concurrent-queue",
"event-listener", "event-listener",
@ -422,9 +422,9 @@ dependencies = [
[[package]] [[package]]
name = "bevy_egui" name = "bevy_egui"
version = "0.15.0" version = "0.15.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4ab46f07c3f360507fae9bc3b9c000c583e0d67661f0dd6dd5a24a709775b1e" checksum = "acbf44ff770566dca66b805a6829df783f64700bd01d35aec1034dff31b531a4"
dependencies = [ dependencies = [
"arboard", "arboard",
"bevy", "bevy",
@ -875,7 +875,7 @@ checksum = "8bda6dada53e546845887ae7357eec57b8d547ef71627b716b33839b4a98b687"
dependencies = [ dependencies = [
"ahash", "ahash",
"getrandom", "getrandom",
"hashbrown 0.12.3", "hashbrown",
"instant", "instant",
"tracing", "tracing",
"uuid", "uuid",
@ -964,24 +964,24 @@ checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a"
[[package]] [[package]]
name = "bumpalo" name = "bumpalo"
version = "3.10.0" version = "3.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37ccbd214614c6783386c1af30caf03192f17891059cecc394b4fb119e363de3" checksum = "c1ad822118d20d2c234f427000d5acc36eabe1e29a348c89b63dd60b13f28e5d"
[[package]] [[package]]
name = "bytemuck" name = "bytemuck"
version = "1.11.0" version = "1.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a5377c8865e74a160d21f29c2d40669f53286db6eab59b88540cbb12ffc8b835" checksum = "2f5715e491b5a1598fc2bef5a606847b5dc1d48ea625bd3c02c00de8285591da"
dependencies = [ dependencies = [
"bytemuck_derive", "bytemuck_derive",
] ]
[[package]] [[package]]
name = "bytemuck_derive" name = "bytemuck_derive"
version = "1.1.1" version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cfd2f4180c5721da6335cc9e9061cce522b87a35e51cc57636d28d22a9863c80" checksum = "1b9e1f5fa78f69496407a27ae9ed989e3c3b072310286f5ef385525e4cbc24a9"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -1119,9 +1119,9 @@ checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b"
[[package]] [[package]]
name = "combine" name = "combine"
version = "4.6.4" version = "4.6.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2a604e93b79d1808327a6fca85a6f2d69de66461e7620f5a4cbf5fb4d1d7c948" checksum = "35ed6e9d84f0b51a7f52daf1c7d71dd136fd7a3f41a8462b8cdb8c78d920fad4"
dependencies = [ dependencies = [
"bytes", "bytes",
"memchr", "memchr",
@ -1592,15 +1592,15 @@ dependencies = [
[[package]] [[package]]
name = "futures-core" name = "futures-core"
version = "0.3.21" version = "0.3.23"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3" checksum = "d2acedae88d38235936c3922476b10fced7b2b68136f5e3c03c2d5be348a1115"
[[package]] [[package]]
name = "futures-io" name = "futures-io"
version = "0.3.21" version = "0.3.23"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b" checksum = "93a66fc6d035a26a3ae255a6d2bca35eda63ae4c5512bef54449113f7a1228e5"
[[package]] [[package]]
name = "futures-lite" name = "futures-lite"
@ -1778,13 +1778,13 @@ dependencies = [
[[package]] [[package]]
name = "gpu-descriptor" name = "gpu-descriptor"
version = "0.2.2" version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a538f217be4d405ff4719a283ca68323cc2384003eca5baaa87501e821c81dda" checksum = "0b0c02e1ba0bdb14e965058ca34e09c020f8e507a760df1121728e0aef68d57a"
dependencies = [ dependencies = [
"bitflags", "bitflags",
"gpu-descriptor-types", "gpu-descriptor-types",
"hashbrown 0.11.2", "hashbrown",
] ]
[[package]] [[package]]
@ -1826,15 +1826,6 @@ dependencies = [
"syn", "syn",
] ]
[[package]]
name = "hashbrown"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
dependencies = [
"ahash",
]
[[package]] [[package]]
name = "hashbrown" name = "hashbrown"
version = "0.12.3" version = "0.12.3"
@ -1931,7 +1922,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e" checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e"
dependencies = [ dependencies = [
"autocfg", "autocfg",
"hashbrown 0.12.3", "hashbrown",
] ]
[[package]] [[package]]
@ -1996,9 +1987,9 @@ dependencies = [
[[package]] [[package]]
name = "itoa" name = "itoa"
version = "1.0.2" version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "112c678d4050afce233f4f2852bb2eb519230b3cf12f33585275537d7e41578d" checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754"
[[package]] [[package]]
name = "jni" name = "jni"
@ -2100,9 +2091,9 @@ dependencies = [
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.126" version = "0.2.132"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" checksum = "8371e4e5341c3a96db127eb2465ac681ced4c433e01dd0e938adbef26ba93ba5"
[[package]] [[package]]
name = "libloading" name = "libloading"
@ -2632,9 +2623,9 @@ dependencies = [
[[package]] [[package]]
name = "once_cell" name = "once_cell"
version = "1.13.0" version = "1.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1" checksum = "074864da206b4973b84eb91683020dbefd6a8c3f0f38e054d93954e891935e4e"
[[package]] [[package]]
name = "owned_ttf_parser" name = "owned_ttf_parser"
@ -2774,9 +2765,9 @@ checksum = "a8815d101cfb4cb491154896bdab292a395a7ac9ab185a9941a2f5be0135900d"
[[package]] [[package]]
name = "proc-macro-crate" name = "proc-macro-crate"
version = "1.2.0" version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26d50bfb8c23f23915855a00d98b5a35ef2e0b871bb52937bacadb798fbb66c8" checksum = "eda0fc3b0fb7c975631757e14d9049da17374063edb6ebbcbc54d880d4fe94e9"
dependencies = [ dependencies = [
"once_cell", "once_cell",
"thiserror", "thiserror",
@ -2942,18 +2933,18 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.141" version = "1.0.143"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7af873f2c95b99fcb0bd0fe622a43e29514658873c8ceba88c4cb88833a22500" checksum = "53e8e5d5b70924f74ff5c6d64d9a5acd91422117c60f48c4e07855238a254553"
dependencies = [ dependencies = [
"serde_derive", "serde_derive",
] ]
[[package]] [[package]]
name = "serde_derive" name = "serde_derive"
version = "1.0.141" version = "1.0.143"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75743a150d003dd863b51dc809bcad0d73f2102c53632f1e954e738192a3413f" checksum = "d3d8e8de557aee63c26b85b947f5e59b690d0454c753f3adeb5cd7835ab88391"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -2962,9 +2953,9 @@ dependencies = [
[[package]] [[package]]
name = "serde_json" name = "serde_json"
version = "1.0.82" version = "1.0.83"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "82c2c1fdcd807d1098552c5b9a36e425e42e9fbd7c6a37a8425f390f781f7fa7" checksum = "38dd04e3c8279e75b31ef29dbdceebfe5ad89f4d0937213c53f7d49d01b3d5a7"
dependencies = [ dependencies = [
"itoa", "itoa",
"ryu", "ryu",
@ -3263,9 +3254,9 @@ checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992"
[[package]] [[package]]
name = "unicode-ident" name = "unicode-ident"
version = "1.0.2" version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "15c61ba63f9235225a22310255a29b806b907c9b8c964bcbd0a2c70f3f2deea7" checksum = "c4f5b37a154999a8f3f98cc23a628d850e154479cd94decf3414696e12e31aaf"
[[package]] [[package]]
name = "unicode-normalization" name = "unicode-normalization"
@ -3662,9 +3653,9 @@ dependencies = [
[[package]] [[package]]
name = "x11-dl" name = "x11-dl"
version = "2.19.1" version = "2.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea26926b4ce81a6f5d9d0f3a0bc401e5a37c6ae14a1bfaa8ff6099ca80038c59" checksum = "0c83627bc137605acc00bb399c7b908ef460b621fc37c953db2b09f88c449ea6"
dependencies = [ dependencies = [
"lazy_static", "lazy_static",
"libc", "libc",

32
src/bin/circle.rs Normal file
View File

@ -0,0 +1,32 @@
use std::f32::consts::PI;
use bevy::prelude::*;
use bevy_prototype_lyon::prelude::*;
fn main() {
App::new()
.insert_resource(Msaa { samples: 4 })
.add_plugins(DefaultPlugins)
.add_plugin(ShapePlugin)
.add_startup_system(setup_system)
.run();
}
fn setup_system(mut commands: Commands) {
let mut path_builder = PathBuilder::new();
path_builder.move_to(Vec2::new(100., 0.));
path_builder.arc(
100.0 * Vec2::ZERO,
100.0 * Vec2::ONE,
90f32.to_radians(),
0.,
);
let line = path_builder.build();
commands.spawn_bundle(Camera2dBundle::default());
commands.spawn_bundle(GeometryBuilder::build_as(
&line,
DrawMode::Stroke(StrokeMode::new(Color::BLACK, 10.0)),
Transform::default(),
));
}

View File

@ -1,4 +1,5 @@
mod debug; mod debug;
mod primitives;
mod turtle; mod turtle;
mod turtle_movement; mod turtle_movement;
mod turtle_shapes; mod turtle_shapes;

110
src/primitives.rs Normal file
View File

@ -0,0 +1,110 @@
use bevy::prelude::{Bundle, Color, Component, Name, 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 {
start: Vec2,
end: Vec2,
}
impl Lens<Path> for CircleAnimationLens {
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 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.);
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,
}
}
}

View File

@ -2,13 +2,16 @@ use std::time::Duration;
use bevy::prelude::*; use bevy::prelude::*;
use bevy_inspector_egui::{Inspectable, RegisterInspectable}; use bevy_inspector_egui::{Inspectable, RegisterInspectable};
use bevy_prototype_lyon::{entity::ShapeBundle, prelude::*, shapes::Line}; use bevy_prototype_lyon::prelude::*;
use bevy_tweening::{ use bevy_tweening::{
component_animator_system, lens::TransformPositionLens, Animator, EaseFunction, Lens, Tween, component_animator_system, lens::TransformScaleLens, Animator, EaseFunction, Tween,
TweenCompleted, TweeningPlugin, TweeningType, TweenCompleted, TweeningPlugin, TweeningType,
}; };
use crate::turtle_shapes; use crate::{
primitives::{LineAnimationLens, TurtleDrawCircle, TurtleDrawLine},
turtle_shapes,
};
pub struct TurtlePlugin; pub struct TurtlePlugin;
@ -39,12 +42,26 @@ impl Default for Turtle {
}, },
commands: TurtleCommands::new(vec![ commands: TurtleCommands::new(vec![
TurtleCommand::Forward(Length(100.)), TurtleCommand::Forward(Length(100.)),
TurtleCommand::Circle {
radius: Length(150.),
angle: Angle(180.),
},
TurtleCommand::Right(Angle(90.)), TurtleCommand::Right(Angle(90.)),
TurtleCommand::Circle {
radius: Length(15.),
angle: Angle(180.),
},
TurtleCommand::Backward(Length(100.)), TurtleCommand::Backward(Length(100.)),
TurtleCommand::Right(Angle(90.)), TurtleCommand::Right(Angle(90.)),
TurtleCommand::Forward(Length(100.)), TurtleCommand::Forward(Length(100.)),
TurtleCommand::Right(Angle(45.)), TurtleCommand::Right(Angle(45.)),
//TurtleCommand::PenUp,
TurtleCommand::Forward(Length(100.)), TurtleCommand::Forward(Length(100.)),
//TurtleCommand::PenDown,
TurtleCommand::Circle {
radius: Length(-30.),
angle: Angle(90.),
},
TurtleCommand::Right(Angle(90.)), TurtleCommand::Right(Angle(90.)),
TurtleCommand::Forward(Length(50.)), TurtleCommand::Forward(Length(50.)),
TurtleCommand::Right(Angle(90.)), TurtleCommand::Right(Angle(90.)),
@ -94,6 +111,7 @@ pub struct TurtleState {
pub start: Vec2, pub start: Vec2,
pub heading: f32, pub heading: f32,
pub index: u64, pub index: u64,
pub drawing: bool,
} }
impl TurtleCommands { impl TurtleCommands {
@ -105,13 +123,14 @@ impl TurtleCommands {
start: Vec2::ZERO, start: Vec2::ZERO,
heading: 0f32.to_radians(), heading: 0f32.to_radians(),
index: 0, index: 0,
drawing: true,
}, },
} }
} }
} }
impl TurtleCommands { impl TurtleCommands {
fn get_next(&mut self) -> Option<(Tween<Transform>, TurtleGraphElement)> { fn get_next(&mut self) -> Option<(Option<Tween<Transform>>, Option<TurtleGraphElement>)> {
let index = self.state.index; let index = self.state.index;
let next_index = index + 1; let next_index = index + 1;
@ -129,9 +148,17 @@ impl TurtleCommands {
TurtleCommand::Right(Angle(x)) => { TurtleCommand::Right(Angle(x)) => {
crate::turtle_movement::turtle_turn(&mut self.state, -*x as f32) crate::turtle_movement::turtle_turn(&mut self.state, -*x as f32)
} }
TurtleCommand::PenUp => todo!(), TurtleCommand::PenUp => {
TurtleCommand::PenDown => todo!(), self.state.drawing = false;
TurtleCommand::Circle => todo!(), (None, None)
}
TurtleCommand::PenDown => {
self.state.drawing = true;
(None, None)
}
TurtleCommand::Circle { radius, angle } => {
crate::turtle_movement::turtle_circle(&mut self.state, radius.0 as f32, *angle)
}
TurtleCommand::Pause => todo!(), TurtleCommand::Pause => todo!(),
}; };
self.state.index = next_index; self.state.index = next_index;
@ -148,6 +175,13 @@ pub enum TurtleGraphElement {
start: Vec2, start: Vec2,
end: Vec2, end: Vec2,
}, },
TurtleCircle {
start: Vec2,
end: Vec2,
center: Vec2,
radii: Vec2,
angle: Angle,
},
#[default] #[default]
Noop, Noop,
} }
@ -161,10 +195,10 @@ pub struct Colors {
fill_color: Color, fill_color: Color,
} }
#[derive(Inspectable, Default)] #[derive(Inspectable, Default, Copy, Clone, Debug)]
pub struct Length(f64); pub struct Length(f32);
#[derive(Inspectable, Default)] #[derive(Inspectable, Default, Copy, Clone, Debug)]
pub struct Angle(f64); pub struct Angle(pub f32);
#[derive(Component, Inspectable, Default)] #[derive(Component, Inspectable, Default)]
pub enum TurtleCommand { pub enum TurtleCommand {
@ -176,24 +210,20 @@ pub enum TurtleCommand {
PenDown, PenDown,
#[default] #[default]
Pause, Pause,
Circle, Circle {
radius: Length,
angle: Angle,
},
} }
fn setup(mut commands: Commands) { fn setup(mut commands: Commands) {
let animator = Animator::new(Tween::new( let animator = Animator::new(Tween::new(
// Use a quadratic easing on both endpoints.
EaseFunction::QuadraticInOut, EaseFunction::QuadraticInOut,
// Loop animation back and forth.
TweeningType::PingPong, TweeningType::PingPong,
// Animation time (one way only; for ping-pong it takes 2 seconds
// to come back to start).
Duration::from_millis(500), Duration::from_millis(500),
// The lens gives access to the Transform component of the Entity, TransformScaleLens {
// for the Animator to animate it. It also contains the start and start: Vec3::new(1., 1., 0.),
// end values respectively associated with the progress ratios 0. and 1. end: Vec3::new(1.3, 1.3, 0.),
TransformPositionLens {
start: Vec3::ZERO,
end: Vec3::new(40., 40., 0.),
}, },
)); ));
commands.spawn_bundle(Camera2dBundle::default()); commands.spawn_bundle(Camera2dBundle::default());
@ -211,81 +241,61 @@ fn setup(mut commands: Commands) {
.insert(TurtleShape); .insert(TurtleShape);
} }
struct MyCustomLens {
start: Vec2,
end: Vec2,
}
impl Lens<Path> for MyCustomLens {
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)]
struct TurtleDrawLine {
#[bundle]
line: ShapeBundle,
name: Name,
marker: LineMarker,
}
#[derive(Component, Default)]
struct LineMarker;
impl TurtleDrawLine {
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,
}
}
}
fn draw_lines( fn draw_lines(
mut commands: Commands, mut commands: Commands,
mut tcmd: Query<&mut TurtleCommands>, mut tcmd: Query<&mut TurtleCommands>,
mut turtle: Query<&mut Animator<Transform>, With<TurtleShape>>, mut turtle: Query<&mut Animator<Transform>, With<TurtleShape>>,
mut query_event: EventReader<TweenCompleted>, // TODO: howto attach only to the right event? mut query_event: EventReader<TweenCompleted>, // TODO: howto attach only to the right event?
) { ) {
for _ev in query_event.iter() { for ev in query_event.iter() {
let mut tcmd = tcmd.single_mut(); let mut tcmd = tcmd.single_mut();
if let Some((turtle_animation, graph_element_to_draw)) = tcmd.get_next() { loop {
let mut turtle = turtle.single_mut(); match tcmd.get_next() {
turtle.set_tweenable(turtle_animation); Some((Some(turtle_animation), Some(graph_element_to_draw))) => {
match graph_element_to_draw { let mut turtle = turtle.single_mut();
TurtleGraphElement::TurtleLine { start, end } => { turtle.set_tweenable(turtle_animation);
let line_animator = Animator::new(Tween::new( match graph_element_to_draw {
// Use a quadratic easing on both endpoints. TurtleGraphElement::TurtleLine { start, end } => {
EaseFunction::QuadraticInOut, let line_animator = Animator::new(Tween::new(
// Loop animation back and forth. EaseFunction::QuadraticInOut,
TweeningType::Once, TweeningType::Once,
// Animation time (one way only; for ping-pong it takes 2 seconds Duration::from_millis(500),
// to come back to start). LineAnimationLens::new(start, end),
Duration::from_millis(500), ));
// The lens gives access to the Transform component of the Entity, commands
// for the Animator to animate it. It also contains the start and .spawn_bundle(TurtleDrawLine::new(start, end, tcmd.state.index))
// end values respectively associated with the progress ratios 0. and 1. .insert(line_animator);
MyCustomLens { start, end }, }
)); TurtleGraphElement::Noop => println!("No drawing!"),
commands TurtleGraphElement::TurtleCircle {
.spawn_bundle(TurtleDrawLine::new(start, end, tcmd.state.index)) center,
.insert(line_animator); radii,
angle,
start,
end,
} => {
// let circle_animator = todo!();
commands.spawn_bundle(TurtleDrawCircle::new(
center,
radii,
angle,
tcmd.state.index,
start,
end,
));
}
}
return;
} }
TurtleGraphElement::Noop => println!("No drawing!"), Some((_, _)) => {
} println!("without animation");
} else { }
println!("nothing to draw") None => {
}; println!("nothing to draw");
return;
}
};
}
} }
} }
@ -301,30 +311,40 @@ fn keypresses(
start: Vec2::ZERO, start: Vec2::ZERO,
heading: 0., heading: 0.,
index: 0, index: 0,
drawing: true,
}; };
if let Some((turtle_animation, graph_element_to_draw)) = tcmd.get_next() { if let Some((Some(turtle_animation), Some(graph_element_to_draw))) = tcmd.get_next() {
let mut shap = qry.single_mut(); let mut shap = qry.single_mut();
shap.set_tweenable(turtle_animation); shap.set_tweenable(turtle_animation);
match graph_element_to_draw { match graph_element_to_draw {
TurtleGraphElement::TurtleLine { start, end } => { TurtleGraphElement::TurtleLine { start, end } => {
let line_animator = Animator::new(Tween::new( let line_animator = Animator::new(Tween::new(
// Use a quadratic easing on both endpoints.
EaseFunction::QuadraticInOut, EaseFunction::QuadraticInOut,
// Loop animation back and forth.
TweeningType::Once, TweeningType::Once,
// Animation time (one way only; for ping-pong it takes 2 seconds
// to come back to start).
Duration::from_millis(500), Duration::from_millis(500),
// The lens gives access to the Transform component of the Entity, LineAnimationLens::new(start, end),
// for the Animator to animate it. It also contains the start and
// end values respectively associated with the progress ratios 0. and 1.
MyCustomLens { start, end },
)); ));
commands commands
.spawn_bundle(TurtleDrawLine::new(start, end, tcmd.state.index)) .spawn_bundle(TurtleDrawLine::new(start, end, tcmd.state.index))
.insert(line_animator); .insert(line_animator);
} }
TurtleGraphElement::Noop => (), TurtleGraphElement::Noop => (),
TurtleGraphElement::TurtleCircle {
center,
radii,
angle,
start,
end,
} => {
commands.spawn_bundle(TurtleDrawCircle::new(
center,
radii,
angle,
tcmd.state.index,
start,
end,
));
}
} }
}; };
} }

View File

@ -6,40 +6,40 @@ use bevy_tweening::{
EaseFunction, Tween, TweeningType, EaseFunction, Tween, TweeningType,
}; };
use crate::turtle::{TurtleGraphElement, TurtleState}; use crate::turtle::{Angle, TurtleGraphElement, TurtleState};
pub fn turtle_turn( pub fn turtle_turn(
state: &mut TurtleState, state: &mut TurtleState,
angle_to_turn: f32, angle_to_turn: f32,
) -> (Tween<Transform>, TurtleGraphElement) { ) -> (Option<Tween<Transform>>, Option<TurtleGraphElement>) {
let start = state.heading; let start = state.heading;
let end = state.heading + (angle_to_turn * PI / 180.); let end = state.heading + (angle_to_turn * PI / 180.);
let animation = Tween::new( let animation = Tween::new(
// Use a quadratic easing on both endpoints. // Use a quadratic easing on both endpoints
EaseFunction::QuadraticInOut, EaseFunction::QuadraticInOut,
// Loop animation back and forth.
TweeningType::Once, TweeningType::Once,
// Animation time (one way only; for ping-pong it takes 2 seconds // Animation time
// to come back to start).
Duration::from_millis(500), Duration::from_millis(500),
// The lens gives access to the Transform component of the Entity, // Rotate the turtle
// for the Animator to animate it. It also contains the start and
// end values respectively associated with the progress ratios 0. and 1.
TransformRotateZLens { start, end }, TransformRotateZLens { start, end },
) )
.with_completed_event(state.index as u64); .with_completed_event(state.index as u64);
// Dont move and draw
let line = TurtleGraphElement::Noop; let line = TurtleGraphElement::Noop;
// Update the state
state.heading = end % (2. * PI); state.heading = end % (2. * PI);
(animation, line) (Some(animation), Some(line))
} }
pub fn turtle_move(state: &mut TurtleState, length: f32) -> (Tween<Transform>, TurtleGraphElement) { pub fn turtle_move(
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) * length); let end = state.start + (Vec2::from_angle(state.heading) * length);
let turtle_movement_animation = Tween::new( let turtle_movement_animation = Tween::new(
// accelerate and decelerate // accelerate and decelerate
EaseFunction::QuadraticInOut, EaseFunction::QuadraticInOut,
// Loop animation back and forth.
TweeningType::Once, TweeningType::Once,
// later to be controlled by speed // later to be controlled by speed
Duration::from_millis(500), Duration::from_millis(500),
@ -50,7 +50,51 @@ pub fn turtle_move(state: &mut TurtleState, length: f32) -> (Tween<Transform>, T
}, },
) )
.with_completed_event(state.index as u64); .with_completed_event(state.index as u64);
let line = TurtleGraphElement::TurtleLine { start, end }; // The line for animating and drawing
let line = if state.drawing {
TurtleGraphElement::TurtleLine { start, end }
} else {
TurtleGraphElement::Noop
};
state.start = end; state.start = end;
(turtle_movement_animation, line) (Some(turtle_movement_animation), Some(line))
}
pub fn turtle_circle(
state: &mut TurtleState,
radius: f32,
angle: Angle,
) -> (Option<Tween<Transform>>, Option<TurtleGraphElement>) {
let radius_tuple = Vec2::ONE * radius.abs();
dbg!(state.start, radius_tuple);
let center = state.start
+ (Vec2::new(radius, 0.).rotate(Vec2::from_angle((state.heading + 90.).to_radians())));
dbg!(center);
let turtle_movement_animation = Tween::new(
// accelerate and decelerate
EaseFunction::QuadraticInOut,
TweeningType::Once,
// later to be controlled by speed
Duration::from_millis(500),
// set the start and end of the animation
TransformPositionLens {
start: center.extend(0.),
end: center.extend(0.),
},
)
.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 + 200.,
}
} else {
TurtleGraphElement::Noop
};
// TODO update end_position : state.start = end;
(Some(turtle_movement_animation), Some(line))
} }