use super::{ship::figuredata::ShipSpec, Fluid, Ori};
use crate::{
comp::{body::ship::figuredata::VoxelCollider, inventory::item::armor::Friction},
consts::WATER_DENSITY,
terrain::Block,
uid::Uid,
util::Dir,
};
use hashbrown::HashMap;
use serde::{Deserialize, Serialize};
use specs::{Component, DerefFlaggedStorage, NullStorage, VecStorage};
use std::sync::Arc;
use vek::*;
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct Pos(pub Vec3<f32>);
impl Component for Pos {
type Storage = VecStorage<Self>;
}
#[derive(Copy, Clone, Default, Debug, PartialEq, Serialize, Deserialize)]
pub struct Vel(pub Vec3<f32>);
impl Vel {
pub fn zero() -> Self { Vel(Vec3::zero()) }
pub fn to_dir(&self) -> Dir { Dir::from_unnormalized(self.0).unwrap_or_default() }
}
impl Component for Vel {
type Storage = VecStorage<Self>;
}
#[derive(Copy, Clone, Debug)]
pub struct PosVelOriDefer {
pub pos: Option<Pos>,
pub vel: Option<Vel>,
pub ori: Option<Ori>,
}
impl Component for PosVelOriDefer {
type Storage = VecStorage<Self>;
}
#[derive(Copy, Clone, Default, Debug, PartialEq)]
pub struct PreviousPhysCache {
pub velocity: Vec3<f32>,
pub velocity_dt: Vec3<f32>,
pub in_fluid: Option<Fluid>,
pub center: Vec3<f32>,
pub collision_boundary: f32,
pub scale: f32,
pub scaled_radius: f32,
pub neighborhood_radius: f32,
pub origins: Option<(Vec2<f32>, Vec2<f32>)>,
pub pos: Option<Pos>,
pub ori: Quaternion<f32>,
}
impl Component for PreviousPhysCache {
type Storage = VecStorage<Self>;
}
#[derive(Copy, Clone, Default, Debug, PartialEq, Serialize, Deserialize)]
pub struct Scale(pub f32);
impl Component for Scale {
type Storage = DerefFlaggedStorage<Self, VecStorage<Self>>;
}
#[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
pub struct Mass(pub f32);
impl Default for Mass {
fn default() -> Mass { Mass(1.0) }
}
impl Component for Mass {
type Storage = DerefFlaggedStorage<Self, VecStorage<Self>>;
}
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct Density(pub f32);
impl Default for Density {
fn default() -> Density { Density(WATER_DENSITY) }
}
impl Component for Density {
type Storage = DerefFlaggedStorage<Self, VecStorage<Self>>;
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum Collider {
Voxel {
id: String,
},
Volume(Arc<VoxelCollider>),
CapsulePrism {
p0: Vec2<f32>,
p1: Vec2<f32>,
radius: f32,
z_min: f32,
z_max: f32,
},
Point,
}
impl Collider {
pub fn is_voxel(&self) -> bool { matches!(self, Collider::Voxel { .. } | Collider::Volume(_)) }
pub fn get_vol<'a>(&'a self, ship_spec: &'a ShipSpec) -> Option<&'a VoxelCollider> {
match self {
Collider::Voxel { id } => ship_spec.colliders.get(id),
Collider::Volume(vol) => Some(&**vol),
_ => None,
}
}
pub fn bounding_radius(&self) -> f32 {
match self {
Collider::Voxel { .. } | Collider::Volume(_) => 1.0,
Collider::CapsulePrism { radius, p0, p1, .. } => {
let a = p0.distance(*p1);
a / 2.0 + *radius
},
Collider::Point => 0.0,
}
}
pub fn get_height(&self) -> f32 {
let (z_min, z_max) = self.get_z_limits(1.0);
z_max - z_min
}
pub fn get_z_limits(&self, modifier: f32) -> (f32, f32) {
match self {
Collider::Voxel { .. } | Collider::Volume(_) => (0.0, 2.0),
Collider::CapsulePrism { z_min, z_max, .. } => (*z_min * modifier, *z_max * modifier),
Collider::Point => (0.0, 0.0),
}
}
}
impl Component for Collider {
type Storage = DerefFlaggedStorage<Self, VecStorage<Self>>;
}
#[derive(Copy, Clone, Default, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct Sticky;
impl Component for Sticky {
type Storage = DerefFlaggedStorage<Self, NullStorage<Self>>;
}
#[derive(Copy, Clone, Default, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct Immovable;
impl Component for Immovable {
type Storage = DerefFlaggedStorage<Self, NullStorage<Self>>;
}
#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)]
pub struct PhysicsState {
pub on_ground: Option<Block>,
pub on_ceiling: bool,
pub on_wall: Option<Vec3<f32>>,
pub touch_entities: HashMap<Uid, Vec3<f32>>,
pub in_fluid: Option<Fluid>,
pub ground_vel: Vec3<f32>,
pub footwear: Friction,
pub skating_last_height: f32,
pub skating_active: bool,
}
impl PhysicsState {
pub fn reset(&mut self) {
let mut touch_entities = std::mem::take(&mut self.touch_entities);
touch_entities.clear();
*self = Self {
touch_entities,
ground_vel: self.ground_vel, ..Self::default()
}
}
pub fn on_surface(&self) -> Option<Vec3<f32>> {
self.on_ground
.map(|_| -Vec3::unit_z())
.or_else(|| self.on_ceiling.then_some(Vec3::unit_z()))
.or(self.on_wall)
}
pub fn in_liquid(&self) -> Option<f32> { self.in_fluid.and_then(|fluid| fluid.depth()) }
}
impl Component for PhysicsState {
type Storage = VecStorage<Self>;
}
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
pub struct ForceUpdate {
flag: bool,
counter: u64,
}
impl ForceUpdate {
pub fn forced() -> Self {
Self {
flag: true,
counter: 0,
}
}
pub fn update(&mut self) {
self.flag = true;
self.counter = self.counter.wrapping_add(1);
}
pub fn clear(&mut self) { self.flag = false; }
pub fn is_forced(&self) -> bool { self.flag }
pub fn counter(&self) -> u64 { self.counter }
}
impl Component for ForceUpdate {
type Storage = VecStorage<Self>;
}