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};

/// Collision detection mode.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum CollisionMode {
    None,
    Plane,
    TerrainHeightfield,
    DepthBuffer,
    SignedDistanceField,
    ProxyCollider,
    VoxelGrid,
}

/// Collision response behavior.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum CollisionResponse {
    Bounce,
    Slide,
    Stick,
    Die,
    Split,
    Shatter,
    Embed,
    Sleep,
    Promote,
    TriggerSubEmitter,
}

/// Collision policy for a particle system.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CollisionPolicy {
    pub mode: CollisionMode,
    pub response: CollisionResponse,
    pub restitution: f32,
    pub friction: f32,
    pub radius: f32,
    pub max_collisions: u32,
    pub material_response_table: Option<String>,
}

impl Default for CollisionPolicy {
    fn default() -> Self {
        Self {
            mode: CollisionMode::None,
            response: CollisionResponse::Bounce,
            restitution: 0.5,
            friction: 0.3,
            radius: 0.05,
            max_collisions: 4,
            material_response_table: None,
        }
    }
}

impl CollisionMode {
    pub const ALL: &[CollisionMode] = &[
        Self::None,
        Self::Plane,
        Self::TerrainHeightfield,
        Self::DepthBuffer,
        Self::SignedDistanceField,
        Self::ProxyCollider,
        Self::VoxelGrid,
    ];
}

impl CollisionResponse {
    pub const ALL: &[CollisionResponse] = &[
        Self::Bounce,
        Self::Slide,
        Self::Stick,
        Self::Die,
        Self::Split,
        Self::Shatter,
        Self::Embed,
        Self::Sleep,
        Self::Promote,
        Self::TriggerSubEmitter,
    ];
}

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

    #[test]
    fn collision_mode_all() {
        assert_eq!(CollisionMode::ALL.len(), 7);
    }

    #[test]
    fn collision_response_all() {
        assert_eq!(CollisionResponse::ALL.len(), 10);
    }

    #[test]
    fn collision_policy_default() {
        let p = CollisionPolicy::default();
        assert_eq!(p.mode, CollisionMode::None);
        assert_eq!(p.response, CollisionResponse::Bounce);
    }

    #[test]
    fn collision_policy_serde() {
        let p = CollisionPolicy {
            mode: CollisionMode::SignedDistanceField,
            response: CollisionResponse::Slide,
            restitution: 0.18,
            friction: 0.82,
            radius: 0.06,
            max_collisions: 12,
            material_response_table: Some("mat/stone".into()),
        };
        let json = serde_json::to_string(&p).unwrap();
        let restored: CollisionPolicy = serde_json::from_str(&json).unwrap();
        assert_eq!(restored.mode, CollisionMode::SignedDistanceField);
        assert_eq!(restored.max_collisions, 12);
    }
}