bevy_utilitarian/randomized_values/
mod.rs

1use bevy::prelude::*;
2use serde::{Deserialize, Serialize};
3use std::f32::consts::PI;
4
5pub trait RandValue {
6    type Out;
7
8    fn generate(&self) -> Self::Out;
9    fn constant(value: Self::Out) -> Self;
10}
11
12#[derive(Debug, Clone, Copy, Reflect, Default, Serialize, Deserialize)]
13pub struct RandF32 {
14    pub min: f32,
15    pub max: f32,
16}
17
18impl RandValue for RandF32 {
19    type Out = f32;
20
21    fn generate(&self) -> f32 {
22        rand::random::<f32>() * (self.max - self.min) + self.min
23    }
24
25    fn constant(value: f32) -> Self {
26        Self {
27            min: value,
28            max: value,
29        }
30    }
31}
32
33#[derive(Debug, Clone, Copy, Reflect, Serialize, Deserialize)]
34pub struct RandVec3 {
35    pub magnitude: RandF32,
36    pub direction: Vec3,
37    pub spread: f32,
38}
39
40impl RandValue for RandVec3 {
41    type Out = Vec3;
42
43    fn generate(&self) -> Vec3 {
44        let dir = if self.spread > 0. {
45            let spread_angle = rand::random::<f32>() * 2. * PI;
46            let spread_radius = rand::random::<f32>() * self.spread;
47
48            let local_dir = Quat::from_rotation_x(spread_angle)
49                * Vec3::new(spread_radius.cos(), 0., spread_radius.sin());
50
51            Quat::from_rotation_arc(Vec3::X, self.direction) * local_dir
52        } else {
53            self.direction.normalize_or_zero()
54        };
55
56        dir * self.magnitude.generate()
57    }
58
59    fn constant(value: Vec3) -> Self {
60        Self {
61            direction: value.normalize_or_zero(),
62            magnitude: RandF32::constant(value.length()),
63            spread: 0.,
64        }
65    }
66}
67
68impl Default for RandVec3 {
69    fn default() -> Self {
70        Self {
71            magnitude: RandF32::default(),
72            direction: Vec3::X,
73            spread: 0.,
74        }
75    }
76}