198 lines
4.7 KiB
Rust
198 lines
4.7 KiB
Rust
use bevy::{ecs::schedule::ScheduleLabel, prelude::*};
|
|
use bevy_mod_debugdump::{render_graph, render_graph_dot, schedule_graph, schedule_graph_dot};
|
|
use core::{fmt, ops};
|
|
use std::{borrow::Borrow, fs, path::Path};
|
|
|
|
mod basis;
|
|
mod transform_f64;
|
|
mod vector2;
|
|
mod vector2_i32;
|
|
mod vector3;
|
|
mod vector3_i32;
|
|
|
|
pub use basis::*;
|
|
pub use transform_f64::*;
|
|
pub use vector2::*;
|
|
pub use vector2_i32::*;
|
|
pub use vector3::*;
|
|
pub use vector3_i32::*;
|
|
|
|
pub trait VectorComponent:
|
|
Sized
|
|
+ Copy
|
|
+ PartialOrd
|
|
+ Reflect
|
|
+ fmt::Display
|
|
+ ops::Add<Output = Self>
|
|
+ ops::Neg<Output = Self>
|
|
+ ops::Sub<Output = Self>
|
|
+ ops::Mul<Output = Self>
|
|
+ ops::Div<Output = Self>
|
|
+ num_traits::identities::Zero
|
|
+ num_traits::identities::One
|
|
+ num_traits::sign::Signed
|
|
{
|
|
fn min(self, b: Self) -> Self;
|
|
fn max(self, b: Self) -> Self;
|
|
}
|
|
|
|
impl<T> VectorComponent for T
|
|
where
|
|
T: Sized
|
|
+ Copy
|
|
+ PartialOrd
|
|
+ Reflect
|
|
+ fmt::Display
|
|
+ ops::Neg<Output = T>
|
|
+ ops::Add<Output = T>
|
|
+ ops::Sub<Output = T>
|
|
+ ops::Mul<Output = T>
|
|
+ ops::Div<Output = T>
|
|
+ num_traits::identities::Zero
|
|
+ num_traits::identities::One
|
|
+ num_traits::sign::Signed,
|
|
{
|
|
fn min(self, b: Self) -> Self {
|
|
if self < b {
|
|
self
|
|
} else {
|
|
b
|
|
}
|
|
}
|
|
|
|
fn max(self, b: Self) -> Self {
|
|
if self > b {
|
|
self
|
|
} else {
|
|
b
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn lerp<
|
|
T: Copy
|
|
+ ops::Add<Output = T>
|
|
+ ops::Sub<Output = T>
|
|
+ ops::Mul<Output = T>
|
|
+ num_traits::identities::One,
|
|
>(
|
|
a: T,
|
|
b: T,
|
|
t: T,
|
|
) -> T {
|
|
a * (T::one() - t) + b * t
|
|
}
|
|
|
|
pub fn inverse_lerp<T: Copy + ops::Sub<Output = T> + ops::Div<Output = T>>(
|
|
a: T,
|
|
b: T,
|
|
value: T,
|
|
) -> T {
|
|
(value - a) / (b - a)
|
|
}
|
|
|
|
pub fn vec2_lerp(a: Vec2, b: Vec2, t: f32) -> Vec2 {
|
|
Vec2 {
|
|
x: lerp(a.x, b.x, t),
|
|
y: lerp(a.y, b.y, t),
|
|
}
|
|
}
|
|
|
|
pub fn vec3_lerp(a: Vec3, b: Vec3, t: f32) -> Vec3 {
|
|
Vec3 {
|
|
x: lerp(a.x, b.x, t),
|
|
y: lerp(a.y, b.y, t),
|
|
z: lerp(a.z, b.z, t),
|
|
}
|
|
}
|
|
|
|
pub fn move_towards_vec2(from: Vec2, to: Vec2, amount: f32) -> Vec2 {
|
|
let diff = to - from;
|
|
let length = diff.length();
|
|
if length <= f32::EPSILON {
|
|
return from;
|
|
}
|
|
from + diff.normalize() * length.min(amount)
|
|
}
|
|
|
|
pub fn move_towards_vec3(from: Vec3, to: Vec3, amount: f32) -> Vec3 {
|
|
let diff = to - from;
|
|
let length = diff.length();
|
|
if length <= f32::EPSILON {
|
|
return from;
|
|
}
|
|
from + diff.normalize() * length.min(amount)
|
|
}
|
|
|
|
/// Get the intersection point (if any) of 2d lines a and b.
|
|
/// Lines are defined by 2 points on the line
|
|
pub fn vec2_intersection(a1: Vec2, a2: Vec2, b1: Vec2, b2: Vec2) -> Option<Vec2> {
|
|
let a_dir = a2 - a1;
|
|
let b_dir = b2 - b1;
|
|
let determinant = a_dir.perp_dot(b_dir);
|
|
if determinant.abs() <= f32::EPSILON {
|
|
return None;
|
|
}
|
|
Some(
|
|
Vec2 {
|
|
x: a_dir.x * (b1.x * b2.y - b1.y * b2.x) - (a1.x * a2.y - a1.y * a2.x) * b_dir.x,
|
|
y: (a1.x * a2.y - a1.y * a2.x) * -b_dir.y + a_dir.y * (b1.x * b2.y - b1.y * b2.x),
|
|
} / determinant,
|
|
)
|
|
}
|
|
|
|
pub fn loop_value(from: f32, to: f32, value: f32) -> f32 {
|
|
let range = to - from;
|
|
if !range.is_normal() {
|
|
return from;
|
|
}
|
|
value - inverse_lerp(from, to, value).floor() * range
|
|
}
|
|
|
|
pub fn create_app_graphs(app: &mut App) {
|
|
let schedules: Vec<Box<dyn ScheduleLabel>> = app
|
|
.world
|
|
.borrow()
|
|
.resource::<Schedules>()
|
|
.iter()
|
|
.map(|(label, _)| label.dyn_clone())
|
|
.collect();
|
|
|
|
println!("Writing {} schedule graphs", schedules.len());
|
|
|
|
schedules.iter().for_each(|schedule_label| {
|
|
let path = Path::new("graphs").join(format!("schedule_{schedule_label:?}.dot"));
|
|
write_schedule_graph(app, &path, &schedule_label.to_owned());
|
|
println!("\t- {}", path.to_string_lossy())
|
|
});
|
|
|
|
println!("Writing render graph");
|
|
{
|
|
let path = Path::new("graphs").join("render.dot");
|
|
write_render_graph(app, &path);
|
|
println!("\t- {}", path.to_string_lossy());
|
|
}
|
|
}
|
|
|
|
fn write_schedule_graph(app: &mut App, path: &Path, schedule: &dyn ScheduleLabel) {
|
|
fs::create_dir_all(path.parent().unwrap()).unwrap();
|
|
fs::write(
|
|
path,
|
|
schedule_graph_dot(
|
|
app,
|
|
schedule.dyn_clone(),
|
|
&schedule_graph::settings::Settings::default(),
|
|
),
|
|
)
|
|
.unwrap();
|
|
}
|
|
|
|
fn write_render_graph(app: &mut App, path: &Path) {
|
|
fs::create_dir_all(path.parent().unwrap()).unwrap();
|
|
fs::write(
|
|
path,
|
|
render_graph_dot(app, &render_graph::settings::Settings::default()),
|
|
)
|
|
.unwrap();
|
|
}
|