use std::ops::{Mul, MulAssign};
use bevy::ecs::component::Component;
use bevy::math::prelude::*;
use bevy::reflect::prelude::*;
use duplicate::duplicate_item;
use crate::utils::NearZero;
#[derive(Debug, Component, Copy, Clone, PartialEq, Default, Reflect)]
pub struct Velocity {
pub linear: Vec3,
pub angular: AxisAngle,
}
#[derive(Debug, Component, Copy, Clone, PartialEq, Default, Reflect)]
pub struct Acceleration {
pub linear: Vec3,
pub angular: AxisAngle,
}
#[derive(Debug, Copy, Clone, PartialEq, Default, Reflect, Component)]
pub struct Damping {
pub linear: f32,
pub angular: f32,
}
#[derive(Debug, Copy, Clone, PartialEq, Default, Reflect)]
pub struct AxisAngle(Vec3);
impl Velocity {
#[must_use]
pub fn from_linear(linear: Vec3) -> Self {
Self {
linear,
angular: AxisAngle::default(),
}
}
#[must_use]
pub fn from_angular(angular: AxisAngle) -> Self {
Self {
angular,
linear: Vec3::ZERO,
}
}
#[must_use]
pub fn with_linear(mut self, linear: Vec3) -> Self {
self.linear = linear;
self
}
#[must_use]
pub fn with_angular(mut self, angular: AxisAngle) -> Self {
self.angular = angular;
self
}
}
impl Acceleration {
#[must_use]
pub fn from_linear(linear: Vec3) -> Self {
Self {
linear,
angular: AxisAngle::default(),
}
}
#[must_use]
pub fn from_angular(angular: AxisAngle) -> Self {
Self {
angular,
linear: Vec3::ZERO,
}
}
#[must_use]
pub fn with_linear(mut self, linear: Vec3) -> Self {
self.linear = linear;
self
}
#[must_use]
pub fn with_angular(mut self, angular: AxisAngle) -> Self {
self.angular = angular;
self
}
}
impl Damping {
#[must_use]
pub fn from_linear(linear: f32) -> Self {
Self {
linear,
angular: 0.0,
}
}
#[must_use]
pub fn from_angular(angular: f32) -> Self {
Self {
angular,
linear: 0.0,
}
}
#[must_use]
pub fn with_linear(mut self, linear: f32) -> Self {
self.linear = linear;
self
}
#[must_use]
pub fn with_angular(mut self, angular: f32) -> Self {
self.angular = angular;
self
}
}
#[duplicate_item(
Velocity;
[ Velocity ];
[ Acceleration ];
)]
impl From<Vec2> for Velocity {
fn from(v: Vec2) -> Self {
Self::from_linear(v.extend(0.0))
}
}
#[duplicate_item(
Velocity;
[ Velocity ];
[ Acceleration ];
)]
impl From<Vec3> for Velocity {
fn from(linear: Vec3) -> Self {
Self::from_linear(linear)
}
}
#[duplicate_item(
Velocity;
[ Velocity ];
[ Acceleration ];
)]
impl From<Velocity> for Vec3 {
fn from(Velocity { linear, .. }: Velocity) -> Self {
linear
}
}
#[duplicate_item(
Velocity;
[ Velocity ];
[ Acceleration ];
)]
impl From<AxisAngle> for Velocity {
fn from(angular: AxisAngle) -> Self {
Self::from_angular(angular)
}
}
#[duplicate_item(
Velocity;
[ Velocity ];
[ Acceleration ];
)]
impl From<Quat> for Velocity {
fn from(quat: Quat) -> Self {
Self::from_angular(quat.into())
}
}
#[duplicate_item(
Velocity;
[ Velocity ];
[ Acceleration ];
)]
impl From<Velocity> for AxisAngle {
fn from(Velocity { angular, .. }: Velocity) -> Self {
angular
}
}
#[duplicate_item(
Velocity;
[ Velocity ];
[ Acceleration ];
)]
impl From<Velocity> for Quat {
fn from(Velocity { angular, .. }: Velocity) -> Self {
angular.into()
}
}
impl From<Vec3> for AxisAngle {
fn from(v: Vec3) -> Self {
Self(v)
}
}
impl From<AxisAngle> for Vec3 {
fn from(AxisAngle(v): AxisAngle) -> Self {
v
}
}
impl From<AxisAngle> for f32 {
fn from(AxisAngle(v): AxisAngle) -> Self {
v.length()
}
}
#[duplicate_item(
Velocity;
[ Velocity ];
[ Acceleration ];
)]
impl NearZero for Velocity {
fn is_near_zero(self) -> bool {
self.linear.is_near_zero() && self.angular.is_near_zero()
}
}
impl MulAssign<f32> for AxisAngle {
fn mul_assign(&mut self, rhs: f32) {
self.0 = self.0 * rhs;
}
}
impl Mul<f32> for AxisAngle {
type Output = Self;
fn mul(mut self, rhs: f32) -> Self::Output {
self *= rhs;
self
}
}
impl Mul<AxisAngle> for f32 {
type Output = AxisAngle;
fn mul(self, mut rhs: AxisAngle) -> Self::Output {
rhs *= self;
rhs
}
}
impl AxisAngle {
#[inline]
#[must_use]
pub fn new(axis: Vec3, angle: f32) -> Self {
Self(axis.normalize() * angle)
}
#[inline]
#[must_use]
pub fn angle_squared(self) -> f32 {
self.0.length_squared()
}
#[inline]
#[must_use]
pub fn angle(self) -> f32 {
self.0.length()
}
#[inline]
#[must_use]
pub fn axis(self) -> Vec3 {
self.0
}
}
impl NearZero for AxisAngle {
fn is_near_zero(self) -> bool {
self.0.is_near_zero()
}
}
impl From<Quat> for AxisAngle {
fn from(quat: Quat) -> Self {
let length = quat.length();
let (axis, angle) = quat.to_axis_angle();
Self(axis.normalize() * (angle * length))
}
}
impl From<AxisAngle> for Quat {
fn from(axis_angle: AxisAngle) -> Self {
if axis_angle.is_near_zero() {
Quat::IDENTITY
} else {
let angle = axis_angle.0.length();
Quat::from_axis_angle(axis_angle.0 / angle, angle)
}
}
}