nightshade 0.57.0

A cross-platform data-oriented game engine.
Documentation
use serde::{Deserialize, Serialize};

use crate::assets::asset::AssetUuid;

#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
pub enum SceneBodyType {
    #[default]
    Static,
    Dynamic,
    KinematicPositionBased,
    KinematicVelocityBased,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ScenePhysics {
    pub body_type: SceneBodyType,
    pub collider: SceneCollider,
    #[serde(default = "default_friction")]
    pub friction: f32,
    #[serde(default = "default_restitution")]
    pub restitution: f32,
    #[serde(default)]
    pub mass: Option<f32>,
    #[serde(default)]
    pub is_sensor: bool,
    #[serde(default = "default_collision_membership")]
    pub collision_membership: u32,
    #[serde(default = "default_collision_filter")]
    pub collision_filter: u32,
    #[serde(default = "default_solver_membership")]
    pub solver_membership: u32,
    #[serde(default = "default_solver_filter")]
    pub solver_filter: u32,
    #[serde(default)]
    /// Locked-axis bits. The physics plugin owns what they mean; the record
    /// only carries them.
    pub locked_axes: u8,
    #[serde(default)]
    pub linvel: [f32; 3],
    #[serde(default)]
    pub angvel: [f32; 3],
}

fn default_collision_membership() -> u32 {
    0xFFFFFFFF
}

fn default_collision_filter() -> u32 {
    0xFFFFFFFF
}

fn default_solver_membership() -> u32 {
    0xFFFFFFFF
}

fn default_solver_filter() -> u32 {
    0xFFFFFFFF
}

fn default_friction() -> f32 {
    0.8
}

fn default_restitution() -> f32 {
    0.1
}

impl Default for ScenePhysics {
    fn default() -> Self {
        Self {
            body_type: SceneBodyType::Static,
            collider: SceneCollider::Cuboid {
                half_extents: [0.5, 0.5, 0.5],
            },
            friction: default_friction(),
            restitution: default_restitution(),
            mass: None,
            is_sensor: false,
            collision_membership: default_collision_membership(),
            collision_filter: default_collision_filter(),
            solver_membership: default_solver_membership(),
            solver_filter: default_solver_filter(),
            locked_axes: 0,
            linvel: [0.0, 0.0, 0.0],
            angvel: [0.0, 0.0, 0.0],
        }
    }
}

impl ScenePhysics {
    pub fn static_cuboid(half_extents: [f32; 3]) -> Self {
        Self {
            collider: SceneCollider::Cuboid { half_extents },
            ..Default::default()
        }
    }

    pub fn dynamic_ball(radius: f32, mass: f32) -> Self {
        Self {
            body_type: SceneBodyType::Dynamic,
            collider: SceneCollider::Ball { radius },
            friction: 0.7,
            restitution: 0.3,
            mass: Some(mass),
            ..Default::default()
        }
    }

    pub fn dynamic_cuboid(half_extents: [f32; 3], mass: f32) -> Self {
        Self {
            body_type: SceneBodyType::Dynamic,
            collider: SceneCollider::Cuboid { half_extents },
            friction: 0.7,
            restitution: 0.2,
            mass: Some(mass),
            ..Default::default()
        }
    }
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum SceneJoint {
    Fixed {
        parent_anchor: [f32; 3],
        child_anchor: [f32; 3],
    },
    Revolute {
        parent_anchor: [f32; 3],
        child_anchor: [f32; 3],
        axis: [f32; 3],
        #[serde(default)]
        limits: Option<[f32; 2]>,
    },
    Prismatic {
        parent_anchor: [f32; 3],
        child_anchor: [f32; 3],
        axis: [f32; 3],
        #[serde(default)]
        limits: Option<[f32; 2]>,
    },
    Spherical {
        parent_anchor: [f32; 3],
        child_anchor: [f32; 3],
    },
    Rope {
        parent_anchor: [f32; 3],
        child_anchor: [f32; 3],
        max_distance: f32,
    },
    Spring {
        parent_anchor: [f32; 3],
        child_anchor: [f32; 3],
        rest_length: f32,
        stiffness: f32,
        damping: f32,
    },
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SceneJointConnection {
    pub parent_entity: AssetUuid,
    pub child_entity: AssetUuid,
    pub joint: SceneJoint,
    #[serde(default)]
    pub collisions_enabled: bool,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum SceneCollider {
    Cuboid {
        half_extents: [f32; 3],
    },
    Ball {
        radius: f32,
    },
    Cylinder {
        half_height: f32,
        radius: f32,
    },
    Capsule {
        half_height: f32,
        radius: f32,
    },
    TriMesh {
        vertices: Vec<[f32; 3]>,
        indices: Vec<[u32; 3]>,
    },
    ConvexHull {
        points: Vec<[f32; 3]>,
    },
    Cone {
        half_height: f32,
        radius: f32,
    },
    HeightField {
        nrows: usize,
        ncols: usize,
        heights: Vec<f32>,
        scale: [f32; 3],
    },
}