generated from hheik/bevy-template
Initial commit
commit
701e88efa9
|
|
@ -0,0 +1,2 @@
|
||||||
|
/target
|
||||||
|
/graphs
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,21 @@
|
||||||
|
[package]
|
||||||
|
name = "bevy-template"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
bevy = "0.15.1"
|
||||||
|
bevy-inspector-egui = "0.28.1"
|
||||||
|
bevy_mod_debugdump = "0.12.1"
|
||||||
|
bevy_rapier2d = "0.28.0"
|
||||||
|
num-traits = "0.2.19"
|
||||||
|
|
||||||
|
# Enable a small amount of optimization in debug mode
|
||||||
|
[profile.dev]
|
||||||
|
opt-level = 1
|
||||||
|
|
||||||
|
# Enable high optimizations for dependencies (incl. Bevy), but not for our code:
|
||||||
|
[profile.dev.package."*"]
|
||||||
|
opt-level = 3
|
||||||
|
|
@ -0,0 +1,45 @@
|
||||||
|
use bevy::prelude::*;
|
||||||
|
|
||||||
|
pub struct DebugPlugin;
|
||||||
|
|
||||||
|
#[derive(Debug, Hash, PartialEq, Eq, Clone, SystemSet)]
|
||||||
|
pub struct DebugSet;
|
||||||
|
|
||||||
|
impl Plugin for DebugPlugin {
|
||||||
|
fn build(&self, app: &mut App) {
|
||||||
|
app.configure_sets(Last, DebugSet.run_if(is_debug_enabled));
|
||||||
|
|
||||||
|
app.insert_resource(DebugMode::on())
|
||||||
|
.add_plugins((
|
||||||
|
bevy_inspector_egui::quick::WorldInspectorPlugin::new().run_if(is_debug_enabled),
|
||||||
|
bevy_rapier2d::prelude::RapierDebugRenderPlugin::default(),
|
||||||
|
))
|
||||||
|
.add_systems(Update, debug_toggle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Reflect, Resource, Default)]
|
||||||
|
#[reflect(Resource)]
|
||||||
|
pub struct DebugMode {
|
||||||
|
pub enabled: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DebugMode {
|
||||||
|
pub fn on() -> Self {
|
||||||
|
Self { enabled: true }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn off() -> Self {
|
||||||
|
Self { enabled: false }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_debug_enabled(debug_mode: Res<DebugMode>) -> bool {
|
||||||
|
debug_mode.enabled
|
||||||
|
}
|
||||||
|
|
||||||
|
fn debug_toggle(input: Res<ButtonInput<KeyCode>>, mut debug_mode: ResMut<DebugMode>) {
|
||||||
|
if input.just_pressed(KeyCode::KeyP) {
|
||||||
|
debug_mode.enabled = !debug_mode.enabled
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,118 @@
|
||||||
|
use crate::{debug, game_setup};
|
||||||
|
use bevy::prelude::*;
|
||||||
|
use bevy_rapier2d::prelude::*;
|
||||||
|
|
||||||
|
pub fn init(app: &mut App) {
|
||||||
|
let app = app.add_plugins((
|
||||||
|
game_setup::GameSetupPlugin,
|
||||||
|
RapierPhysicsPlugin::<NoUserData>::default(),
|
||||||
|
debug::DebugPlugin,
|
||||||
|
));
|
||||||
|
|
||||||
|
app.add_systems(Startup, setup_2d)
|
||||||
|
.add_systems(Update, demo_2d);
|
||||||
|
|
||||||
|
// app.add_systems(Startup, setup_3d)
|
||||||
|
// .add_systems(Update, demo_3d);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn setup_2d(mut commands: Commands) {
|
||||||
|
commands.spawn((
|
||||||
|
Name::from("Demo 2D camera"),
|
||||||
|
Camera2d,
|
||||||
|
Transform::from_xyz(0.0, 0.0, 10.0),
|
||||||
|
));
|
||||||
|
commands.spawn((
|
||||||
|
Name::from("Demo 2D sprite"),
|
||||||
|
Sprite::sized(Vec2::splat(256.0)),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn demo_2d(
|
||||||
|
mut camera_query: Query<(&mut Transform, &mut OrthographicProjection)>,
|
||||||
|
mut mouse_events: EventReader<bevy::input::mouse::MouseMotion>,
|
||||||
|
mut scroll_events: EventReader<bevy::input::mouse::MouseWheel>,
|
||||||
|
mouse_input: Res<ButtonInput<MouseButton>>,
|
||||||
|
) {
|
||||||
|
let raw_mouse_motion: Vec2 = mouse_events.read().map(|e| e.delta).sum();
|
||||||
|
let raw_scroll_motion: f32 = scroll_events
|
||||||
|
.read()
|
||||||
|
.map(|event| match event.unit {
|
||||||
|
bevy::input::mouse::MouseScrollUnit::Line => event.y * -0.1,
|
||||||
|
bevy::input::mouse::MouseScrollUnit::Pixel => event.y * -0.05,
|
||||||
|
})
|
||||||
|
.sum();
|
||||||
|
|
||||||
|
for (mut transform, mut projection) in camera_query.iter_mut() {
|
||||||
|
projection.scale += raw_scroll_motion * projection.scale;
|
||||||
|
let mouse_motion = raw_mouse_motion * projection.scale * Vec2::new(-1.0, 1.0);
|
||||||
|
if mouse_input.pressed(MouseButton::Middle) {
|
||||||
|
transform.translation += mouse_motion.extend(0.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn setup_3d(
|
||||||
|
mut commands: Commands,
|
||||||
|
mut meshes: ResMut<Assets<Mesh>>,
|
||||||
|
mut materials: ResMut<Assets<StandardMaterial>>,
|
||||||
|
) {
|
||||||
|
commands.spawn((
|
||||||
|
Name::from("Demo 3D camera"),
|
||||||
|
Camera3d::default(),
|
||||||
|
Transform::from_xyz(0.0, 0.0, 10.0),
|
||||||
|
PointLight::default(),
|
||||||
|
));
|
||||||
|
commands.spawn((
|
||||||
|
Name::from("Demo 3D cuboid"),
|
||||||
|
Mesh3d(meshes.add(Cuboid::from_length(1.0))),
|
||||||
|
MeshMaterial3d(materials.add(Color::from(bevy::color::palettes::css::ORANGE))),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn demo_3d(
|
||||||
|
mut camera_query: Query<&mut Transform, With<Camera3d>>,
|
||||||
|
mut mouse_events: EventReader<bevy::input::mouse::MouseMotion>,
|
||||||
|
mouse_input: Res<ButtonInput<MouseButton>>,
|
||||||
|
key_input: Res<ButtonInput<KeyCode>>,
|
||||||
|
time: Res<Time>,
|
||||||
|
) {
|
||||||
|
let raw_mouse_motion: Vec2 = mouse_events.read().map(|e| e.delta).sum();
|
||||||
|
|
||||||
|
if mouse_input.pressed(MouseButton::Right) {
|
||||||
|
let move_forward = key_input.pressed(KeyCode::KeyW);
|
||||||
|
let move_back = key_input.pressed(KeyCode::KeyS);
|
||||||
|
let move_left = key_input.pressed(KeyCode::KeyA);
|
||||||
|
let move_right = key_input.pressed(KeyCode::KeyD);
|
||||||
|
let move_up = key_input.pressed(KeyCode::Space) || key_input.pressed(KeyCode::KeyE);
|
||||||
|
let move_down = key_input.pressed(KeyCode::ControlLeft) || key_input.pressed(KeyCode::KeyQ);
|
||||||
|
|
||||||
|
let raw_movement = Vec3 {
|
||||||
|
x: match (move_right, move_left) {
|
||||||
|
(true, false) => 1.0,
|
||||||
|
(false, true) => -1.0,
|
||||||
|
_ => 0.0,
|
||||||
|
},
|
||||||
|
y: match (move_up, move_down) {
|
||||||
|
(true, false) => 1.0,
|
||||||
|
(false, true) => -1.0,
|
||||||
|
_ => 0.0,
|
||||||
|
},
|
||||||
|
z: match (move_back, move_forward) {
|
||||||
|
(true, false) => 1.0,
|
||||||
|
(false, true) => -1.0,
|
||||||
|
_ => 0.0,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
for mut transform in camera_query.iter_mut() {
|
||||||
|
let mouse_motion = raw_mouse_motion * Vec2::new(-1.0, -1.0) * 0.002;
|
||||||
|
transform.rotate_axis(Dir3::Y, mouse_motion.x);
|
||||||
|
transform.rotate_local_x(mouse_motion.y);
|
||||||
|
|
||||||
|
let local_movement = raw_movement * time.delta_secs() * 10.0;
|
||||||
|
let movement = transform.rotation * local_movement;
|
||||||
|
transform.translation += movement;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
use bevy::{prelude::*, window::WindowResolution};
|
||||||
|
|
||||||
|
pub struct GameSetupPlugin;
|
||||||
|
|
||||||
|
impl Plugin for GameSetupPlugin {
|
||||||
|
fn build(&self, app: &mut App) {
|
||||||
|
app.insert_resource(ClearColor(Color::BLACK)).add_plugins(
|
||||||
|
DefaultPlugins
|
||||||
|
.set(WindowPlugin {
|
||||||
|
primary_window: Some(Window {
|
||||||
|
resolution: WindowResolution::new(512.0 * 2.0, 320.0 * 2.0),
|
||||||
|
title: "Bevy template <press P to toggle debug mode>".to_string(), // NOTE: Replace this
|
||||||
|
resizable: false,
|
||||||
|
..default()
|
||||||
|
}),
|
||||||
|
..default()
|
||||||
|
})
|
||||||
|
.set(ImagePlugin::default_nearest()),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
use bevy::prelude::*;
|
||||||
|
use util::create_app_graphs;
|
||||||
|
|
||||||
|
pub mod debug;
|
||||||
|
pub mod game;
|
||||||
|
pub mod game_setup;
|
||||||
|
pub mod util;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let mut app = App::new();
|
||||||
|
game::init(&mut app);
|
||||||
|
create_app_graphs(&mut app);
|
||||||
|
app.run();
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,169 @@
|
||||||
|
use bevy::prelude::*;
|
||||||
|
use bevy_mod_debugdump::{render_graph, render_graph_dot};
|
||||||
|
use core::{fmt, ops};
|
||||||
|
use std::{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) {
|
||||||
|
// TODO: Figure out how to list schedules under the new interned ScheduleLabel system
|
||||||
|
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_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();
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,42 @@
|
||||||
|
use bevy::prelude::*;
|
||||||
|
|
||||||
|
use super::{Vector3, VectorComponent};
|
||||||
|
|
||||||
|
#[derive(PartialEq, Eq, Hash, Clone, Copy, Debug, Reflect)]
|
||||||
|
pub struct Basis<T: VectorComponent> {
|
||||||
|
pub x: Vector3<T>,
|
||||||
|
pub y: Vector3<T>,
|
||||||
|
pub z: Vector3<T>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: VectorComponent> Default for Basis<T> {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
x: Vector3::x(),
|
||||||
|
y: Vector3::y(),
|
||||||
|
z: Vector3::z(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: VectorComponent> Basis<T> {
|
||||||
|
pub fn identity() -> Self {
|
||||||
|
Self::default()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn inverse(&self) -> Self {
|
||||||
|
Self {
|
||||||
|
x: self.x * -T::one(),
|
||||||
|
y: self.y * -T::one(),
|
||||||
|
z: self.z * -T::one(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn transform(&self, point: Vector3<T>) -> Vector3<T> {
|
||||||
|
self.x * point.x + self.y * point.y + self.z * point.z
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn inverse_transform(&self, point: Vector3<T>) -> Vector3<T> {
|
||||||
|
self.inverse().transform(point)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,34 @@
|
||||||
|
use bevy::prelude::*;
|
||||||
|
|
||||||
|
mod basis_f64;
|
||||||
|
mod vector3_f64;
|
||||||
|
|
||||||
|
pub use basis_f64::*;
|
||||||
|
pub use vector3_f64::*;
|
||||||
|
|
||||||
|
pub struct DoublePrecisionPlugin;
|
||||||
|
|
||||||
|
impl Plugin for DoublePrecisionPlugin {
|
||||||
|
fn build(&self, app: &mut App) {
|
||||||
|
app.insert_resource(WorldOffset::default())
|
||||||
|
.register_type::<TranslationD>()
|
||||||
|
.add_systems(PostUpdate, translation_system);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Resource, Reflect, Default)]
|
||||||
|
#[reflect(Resource)]
|
||||||
|
pub struct WorldOffset(pub Vector3D);
|
||||||
|
|
||||||
|
#[derive(Component, Reflect, Default)]
|
||||||
|
#[reflect(Component)]
|
||||||
|
pub struct TranslationD(pub Vector3D);
|
||||||
|
|
||||||
|
fn translation_system(
|
||||||
|
mut query: Query<(&mut Transform, &TranslationD)>,
|
||||||
|
world_offset: Res<WorldOffset>,
|
||||||
|
) {
|
||||||
|
for (mut real_transform, translation) in query.iter_mut() {
|
||||||
|
real_transform.translation = Vec3::from(translation.0 - world_offset.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
use crate::util::Basis;
|
||||||
|
|
||||||
|
use super::Vector3D;
|
||||||
|
|
||||||
|
pub type BasisD = Basis<f64>;
|
||||||
|
|
||||||
|
impl BasisD {
|
||||||
|
pub fn from_euler(yaw: f64, pitch: f64, roll: f64) -> Self {
|
||||||
|
let basis = Self::identity();
|
||||||
|
let basis = basis.rotate_by_axis(&basis.y, yaw);
|
||||||
|
let basis = basis.rotate_by_axis(&basis.x, pitch);
|
||||||
|
let basis = basis.rotate_by_axis(&basis.z, roll);
|
||||||
|
basis
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn rotate_by_axis(&self, axis: &Vector3D, angle: f64) -> Self {
|
||||||
|
Self {
|
||||||
|
x: self.x.rotate_around_axis(axis, angle),
|
||||||
|
y: self.y.rotate_around_axis(axis, angle),
|
||||||
|
z: self.z.rotate_around_axis(axis, angle),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,74 @@
|
||||||
|
use bevy::prelude::*;
|
||||||
|
|
||||||
|
use crate::util::Vector3;
|
||||||
|
|
||||||
|
pub type Vector3D = Vector3<f64>;
|
||||||
|
|
||||||
|
impl Vector3D {
|
||||||
|
pub const ZERO: Self = Self {
|
||||||
|
x: 0.0,
|
||||||
|
y: 0.0,
|
||||||
|
z: 0.0,
|
||||||
|
};
|
||||||
|
pub const ONE: Self = Self {
|
||||||
|
x: 1.0,
|
||||||
|
y: 1.0,
|
||||||
|
z: 1.0,
|
||||||
|
};
|
||||||
|
pub const UP: Self = Self {
|
||||||
|
x: 0.0,
|
||||||
|
y: 1.0,
|
||||||
|
z: 0.0,
|
||||||
|
};
|
||||||
|
pub const DOWN: Self = Self {
|
||||||
|
x: 0.0,
|
||||||
|
y: -1.0,
|
||||||
|
z: 0.0,
|
||||||
|
};
|
||||||
|
pub const LEFT: Self = Self {
|
||||||
|
x: -1.0,
|
||||||
|
y: 0.0,
|
||||||
|
z: 0.0,
|
||||||
|
};
|
||||||
|
pub const RIGHT: Self = Self {
|
||||||
|
x: 1.0,
|
||||||
|
y: 0.0,
|
||||||
|
z: 0.0,
|
||||||
|
};
|
||||||
|
pub const FORWARD: Self = Self {
|
||||||
|
x: 0.0,
|
||||||
|
y: 0.0,
|
||||||
|
z: -1.0,
|
||||||
|
};
|
||||||
|
pub const BACK: Self = Self {
|
||||||
|
x: 0.0,
|
||||||
|
y: 0.0,
|
||||||
|
z: 1.0,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn rotate_around_axis(&self, axis: &Self, angle: f64) -> Self {
|
||||||
|
*self * angle.cos()
|
||||||
|
+ axis.cross(self) * angle.sin()
|
||||||
|
+ *axis * axis.dot(self) * (1.0 - angle.cos())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Vec3> for Vector3D {
|
||||||
|
fn from(vec: Vec3) -> Self {
|
||||||
|
Self {
|
||||||
|
x: vec.x as f64,
|
||||||
|
y: vec.y as f64,
|
||||||
|
z: vec.y as f64,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Vector3D> for Vec3 {
|
||||||
|
fn from(vec: Vector3D) -> Self {
|
||||||
|
Vec3 {
|
||||||
|
x: vec.x as f32,
|
||||||
|
y: vec.y as f32,
|
||||||
|
z: vec.z as f32,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,152 @@
|
||||||
|
use bevy::reflect::Reflect;
|
||||||
|
use core::{fmt, ops};
|
||||||
|
|
||||||
|
use super::VectorComponent;
|
||||||
|
|
||||||
|
#[derive(PartialEq, Eq, Hash, Clone, Copy, Default, Debug, Reflect)]
|
||||||
|
pub struct Vector2<T: VectorComponent> {
|
||||||
|
pub x: T,
|
||||||
|
pub y: T,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: VectorComponent> Vector2<T> {
|
||||||
|
pub fn x() -> Self {
|
||||||
|
Self {
|
||||||
|
x: T::one(),
|
||||||
|
y: T::zero(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn y() -> Self {
|
||||||
|
Self {
|
||||||
|
x: T::zero(),
|
||||||
|
y: T::one(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn zero() -> Self {
|
||||||
|
Self {
|
||||||
|
x: T::zero(),
|
||||||
|
y: T::zero(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn one() -> Self {
|
||||||
|
Self {
|
||||||
|
x: T::one(),
|
||||||
|
y: T::one(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn up() -> Self {
|
||||||
|
Self {
|
||||||
|
x: T::zero(),
|
||||||
|
y: T::one(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn down() -> Self {
|
||||||
|
Self {
|
||||||
|
x: T::zero(),
|
||||||
|
y: -T::one(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn left() -> Self {
|
||||||
|
Self {
|
||||||
|
x: -T::one(),
|
||||||
|
y: T::zero(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn right() -> Self {
|
||||||
|
Self {
|
||||||
|
x: T::one(),
|
||||||
|
y: T::zero(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new(x: T, y: T) -> Vector2<T> {
|
||||||
|
Vector2 { x, y }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn min(&self, other: &Vector2<T>) -> Vector2<T> {
|
||||||
|
Vector2 {
|
||||||
|
x: VectorComponent::min(self.x, other.x),
|
||||||
|
y: VectorComponent::min(self.y, other.y),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn max(&self, other: &Vector2<T>) -> Vector2<T> {
|
||||||
|
Vector2 {
|
||||||
|
x: VectorComponent::max(self.x, other.x),
|
||||||
|
y: VectorComponent::max(self.y, other.y),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: VectorComponent> fmt::Display for Vector2<T> {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
write!(f, "({}, {})", self.x, self.y)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: VectorComponent> ops::Add<Vector2<T>> for Vector2<T> {
|
||||||
|
type Output = Vector2<T>;
|
||||||
|
fn add(self, rhs: Vector2<T>) -> Self::Output {
|
||||||
|
Vector2 {
|
||||||
|
x: self.x + rhs.x,
|
||||||
|
y: self.y + rhs.y,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: VectorComponent> ops::Neg for Vector2<T> {
|
||||||
|
type Output = Vector2<T>;
|
||||||
|
fn neg(self) -> Self::Output {
|
||||||
|
Vector2 {
|
||||||
|
x: -self.x,
|
||||||
|
y: -self.y,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: VectorComponent> ops::Sub<Vector2<T>> for Vector2<T> {
|
||||||
|
type Output = Vector2<T>;
|
||||||
|
fn sub(self, rhs: Vector2<T>) -> Self::Output {
|
||||||
|
self + (-rhs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: VectorComponent> ops::Mul<Vector2<T>> for Vector2<T> {
|
||||||
|
type Output = Vector2<T>;
|
||||||
|
fn mul(self, rhs: Vector2<T>) -> Self::Output {
|
||||||
|
Vector2 {
|
||||||
|
x: self.x * rhs.x,
|
||||||
|
y: self.y * rhs.y,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: VectorComponent> ops::Mul<T> for Vector2<T> {
|
||||||
|
type Output = Vector2<T>;
|
||||||
|
fn mul(self, rhs: T) -> Self::Output {
|
||||||
|
Vector2 {
|
||||||
|
x: self.x * rhs,
|
||||||
|
y: self.y * rhs,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: VectorComponent> ops::Div<Vector2<T>> for Vector2<T> {
|
||||||
|
type Output = Vector2<T>;
|
||||||
|
fn div(self, rhs: Vector2<T>) -> Self::Output {
|
||||||
|
Vector2 {
|
||||||
|
x: self.x / rhs.x,
|
||||||
|
y: self.y / rhs.y,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: VectorComponent> ops::Div<T> for Vector2<T> {
|
||||||
|
type Output = Vector2<T>;
|
||||||
|
fn div(self, rhs: T) -> Self::Output {
|
||||||
|
Vector2 {
|
||||||
|
x: self.x / rhs,
|
||||||
|
y: self.y / rhs,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,46 @@
|
||||||
|
use bevy::prelude::*;
|
||||||
|
|
||||||
|
use super::Vector2;
|
||||||
|
|
||||||
|
pub type Vector2I = Vector2<i32>;
|
||||||
|
|
||||||
|
impl Vector2I {
|
||||||
|
pub const ZERO: Vector2I = Vector2I { x: 0, y: 0 };
|
||||||
|
pub const ONE: Vector2I = Vector2I { x: 1, y: 1 };
|
||||||
|
pub const UP: Vector2I = Vector2I { x: 0, y: 1 };
|
||||||
|
pub const DOWN: Vector2I = Vector2I { x: 0, y: -1 };
|
||||||
|
pub const LEFT: Vector2I = Vector2I { x: -1, y: 0 };
|
||||||
|
pub const RIGHT: Vector2I = Vector2I { x: 1, y: 0 };
|
||||||
|
|
||||||
|
pub fn angle(&self) -> f32 {
|
||||||
|
(self.y as f32).atan2(self.x as f32)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Vec2> for Vector2I {
|
||||||
|
fn from(vec: Vec2) -> Self {
|
||||||
|
Self {
|
||||||
|
x: vec.x as i32,
|
||||||
|
y: vec.y as i32,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Vector2I> for Vec2 {
|
||||||
|
fn from(vec: Vector2I) -> Self {
|
||||||
|
Vec2 {
|
||||||
|
x: vec.x as f32,
|
||||||
|
y: vec.y as f32,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Vector2I> for Vec3 {
|
||||||
|
fn from(vec: Vector2I) -> Self {
|
||||||
|
Vec3 {
|
||||||
|
x: vec.x as f32,
|
||||||
|
y: vec.y as f32,
|
||||||
|
z: 0.0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,202 @@
|
||||||
|
use bevy::reflect::Reflect;
|
||||||
|
use core::{fmt, ops};
|
||||||
|
|
||||||
|
use super::VectorComponent;
|
||||||
|
|
||||||
|
#[derive(PartialEq, Eq, Hash, Clone, Copy, Default, Debug, Reflect)]
|
||||||
|
pub struct Vector3<T: VectorComponent> {
|
||||||
|
pub x: T,
|
||||||
|
pub y: T,
|
||||||
|
pub z: T,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: VectorComponent> Vector3<T> {
|
||||||
|
pub fn x() -> Self {
|
||||||
|
Self {
|
||||||
|
x: T::one(),
|
||||||
|
y: T::zero(),
|
||||||
|
z: T::zero(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn y() -> Self {
|
||||||
|
Self {
|
||||||
|
x: T::zero(),
|
||||||
|
y: T::one(),
|
||||||
|
z: T::zero(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn z() -> Self {
|
||||||
|
Self {
|
||||||
|
x: T::zero(),
|
||||||
|
y: T::zero(),
|
||||||
|
z: T::one(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn zero() -> Self {
|
||||||
|
Self {
|
||||||
|
x: T::zero(),
|
||||||
|
y: T::zero(),
|
||||||
|
z: T::zero(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn one() -> Self {
|
||||||
|
Self {
|
||||||
|
x: T::one(),
|
||||||
|
y: T::one(),
|
||||||
|
z: T::one(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn up() -> Self {
|
||||||
|
Self {
|
||||||
|
x: T::zero(),
|
||||||
|
y: T::one(),
|
||||||
|
z: T::zero(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn down() -> Self {
|
||||||
|
Self {
|
||||||
|
x: T::zero(),
|
||||||
|
y: -T::one(),
|
||||||
|
z: T::zero(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn left() -> Self {
|
||||||
|
Self {
|
||||||
|
x: -T::one(),
|
||||||
|
y: T::zero(),
|
||||||
|
z: T::zero(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn right() -> Self {
|
||||||
|
Self {
|
||||||
|
x: T::one(),
|
||||||
|
y: T::zero(),
|
||||||
|
z: T::zero(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn forward() -> Self {
|
||||||
|
Self {
|
||||||
|
x: T::zero(),
|
||||||
|
y: T::zero(),
|
||||||
|
z: -T::one(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn back() -> Self {
|
||||||
|
Self {
|
||||||
|
x: T::zero(),
|
||||||
|
y: T::zero(),
|
||||||
|
z: T::one(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new(x: T, y: T, z: T) -> Self {
|
||||||
|
Vector3 { x, y, z }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn min(&self, other: &Self) -> Self {
|
||||||
|
Vector3 {
|
||||||
|
x: VectorComponent::min(self.x, other.x),
|
||||||
|
y: VectorComponent::min(self.y, other.y),
|
||||||
|
z: VectorComponent::min(self.z, other.z),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn max(&self, other: &Self) -> Self {
|
||||||
|
Vector3 {
|
||||||
|
x: VectorComponent::max(self.x, other.x),
|
||||||
|
y: VectorComponent::max(self.y, other.y),
|
||||||
|
z: VectorComponent::max(self.z, other.z),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn dot(&self, other: &Self) -> T {
|
||||||
|
self.x * other.x + self.y * other.y + self.z * other.z
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn cross(&self, other: &Self) -> Self {
|
||||||
|
Self {
|
||||||
|
x: self.y * other.z - self.z * other.y,
|
||||||
|
y: self.z * other.x - self.x * other.z,
|
||||||
|
z: self.x * other.y - self.y * other.x,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: VectorComponent> fmt::Display for Vector3<T> {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
write!(f, "({}, {}, {})", self.x, self.y, self.z)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: VectorComponent> ops::Add<Vector3<T>> for Vector3<T> {
|
||||||
|
type Output = Self;
|
||||||
|
fn add(self, rhs: Self) -> Self::Output {
|
||||||
|
Vector3 {
|
||||||
|
x: self.x + rhs.x,
|
||||||
|
y: self.y + rhs.y,
|
||||||
|
z: self.z + rhs.z,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: VectorComponent> ops::Neg for Vector3<T> {
|
||||||
|
type Output = Self;
|
||||||
|
fn neg(self) -> Self::Output {
|
||||||
|
Vector3 {
|
||||||
|
x: -self.x,
|
||||||
|
y: -self.y,
|
||||||
|
z: -self.z,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: VectorComponent> ops::Sub<Vector3<T>> for Vector3<T> {
|
||||||
|
type Output = Self;
|
||||||
|
fn sub(self, rhs: Self) -> Self::Output {
|
||||||
|
self + (-rhs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: VectorComponent> ops::Mul<Vector3<T>> for Vector3<T> {
|
||||||
|
type Output = Self;
|
||||||
|
fn mul(self, rhs: Self) -> Self::Output {
|
||||||
|
Vector3 {
|
||||||
|
x: self.x * rhs.x,
|
||||||
|
y: self.y * rhs.y,
|
||||||
|
z: self.z * rhs.z,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: VectorComponent> ops::Mul<T> for Vector3<T> {
|
||||||
|
type Output = Self;
|
||||||
|
fn mul(self, rhs: T) -> Self::Output {
|
||||||
|
Vector3 {
|
||||||
|
x: self.x * rhs,
|
||||||
|
y: self.y * rhs,
|
||||||
|
z: self.z * rhs,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: VectorComponent> ops::Div<Vector3<T>> for Vector3<T> {
|
||||||
|
type Output = Self;
|
||||||
|
fn div(self, rhs: Vector3<T>) -> Self::Output {
|
||||||
|
Vector3 {
|
||||||
|
x: self.x / rhs.x,
|
||||||
|
y: self.y / rhs.y,
|
||||||
|
z: self.z / rhs.z,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: VectorComponent> ops::Div<T> for Vector3<T> {
|
||||||
|
type Output = Self;
|
||||||
|
fn div(self, rhs: T) -> Self::Output {
|
||||||
|
Vector3 {
|
||||||
|
x: self.x / rhs,
|
||||||
|
y: self.y / rhs,
|
||||||
|
z: self.z / rhs,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
use bevy::prelude::*;
|
||||||
|
|
||||||
|
use super::Vector3;
|
||||||
|
|
||||||
|
pub type Vector3I = Vector3<i32>;
|
||||||
|
|
||||||
|
impl Vector3I {
|
||||||
|
pub const ZERO: Self = Self { x: 0, y: 0, z: 0 };
|
||||||
|
pub const ONE: Self = Self { x: 1, y: 1, z: 1 };
|
||||||
|
pub const UP: Self = Self { x: 0, y: 1, z: 0 };
|
||||||
|
pub const DOWN: Self = Self { x: 0, y: -1, z: 0 };
|
||||||
|
pub const LEFT: Self = Self { x: -1, y: 0, z: 0 };
|
||||||
|
pub const RIGHT: Self = Self { x: 1, y: 0, z: 0 };
|
||||||
|
pub const FORWARD: Self = Self { x: 0, y: 0, z: -1 };
|
||||||
|
pub const BACK: Self = Self { x: 0, y: 0, z: 1 };
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Vec3> for Vector3I {
|
||||||
|
fn from(vec: Vec3) -> Self {
|
||||||
|
Self {
|
||||||
|
x: vec.x as i32,
|
||||||
|
y: vec.y as i32,
|
||||||
|
z: vec.y as i32,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Vector3I> for Vec3 {
|
||||||
|
fn from(vec: Vector3I) -> Self {
|
||||||
|
Vec3 {
|
||||||
|
x: vec.x as f32,
|
||||||
|
y: vec.y as f32,
|
||||||
|
z: vec.z as f32,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue