dreamwell-engine 1.0.0

Dreamwell pure-logic engine library — transforms, hierarchy, canon pipeline, spatial math, hashing, tile rules, validation, waymark schema, material/lighting descriptors. No SpacetimeDB dependency.
Documentation
use serde::{Deserialize, Serialize};

/// Force field kind — type of spatial force applied to particles.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum ForceFieldKind {
    Gravity,
    Drag,
    Damping,
    Directional,
    Radial,
    Attractor,
    Repulsor,
    Vortex,
    Orbital,
    Turbulence,
    CurlNoise,
    Wind,
    Buoyancy,
    CustomVectorField,
}

/// Force binding — references a force field by kind with strength and radius.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ForceBinding {
    pub kind: ForceFieldKind,
    pub strength: f32,
    pub radius: f32,
}

/// Force field descriptor — full definition of a spatial force field.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ForceFieldDescriptor {
    pub kind: ForceFieldKind,
    pub position: [f32; 3],
    pub direction: [f32; 3],
    pub strength: f32,
    pub radius: f32,
    pub falloff: f32,
    pub noise_frequency: f32,
    pub noise_amplitude: f32,
}

impl Default for ForceFieldDescriptor {
    fn default() -> Self {
        Self {
            kind: ForceFieldKind::Gravity,
            position: [0.0, 0.0, 0.0],
            direction: [0.0, -1.0, 0.0],
            strength: 9.81,
            radius: f32::MAX,
            falloff: 0.0,
            noise_frequency: 0.0,
            noise_amplitude: 0.0,
        }
    }
}

impl ForceFieldKind {
    pub const ALL: &[ForceFieldKind] = &[
        Self::Gravity,
        Self::Drag,
        Self::Damping,
        Self::Directional,
        Self::Radial,
        Self::Attractor,
        Self::Repulsor,
        Self::Vortex,
        Self::Orbital,
        Self::Turbulence,
        Self::CurlNoise,
        Self::Wind,
        Self::Buoyancy,
        Self::CustomVectorField,
    ];

    pub fn name(&self) -> &'static str {
        match self {
            Self::Gravity => "Gravity",
            Self::Drag => "Drag",
            Self::Damping => "Damping",
            Self::Directional => "Directional",
            Self::Radial => "Radial",
            Self::Attractor => "Attractor",
            Self::Repulsor => "Repulsor",
            Self::Vortex => "Vortex",
            Self::Orbital => "Orbital",
            Self::Turbulence => "Turbulence",
            Self::CurlNoise => "Curl Noise",
            Self::Wind => "Wind",
            Self::Buoyancy => "Buoyancy",
            Self::CustomVectorField => "Custom Vector Field",
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn force_field_kind_all() {
        assert_eq!(ForceFieldKind::ALL.len(), 14);
    }

    #[test]
    fn force_field_descriptor_default() {
        let f = ForceFieldDescriptor::default();
        assert_eq!(f.kind, ForceFieldKind::Gravity);
        assert_eq!(f.direction, [0.0, -1.0, 0.0]);
    }

    #[test]
    fn force_field_serde() {
        let f = ForceFieldDescriptor {
            kind: ForceFieldKind::Vortex,
            position: [1.0, 2.0, 3.0],
            direction: [0.0, 1.0, 0.0],
            strength: 5.0,
            radius: 10.0,
            falloff: 1.0,
            noise_frequency: 0.0,
            noise_amplitude: 0.0,
        };
        let json = serde_json::to_string(&f).unwrap();
        let restored: ForceFieldDescriptor = serde_json::from_str(&json).unwrap();
        assert_eq!(restored.kind, ForceFieldKind::Vortex);
    }
}