use crate::ecs::light::components::Light;
use crate::ecs::material::components::Material;
use crate::ecs::physics::components::{ColliderComponent, ColliderShape, RigidBodyComponent};
use crate::ecs::physics::types::{InteractionGroups, LockedAxes, RigidBodyType};
use crate::ecs::world::components::{
BoundingVolume, Camera, LocalTransform, Name, RenderMesh, Visibility,
};
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum PrefabBodyType {
Dynamic,
Kinematic,
Static,
}
pub fn prefab_body_type_to_rigid_body_type(body_type: PrefabBodyType) -> RigidBodyType {
match body_type {
PrefabBodyType::Dynamic => RigidBodyType::Dynamic,
PrefabBodyType::Kinematic => RigidBodyType::KinematicPositionBased,
PrefabBodyType::Static => RigidBodyType::Fixed,
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PrefabRigidBody {
pub body_type: PrefabBodyType,
pub mass: f32,
}
impl Default for PrefabRigidBody {
fn default() -> Self {
Self {
body_type: PrefabBodyType::Dynamic,
mass: 1.0,
}
}
}
pub fn prefab_rigid_body_to_component(prefab: &PrefabRigidBody) -> RigidBodyComponent {
RigidBodyComponent {
handle: None,
body_type: prefab_body_type_to_rigid_body_type(prefab.body_type),
translation: [0.0, 0.0, 0.0],
rotation: [0.0, 0.0, 0.0, 1.0],
linvel: [0.0, 0.0, 0.0],
angvel: [0.0, 0.0, 0.0],
mass: prefab.mass,
linear_damping: 0.0,
angular_damping: 0.0,
gravity_scale: 1.0,
locked_axes: LockedAxes::empty(),
ccd_enabled: false,
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PrefabCollider {
pub shape: ColliderShape,
pub friction: f32,
pub restitution: f32,
pub density: f32,
pub is_sensor: bool,
}
impl Default for PrefabCollider {
fn default() -> Self {
Self {
shape: ColliderShape::Cuboid {
hx: 0.5,
hy: 0.5,
hz: 0.5,
},
friction: 0.5,
restitution: 0.0,
density: 1.0,
is_sensor: false,
}
}
}
pub fn prefab_collider_to_component(prefab: &PrefabCollider) -> ColliderComponent {
ColliderComponent {
handle: None,
shape: prefab.shape.clone(),
friction: prefab.friction,
restitution: prefab.restitution,
density: prefab.density,
is_sensor: prefab.is_sensor,
collision_groups: InteractionGroups::all(),
solver_groups: InteractionGroups::all(),
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Prefab {
pub name: String,
pub root_nodes: Vec<PrefabNode>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub material_variants: Vec<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PrefabMaterialVariant {
pub variant_names: Vec<String>,
pub material: Material,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PrefabNode {
pub local_transform: LocalTransform,
pub components: PrefabComponents,
pub children: Vec<PrefabNode>,
#[serde(skip_serializing_if = "Option::is_none")]
pub node_index: Option<usize>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct PrefabSource {
pub prefab_name: String,
pub source_path: Option<String>,
#[cfg(feature = "scene_graph")]
#[serde(default)]
pub source_uuid: Option<crate::ecs::scene::AssetUuid>,
}
pub fn prefab_source_new(prefab_name: impl Into<String>) -> PrefabSource {
PrefabSource {
prefab_name: prefab_name.into(),
source_path: None,
#[cfg(feature = "scene_graph")]
source_uuid: None,
}
}
pub fn prefab_source_with_path(
prefab_name: impl Into<String>,
source_path: impl Into<String>,
) -> PrefabSource {
PrefabSource {
prefab_name: prefab_name.into(),
source_path: Some(source_path.into()),
#[cfg(feature = "scene_graph")]
source_uuid: None,
}
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct PrefabComponents {
#[serde(skip_serializing_if = "Option::is_none")]
pub name: Option<Name>,
#[serde(skip_serializing_if = "Option::is_none")]
pub render_mesh: Option<RenderMesh>,
#[serde(skip_serializing_if = "Option::is_none")]
pub material: Option<Material>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub material_variants: Vec<PrefabMaterialVariant>,
#[serde(skip_serializing_if = "Option::is_none")]
pub camera: Option<Camera>,
#[serde(skip_serializing_if = "Option::is_none")]
pub light: Option<Light>,
#[serde(skip_serializing_if = "Option::is_none")]
pub visibility: Option<Visibility>,
#[serde(skip_serializing_if = "Option::is_none")]
pub bounding_volume: Option<BoundingVolume>,
#[serde(skip_serializing_if = "Option::is_none")]
pub rigid_body: Option<PrefabRigidBody>,
#[serde(skip_serializing_if = "Option::is_none")]
pub collider: Option<PrefabCollider>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub skin_index: Option<usize>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub instances: Vec<crate::ecs::world::components::LocalTransform>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct FieldOverride {
pub field_name: String,
pub value: crate::ecs::scene::TypedPayload,
}