colliders
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
//! BoxCollider component wrapper
|
//! BoxCollider component wrapper
|
||||||
|
|
||||||
use crate::types::{yaml_helpers, ComponentContext, UnityComponent, Vector3};
|
use crate::types::{yaml_helpers, ComponentContext, UnityComponent, Vector3};
|
||||||
|
use crate::types::unity_types::Collider;
|
||||||
use sparsey::Entity;
|
use sparsey::Entity;
|
||||||
|
|
||||||
/// A BoxCollider component
|
/// A BoxCollider component
|
||||||
@@ -9,28 +10,39 @@ use sparsey::Entity;
|
|||||||
/// It defines a box-shaped volume that can be used for collision detection.
|
/// It defines a box-shaped volume that can be used for collision detection.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct BoxCollider {
|
pub struct BoxCollider {
|
||||||
size: Option<Vector3>,
|
size: Vector3,
|
||||||
center: Option<Vector3>,
|
center: Vector3,
|
||||||
|
collider: Collider,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BoxCollider {
|
impl BoxCollider {
|
||||||
/// Get the size of the box collider
|
/// Get the size of the box collider
|
||||||
pub fn size(&self) -> Option<&Vector3> {
|
pub fn size(&self) -> &Vector3 {
|
||||||
self.size.as_ref()
|
&self.size
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the center offset of the box collider
|
/// Get the center offset of the box collider
|
||||||
pub fn center(&self) -> Option<&Vector3> {
|
pub fn center(&self) -> &Vector3 {
|
||||||
self.center.as_ref()
|
&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
|
/// 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;
|
self.size = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the center offset of the box collider
|
/// 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;
|
self.center = center;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -39,17 +51,23 @@ impl UnityComponent for BoxCollider {
|
|||||||
/// Parse a BoxCollider from YAML
|
/// Parse a BoxCollider from YAML
|
||||||
///
|
///
|
||||||
/// Note: Caller is responsible for ensuring this is called on the correct document type.
|
/// Note: Caller is responsible for ensuring this is called on the correct document type.
|
||||||
fn parse(yaml: &serde_yaml::Mapping, _ctx: &ComponentContext) -> Option<Self> {
|
fn parse(yaml: &serde_yaml::Mapping, ctx: &ComponentContext) -> Option<Self> {
|
||||||
let size = yaml_helpers::get_vector3(yaml, "m_Size");
|
let size = yaml_helpers::get_vector3(yaml, "m_Size").unwrap_or_default();
|
||||||
let center = yaml_helpers::get_vector3(yaml, "m_Center");
|
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 {
|
impl crate::types::EcsInsertable for BoxCollider {
|
||||||
fn insert_into_world(self, world: &mut sparsey::World, entity: Entity) {
|
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| {
|
parse_and_insert: |yaml, ctx, world, entity| {
|
||||||
<BoxCollider as crate::types::EcsInsertable>::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)
|
//! Unity-specific types (GameObjects, Transforms, PrefabInstances)
|
||||||
|
|
||||||
pub mod box_collider;
|
pub mod box_collider;
|
||||||
|
pub mod capsule_collider;
|
||||||
|
pub mod collider;
|
||||||
pub mod game_object;
|
pub mod game_object;
|
||||||
pub mod mesh_filter;
|
pub mod mesh_filter;
|
||||||
pub mod mesh_renderer;
|
pub mod mesh_renderer;
|
||||||
pub mod prefab_instance;
|
pub mod prefab_instance;
|
||||||
pub mod renderer;
|
pub mod renderer;
|
||||||
|
pub mod sphere_collider;
|
||||||
pub mod transform;
|
pub mod transform;
|
||||||
|
|
||||||
pub use box_collider::BoxCollider;
|
pub use box_collider::BoxCollider;
|
||||||
|
pub use capsule_collider::CapsuleCollider;
|
||||||
|
pub use collider::Collider;
|
||||||
pub use game_object::GameObject;
|
pub use game_object::GameObject;
|
||||||
pub use mesh_filter::MeshFilter;
|
pub use mesh_filter::MeshFilter;
|
||||||
pub use mesh_renderer::MeshRenderer;
|
pub use mesh_renderer::MeshRenderer;
|
||||||
@@ -16,4 +21,5 @@ pub use prefab_instance::{
|
|||||||
PrefabInstance, PrefabInstanceComponent, PrefabModification, PrefabResolver,
|
PrefabInstance, PrefabInstanceComponent, PrefabModification, PrefabResolver,
|
||||||
};
|
};
|
||||||
pub use renderer::Renderer;
|
pub use renderer::Renderer;
|
||||||
|
pub use sphere_collider::SphereCollider;
|
||||||
pub use transform::{RectTransform, Transform};
|
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