bevy_utilitarian 0.9.0

A collection of mostly maths, interpolation and geometric utilities that aim to make Bevy programmers happier
Documentation
use bevy::prelude::*;
use serde::{Deserialize, Serialize};
use std::f32::consts::PI;

pub trait RandValue {
    type Out;

    fn generate(&self) -> Self::Out;
    fn constant(value: Self::Out) -> Self;
}

#[derive(Debug, Clone, Copy, Reflect, Default, Serialize, Deserialize)]
pub struct RandF32 {
    pub min: f32,
    pub max: f32,
}

impl RandValue for RandF32 {
    type Out = f32;

    fn generate(&self) -> f32 {
        rand::random::<f32>() * (self.max - self.min) + self.min
    }

    fn constant(value: f32) -> Self {
        Self {
            min: value,
            max: value,
        }
    }
}

#[derive(Debug, Clone, Copy, Reflect, Serialize, Deserialize)]
pub struct RandVec3 {
    pub magnitude: RandF32,
    pub direction: Vec3,
    pub spread: f32,
}

impl RandValue for RandVec3 {
    type Out = Vec3;

    fn generate(&self) -> Vec3 {
        let dir = if self.spread > 0. {
            let spread_angle = rand::random::<f32>() * 2. * PI;
            let spread_radius = rand::random::<f32>() * self.spread;

            let local_dir = Quat::from_rotation_x(spread_angle)
                * Vec3::new(spread_radius.cos(), 0., spread_radius.sin());

            Quat::from_rotation_arc(Vec3::X, self.direction) * local_dir
        } else {
            self.direction.normalize_or_zero()
        };

        dir * self.magnitude.generate()
    }

    fn constant(value: Vec3) -> Self {
        Self {
            direction: value.normalize_or_zero(),
            magnitude: RandF32::constant(value.length()),
            spread: 0.,
        }
    }
}

impl Default for RandVec3 {
    fn default() -> Self {
        Self {
            magnitude: RandF32::default(),
            direction: Vec3::X,
            spread: 0.,
        }
    }
}