colliders
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
//! BoxCollider component wrapper
|
||||
|
||||
use crate::types::{yaml_helpers, ComponentContext, UnityComponent, Vector3};
|
||||
use crate::types::unity_types::Collider;
|
||||
use sparsey::Entity;
|
||||
|
||||
/// A BoxCollider component
|
||||
@@ -9,28 +10,39 @@ use sparsey::Entity;
|
||||
/// It defines a box-shaped volume that can be used for collision detection.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct BoxCollider {
|
||||
size: Option<Vector3>,
|
||||
center: Option<Vector3>,
|
||||
size: Vector3,
|
||||
center: Vector3,
|
||||
collider: Collider,
|
||||
}
|
||||
|
||||
impl BoxCollider {
|
||||
/// Get the size of the box collider
|
||||
pub fn size(&self) -> Option<&Vector3> {
|
||||
self.size.as_ref()
|
||||
pub fn size(&self) -> &Vector3 {
|
||||
&self.size
|
||||
}
|
||||
|
||||
/// Get the center offset of the box collider
|
||||
pub fn center(&self) -> Option<&Vector3> {
|
||||
self.center.as_ref()
|
||||
pub fn center(&self) -> &Vector3 {
|
||||
&self.center
|
||||
}
|
||||
|
||||
/// Get the base collider component
|
||||
pub fn collider(&self) -> &Collider {
|
||||
&self.collider
|
||||
}
|
||||
|
||||
/// Get mutable access to the base collider component
|
||||
pub fn collider_mut(&mut self) -> &mut Collider {
|
||||
&mut self.collider
|
||||
}
|
||||
|
||||
/// Set the size of the box collider
|
||||
pub fn set_size(&mut self, size: Option<Vector3>) {
|
||||
pub fn set_size(&mut self, size: Vector3) {
|
||||
self.size = size;
|
||||
}
|
||||
|
||||
/// Set the center offset of the box collider
|
||||
pub fn set_center(&mut self, center: Option<Vector3>) {
|
||||
pub fn set_center(&mut self, center: Vector3) {
|
||||
self.center = center;
|
||||
}
|
||||
}
|
||||
@@ -39,17 +51,23 @@ impl UnityComponent for BoxCollider {
|
||||
/// Parse a BoxCollider from YAML
|
||||
///
|
||||
/// Note: Caller is responsible for ensuring this is called on the correct document type.
|
||||
fn parse(yaml: &serde_yaml::Mapping, _ctx: &ComponentContext) -> Option<Self> {
|
||||
let size = yaml_helpers::get_vector3(yaml, "m_Size");
|
||||
let center = yaml_helpers::get_vector3(yaml, "m_Center");
|
||||
fn parse(yaml: &serde_yaml::Mapping, ctx: &ComponentContext) -> Option<Self> {
|
||||
let size = yaml_helpers::get_vector3(yaml, "m_Size").unwrap_or_default();
|
||||
let center = yaml_helpers::get_vector3(yaml, "m_Center").unwrap_or_default();
|
||||
|
||||
Some(Self { size, center })
|
||||
// Parse the base collider component (layer masks)
|
||||
let collider = Collider::parse(yaml, ctx)?;
|
||||
|
||||
Some(Self { size, center, collider })
|
||||
}
|
||||
}
|
||||
|
||||
impl crate::types::EcsInsertable for BoxCollider {
|
||||
fn insert_into_world(self, world: &mut sparsey::World, entity: Entity) {
|
||||
world.insert(entity, (self,));
|
||||
// Insert both the BoxCollider and the base Collider component
|
||||
// This allows querying for either specific collider types or all colliders
|
||||
let collider = self.collider.clone();
|
||||
world.insert(entity, (self, collider));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,6 +79,9 @@ inventory::submit! {
|
||||
parse_and_insert: |yaml, ctx, world, entity| {
|
||||
<BoxCollider as crate::types::EcsInsertable>::parse_and_insert(yaml, ctx, world, entity)
|
||||
},
|
||||
register: |builder| builder.register::<BoxCollider>(),
|
||||
register: |builder| {
|
||||
// Register both BoxCollider and the base Collider component
|
||||
builder.register::<BoxCollider>().register::<Collider>()
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
117
unity-parser/src/types/unity_types/capsule_collider.rs
Normal file
117
unity-parser/src/types/unity_types/capsule_collider.rs
Normal file
@@ -0,0 +1,117 @@
|
||||
//! CapsuleCollider component wrapper
|
||||
|
||||
use crate::types::{yaml_helpers, ComponentContext, UnityComponent, Vector3};
|
||||
use crate::types::unity_types::Collider;
|
||||
use sparsey::Entity;
|
||||
|
||||
/// A CapsuleCollider component
|
||||
///
|
||||
/// CapsuleCollider is a basic collision primitive in the shape of a capsule.
|
||||
/// It defines a capsule-shaped volume (cylinder with hemispherical ends) that can be used for collision detection.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct CapsuleCollider {
|
||||
radius: f32,
|
||||
height: f32,
|
||||
center: Vector3,
|
||||
direction: i32, // 0 = X-axis, 1 = Y-axis, 2 = Z-axis
|
||||
collider: Collider,
|
||||
}
|
||||
|
||||
impl CapsuleCollider {
|
||||
/// Get the radius of the capsule collider
|
||||
pub fn radius(&self) -> f32 {
|
||||
self.radius
|
||||
}
|
||||
|
||||
/// Get the height of the capsule collider
|
||||
pub fn height(&self) -> f32 {
|
||||
self.height
|
||||
}
|
||||
|
||||
/// Get the center offset of the capsule collider
|
||||
pub fn center(&self) -> &Vector3 {
|
||||
&self.center
|
||||
}
|
||||
|
||||
/// Get the direction axis of the capsule (0=X, 1=Y, 2=Z)
|
||||
pub fn direction(&self) -> i32 {
|
||||
self.direction
|
||||
}
|
||||
|
||||
/// Get the base collider component
|
||||
pub fn collider(&self) -> &Collider {
|
||||
&self.collider
|
||||
}
|
||||
|
||||
/// Get mutable access to the base collider component
|
||||
pub fn collider_mut(&mut self) -> &mut Collider {
|
||||
&mut self.collider
|
||||
}
|
||||
|
||||
/// Set the radius of the capsule collider
|
||||
pub fn set_radius(&mut self, radius: f32) {
|
||||
self.radius = radius;
|
||||
}
|
||||
|
||||
/// Set the height of the capsule collider
|
||||
pub fn set_height(&mut self, height: f32) {
|
||||
self.height = height;
|
||||
}
|
||||
|
||||
/// Set the center offset of the capsule collider
|
||||
pub fn set_center(&mut self, center: Vector3) {
|
||||
self.center = center;
|
||||
}
|
||||
|
||||
/// Set the direction axis (0=X, 1=Y, 2=Z)
|
||||
pub fn set_direction(&mut self, direction: i32) {
|
||||
self.direction = direction;
|
||||
}
|
||||
}
|
||||
|
||||
impl UnityComponent for CapsuleCollider {
|
||||
/// Parse a CapsuleCollider from YAML
|
||||
///
|
||||
/// Note: Caller is responsible for ensuring this is called on the correct document type.
|
||||
fn parse(yaml: &serde_yaml::Mapping, ctx: &ComponentContext) -> Option<Self> {
|
||||
let radius = yaml_helpers::get_f64(yaml, "m_Radius").unwrap_or(0.0) as f32;
|
||||
let height = yaml_helpers::get_f64(yaml, "m_Height").unwrap_or(0.0) as f32;
|
||||
let center = yaml_helpers::get_vector3(yaml, "m_Center").unwrap_or_default();
|
||||
let direction = yaml_helpers::get_i64(yaml, "m_Direction").unwrap_or(0) as i32;
|
||||
|
||||
// Parse the base collider component (layer masks)
|
||||
let collider = Collider::parse(yaml, ctx)?;
|
||||
|
||||
Some(Self {
|
||||
radius,
|
||||
height,
|
||||
center,
|
||||
direction,
|
||||
collider,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl crate::types::EcsInsertable for CapsuleCollider {
|
||||
fn insert_into_world(self, world: &mut sparsey::World, entity: Entity) {
|
||||
// Insert both the CapsuleCollider and the base Collider component
|
||||
// This allows querying for either specific collider types or all colliders
|
||||
let collider = self.collider.clone();
|
||||
world.insert(entity, (self, collider));
|
||||
}
|
||||
}
|
||||
|
||||
// Register component with inventory
|
||||
inventory::submit! {
|
||||
crate::types::ComponentRegistration {
|
||||
type_id: 136, // Unity type ID for CapsuleCollider
|
||||
class_name: "CapsuleCollider",
|
||||
parse_and_insert: |yaml, ctx, world, entity| {
|
||||
<CapsuleCollider as crate::types::EcsInsertable>::parse_and_insert(yaml, ctx, world, entity)
|
||||
},
|
||||
register: |builder| {
|
||||
// Register both CapsuleCollider and the base Collider component
|
||||
builder.register::<CapsuleCollider>().register::<Collider>()
|
||||
},
|
||||
}
|
||||
}
|
||||
87
unity-parser/src/types/unity_types/collider.rs
Normal file
87
unity-parser/src/types/unity_types/collider.rs
Normal file
@@ -0,0 +1,87 @@
|
||||
//! Collider component wrapper
|
||||
|
||||
use crate::types::{ComponentContext, UnityComponent};
|
||||
use serde_yaml::{Mapping, Value};
|
||||
use sparsey::Entity;
|
||||
|
||||
/// A Collider component
|
||||
///
|
||||
/// Collider is the base class for collision primitives.
|
||||
/// Contains layer mask information for collision filtering.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Collider {
|
||||
/// Layer mask for which layers this collider can collide with
|
||||
include_layers: u32,
|
||||
/// Layer mask for which layers this collider should ignore
|
||||
exclude_layers: u32,
|
||||
}
|
||||
|
||||
impl Collider {
|
||||
/// Get the include layers bitset
|
||||
pub fn include_layers(&self) -> u32 {
|
||||
self.include_layers
|
||||
}
|
||||
|
||||
/// Get the exclude layers bitset
|
||||
pub fn exclude_layers(&self) -> u32 {
|
||||
self.exclude_layers
|
||||
}
|
||||
|
||||
/// Set the include layers bitset
|
||||
pub fn set_include_layers(&mut self, layers: u32) {
|
||||
self.include_layers = layers;
|
||||
}
|
||||
|
||||
/// Set the exclude layers bitset
|
||||
pub fn set_exclude_layers(&mut self, layers: u32) {
|
||||
self.exclude_layers = layers;
|
||||
}
|
||||
|
||||
/// Check if the collider can interact with a specific layer (0-31)
|
||||
pub fn can_collide_with_layer(&self, layer: u8) -> bool {
|
||||
if layer >= 32 {
|
||||
return false;
|
||||
}
|
||||
let layer_bit = 1u32 << layer;
|
||||
(self.include_layers & layer_bit) != 0 && (self.exclude_layers & layer_bit) == 0
|
||||
}
|
||||
}
|
||||
|
||||
/// Helper function to parse Unity's layer bitset structure
|
||||
///
|
||||
/// Unity stores layer masks as:
|
||||
/// ```yaml
|
||||
/// m_IncludeLayers:
|
||||
/// serializedVersion: 2
|
||||
/// m_Bits: 0
|
||||
/// ```
|
||||
fn parse_layer_bitset(map: &Mapping, key: &str) -> Option<u32> {
|
||||
let obj = map
|
||||
.get(&Value::String(key.to_string()))
|
||||
.and_then(|v| v.as_mapping())?;
|
||||
|
||||
obj.get(&Value::String("m_Bits".to_string()))
|
||||
.and_then(|v| v.as_u64())
|
||||
.map(|bits| bits as u32)
|
||||
}
|
||||
|
||||
impl UnityComponent for Collider {
|
||||
/// Parse a Collider from YAML
|
||||
///
|
||||
/// Note: Caller is responsible for ensuring this is called on the correct document type.
|
||||
fn parse(yaml: &Mapping, _ctx: &ComponentContext) -> Option<Self> {
|
||||
let include_layers = parse_layer_bitset(yaml, "m_IncludeLayers").unwrap_or(0);
|
||||
let exclude_layers = parse_layer_bitset(yaml, "m_ExcludeLayers").unwrap_or(0);
|
||||
|
||||
Some(Self {
|
||||
include_layers,
|
||||
exclude_layers,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl crate::types::EcsInsertable for Collider {
|
||||
fn insert_into_world(self, world: &mut sparsey::World, entity: Entity) {
|
||||
world.insert(entity, (self,));
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,19 @@
|
||||
//! Unity-specific types (GameObjects, Transforms, PrefabInstances)
|
||||
|
||||
pub mod box_collider;
|
||||
pub mod capsule_collider;
|
||||
pub mod collider;
|
||||
pub mod game_object;
|
||||
pub mod mesh_filter;
|
||||
pub mod mesh_renderer;
|
||||
pub mod prefab_instance;
|
||||
pub mod renderer;
|
||||
pub mod sphere_collider;
|
||||
pub mod transform;
|
||||
|
||||
pub use box_collider::BoxCollider;
|
||||
pub use capsule_collider::CapsuleCollider;
|
||||
pub use collider::Collider;
|
||||
pub use game_object::GameObject;
|
||||
pub use mesh_filter::MeshFilter;
|
||||
pub use mesh_renderer::MeshRenderer;
|
||||
@@ -16,4 +21,5 @@ pub use prefab_instance::{
|
||||
PrefabInstance, PrefabInstanceComponent, PrefabModification, PrefabResolver,
|
||||
};
|
||||
pub use renderer::Renderer;
|
||||
pub use sphere_collider::SphereCollider;
|
||||
pub use transform::{RectTransform, Transform};
|
||||
|
||||
91
unity-parser/src/types/unity_types/sphere_collider.rs
Normal file
91
unity-parser/src/types/unity_types/sphere_collider.rs
Normal file
@@ -0,0 +1,91 @@
|
||||
//! SphereCollider component wrapper
|
||||
|
||||
use crate::types::{yaml_helpers, ComponentContext, UnityComponent, Vector3};
|
||||
use crate::types::unity_types::Collider;
|
||||
use sparsey::Entity;
|
||||
|
||||
/// A SphereCollider component
|
||||
///
|
||||
/// SphereCollider is a basic collision primitive in the shape of a sphere.
|
||||
/// It defines a sphere-shaped volume that can be used for collision detection.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct SphereCollider {
|
||||
radius: f32,
|
||||
center: Vector3,
|
||||
collider: Collider,
|
||||
}
|
||||
|
||||
impl SphereCollider {
|
||||
/// Get the radius of the sphere collider
|
||||
pub fn radius(&self) -> f32 {
|
||||
self.radius
|
||||
}
|
||||
|
||||
/// Get the center offset of the sphere collider
|
||||
pub fn center(&self) -> &Vector3 {
|
||||
&self.center
|
||||
}
|
||||
|
||||
/// Get the base collider component
|
||||
pub fn collider(&self) -> &Collider {
|
||||
&self.collider
|
||||
}
|
||||
|
||||
/// Get mutable access to the base collider component
|
||||
pub fn collider_mut(&mut self) -> &mut Collider {
|
||||
&mut self.collider
|
||||
}
|
||||
|
||||
/// Set the radius of the sphere collider
|
||||
pub fn set_radius(&mut self, radius: f32) {
|
||||
self.radius = radius;
|
||||
}
|
||||
|
||||
/// Set the center offset of the sphere collider
|
||||
pub fn set_center(&mut self, center: Vector3) {
|
||||
self.center = center;
|
||||
}
|
||||
}
|
||||
|
||||
impl UnityComponent for SphereCollider {
|
||||
/// Parse a SphereCollider from YAML
|
||||
///
|
||||
/// Note: Caller is responsible for ensuring this is called on the correct document type.
|
||||
fn parse(yaml: &serde_yaml::Mapping, ctx: &ComponentContext) -> Option<Self> {
|
||||
let radius = yaml_helpers::get_f64(yaml, "m_Radius").unwrap_or(0.0) as f32;
|
||||
let center = yaml_helpers::get_vector3(yaml, "m_Center").unwrap_or_default();
|
||||
|
||||
// Parse the base collider component (layer masks)
|
||||
let collider = Collider::parse(yaml, ctx)?;
|
||||
|
||||
Some(Self {
|
||||
radius,
|
||||
center,
|
||||
collider,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl crate::types::EcsInsertable for SphereCollider {
|
||||
fn insert_into_world(self, world: &mut sparsey::World, entity: Entity) {
|
||||
// Insert both the SphereCollider and the base Collider component
|
||||
// This allows querying for either specific collider types or all colliders
|
||||
let collider = self.collider.clone();
|
||||
world.insert(entity, (self, collider));
|
||||
}
|
||||
}
|
||||
|
||||
// Register component with inventory
|
||||
inventory::submit! {
|
||||
crate::types::ComponentRegistration {
|
||||
type_id: 135, // Unity type ID for SphereCollider
|
||||
class_name: "SphereCollider",
|
||||
parse_and_insert: |yaml, ctx, world, entity| {
|
||||
<SphereCollider as crate::types::EcsInsertable>::parse_and_insert(yaml, ctx, world, entity)
|
||||
},
|
||||
register: |builder| {
|
||||
// Register both SphereCollider and the base Collider component
|
||||
builder.register::<SphereCollider>().register::<Collider>()
|
||||
},
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user