#![warn(missing_docs)]
use crate::scene::dim2::rectangle::Rectangle;
use crate::{
asset::core::inspect::PropertyInfo,
core::{
define_is_as,
inspect::Inspect,
math::aabb::AxisAlignedBoundingBox,
visitor::{Visit, VisitResult, Visitor},
},
scene::{
base::Base, camera::Camera, collider::Collider, decal::Decal, dim2, joint::Joint,
light::Light, mesh::Mesh, particle_system::ParticleSystem, rigidbody::RigidBody,
sprite::Sprite, terrain::Terrain,
},
};
use std::ops::{Deref, DerefMut};
macro_rules! static_dispatch {
($self:ident, $func:ident, $($args:expr),*) => {
match $self {
Node::Base(v) => v.$func($($args),*),
Node::Mesh(v) => v.$func($($args),*),
Node::Camera(v) => v.$func($($args),*),
Node::Light(v) => v.$func($($args),*),
Node::ParticleSystem(v) => v.$func($($args),*),
Node::Sprite(v) => v.$func($($args),*),
Node::Terrain(v) => v.$func($($args),*),
Node::Decal(v) => v.$func($($args),*),
Node::RigidBody(v) => v.$func($($args),*),
Node::Collider(v) => v.$func($($args),*),
Node::Joint(v) => v.$func($($args),*),
Node::Rectangle(v) => v.$func($($args),*),
Node::RigidBody2D(v) => v.$func($($args),*),
Node::Collider2D(v) => v.$func($($args),*),
Node::Joint2D(v) => v.$func($($args),*),
}
};
}
impl Visit for Node {
fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
let mut kind_id = self.id();
kind_id.visit("KindId", visitor)?;
if visitor.is_reading() {
*self = Node::from_id(kind_id)?;
}
static_dispatch!(self, visit, name, visitor)
}
}
impl Inspect for Node {
fn properties(&self) -> Vec<PropertyInfo<'_>> {
static_dispatch!(self, properties,)
}
}
#[allow(clippy::large_enum_variant)]
#[derive(Debug)]
pub enum Node {
Base(Base),
Light(Light),
Camera(Camera),
Mesh(Mesh),
Sprite(Sprite),
ParticleSystem(ParticleSystem),
Terrain(Terrain),
Decal(Decal),
RigidBody(RigidBody),
Collider(Collider),
Joint(Joint),
RigidBody2D(dim2::rigidbody::RigidBody),
Collider2D(dim2::collider::Collider),
Joint2D(dim2::joint::Joint),
Rectangle(dim2::rectangle::Rectangle),
}
macro_rules! static_dispatch_deref {
($self:ident) => {
match $self {
Node::Base(v) => v,
Node::Mesh(v) => v,
Node::Camera(v) => v,
Node::Light(v) => v,
Node::ParticleSystem(v) => v,
Node::Sprite(v) => v,
Node::Terrain(v) => v,
Node::Decal(v) => v,
Node::RigidBody(v) => v,
Node::Collider(v) => v,
Node::Joint(v) => v,
Node::Rectangle(v) => v,
Node::RigidBody2D(v) => v,
Node::Collider2D(v) => v,
Node::Joint2D(v) => v,
}
};
}
impl Deref for Node {
type Target = Base;
fn deref(&self) -> &Self::Target {
static_dispatch_deref!(self)
}
}
impl DerefMut for Node {
fn deref_mut(&mut self) -> &mut Self::Target {
static_dispatch_deref!(self)
}
}
impl Default for Node {
fn default() -> Self {
Self::Base(Default::default())
}
}
impl Node {
pub fn local_bounding_box(&self) -> AxisAlignedBoundingBox {
static_dispatch!(self, local_bounding_box,)
}
pub fn world_bounding_box(&self) -> AxisAlignedBoundingBox {
static_dispatch!(self, world_bounding_box,)
}
pub fn from_id(id: u8) -> Result<Self, String> {
match id {
0 => Ok(Self::Base(Default::default())),
1 => Ok(Self::Light(Default::default())),
2 => Ok(Self::Camera(Default::default())),
3 => Ok(Self::Mesh(Default::default())),
4 => Ok(Self::Sprite(Default::default())),
5 => Ok(Self::ParticleSystem(Default::default())),
6 => Ok(Self::Terrain(Default::default())),
7 => Ok(Self::Decal(Default::default())),
8 => Ok(Self::RigidBody(Default::default())),
9 => Ok(Self::Collider(Default::default())),
10 => Ok(Self::Joint(Default::default())),
11 => Ok(Self::Rectangle(Default::default())),
12 => Ok(Self::RigidBody2D(Default::default())),
13 => Ok(Self::Collider2D(Default::default())),
14 => Ok(Self::Joint2D(Default::default())),
_ => Err(format!("Invalid node kind {}", id)),
}
}
pub fn id(&self) -> u8 {
match self {
Self::Base(_) => 0,
Self::Light(_) => 1,
Self::Camera(_) => 2,
Self::Mesh(_) => 3,
Self::Sprite(_) => 4,
Self::ParticleSystem(_) => 5,
Self::Terrain(_) => 6,
Self::Decal(_) => 7,
Self::RigidBody(_) => 8,
Self::Collider(_) => 9,
Self::Joint(_) => 10,
Self::Rectangle(_) => 11,
Self::RigidBody2D(_) => 12,
Self::Collider2D(_) => 13,
Self::Joint2D(_) => 14,
}
}
pub fn raw_copy(&self) -> Self {
match self {
Node::Base(v) => Node::Base(v.raw_copy()),
Node::Light(v) => Node::Light(v.raw_copy()),
Node::Camera(v) => Node::Camera(v.raw_copy()),
Node::Mesh(v) => Node::Mesh(v.raw_copy()),
Node::Sprite(v) => Node::Sprite(v.raw_copy()),
Node::ParticleSystem(v) => Node::ParticleSystem(v.raw_copy()),
Node::Terrain(v) => Node::Terrain(v.raw_copy()),
Node::Decal(v) => Node::Decal(v.raw_copy()),
Node::RigidBody(v) => Node::RigidBody(v.raw_copy()),
Node::Collider(v) => Node::Collider(v.raw_copy()),
Node::Joint(v) => Node::Joint(v.raw_copy()),
Node::Rectangle(v) => Node::Rectangle(v.raw_copy()),
Node::RigidBody2D(v) => Node::RigidBody2D(v.raw_copy()),
Node::Collider2D(v) => Node::Collider2D(v.raw_copy()),
Node::Joint2D(v) => Node::Joint2D(v.raw_copy()),
}
}
define_is_as!(Node : Mesh -> ref Mesh => fn is_mesh, fn as_mesh, fn as_mesh_mut);
define_is_as!(Node : Camera -> ref Camera => fn is_camera, fn as_camera, fn as_camera_mut);
define_is_as!(Node : Light -> ref Light => fn is_light, fn as_light, fn as_light_mut);
define_is_as!(Node : ParticleSystem -> ref ParticleSystem => fn is_particle_system, fn as_particle_system, fn as_particle_system_mut);
define_is_as!(Node : Sprite -> ref Sprite => fn is_sprite, fn as_sprite, fn as_sprite_mut);
define_is_as!(Node : Terrain -> ref Terrain => fn is_terrain, fn as_terrain, fn as_terrain_mut);
define_is_as!(Node : Decal -> ref Decal => fn is_decal, fn as_decal, fn as_decal_mut);
define_is_as!(Node : Rectangle -> ref Rectangle => fn is_rectangle, fn as_rectangle, fn as_rectangle_mut);
define_is_as!(Node : RigidBody -> ref RigidBody => fn is_rigid_body, fn as_rigid_body, fn as_rigid_body_mut);
define_is_as!(Node : Collider -> ref Collider => fn is_collider, fn as_collider, fn as_collider_mut);
define_is_as!(Node : Joint -> ref Joint => fn is_joint, fn as_joint, fn as_joint_mut);
define_is_as!(Node : RigidBody2D -> ref dim2::rigidbody::RigidBody => fn is_rigid_body2d, fn as_rigid_body2d, fn as_rigid_body2d_mut);
define_is_as!(Node : Collider2D -> ref dim2::collider::Collider => fn is_collider2d, fn as_collider2d, fn as_collider2d_mut);
define_is_as!(Node : Joint2D -> ref dim2::joint::Joint => fn is_joint2d, fn as_joint2d, fn as_joint2d_mut);
}