couch-rust/src/gameobject.rs

145 lines
2.8 KiB
Rust

use nalgebra_glm as glm;
use crate::model::Model;
use std::rc::Rc;
use std::cell::RefCell;
pub type NodeRef = Rc<RefCell<Node>>;
pub struct Node {
pub name: String,
pub gameobject: GameObject,
pub children: Vec<NodeRef>,
}
pub trait Childbearing<T> { // TODO remove this
fn add_child(&mut self, name: &str, child: T);
}
impl Node {
pub fn find_node(&mut self, name: &str) -> Option<NodeRef> {
self.children
.iter()
.find(|node| node.borrow().name == name)
.map(|node| Rc::clone(node))
}
}
macro_rules! impl_childbearing {
($t:ty, $e:path) => {
impl Childbearing<$t> for Node {
fn add_child(&mut self, name: &str, child: $t) {
self.children.push(Rc::new(RefCell::new(Node::new(name.to_string(), $e(Box::new(child))))));
}
}
}
}
impl Node {
pub fn new(name: String, gameobject: GameObject) -> Self {
Node {
name,
gameobject,
children: Vec::new(),
}
}
}
pub enum GameObject {
Null,
Camera(Box<Camera>),
Mesh(Box<Mesh>),
}
impl GameObject {
pub fn get_transform(&self) -> Result<Transform, String> {
use GameObject::*;
match self {
Camera(camera) => Ok(camera.get_transform()),
Mesh(mesh) => Ok(mesh.get_transform()),
_ => Err("object does not implement \"get_transform\"".to_string())
}
}
pub fn set_transform(&mut self, transform: Transform) -> Result<(), String> {
use GameObject::*;
match self {
Camera(camera) => { camera.set_transform(transform); Ok(()) }
Mesh(mesh) => { mesh.set_transform(transform); Ok(()) }
_ => Err("object does not implement \"set_transform\"".to_string())
}
}
}
#[derive(Clone, Copy)]
pub struct Transform {
pub position: glm::Vec3,
pub rotation: glm::Vec3,
pub scale: glm::Vec3,
}
impl Default for Transform {
fn default() -> Self {
Transform {
position: glm::zero(),
rotation: glm::zero(),
scale: glm::vec3(1.0, 1.0, 1.0),
}
}
}
pub trait Spatial {
fn get_transform(&self) -> Transform;
fn set_transform(&mut self, transform: Transform);
}
pub struct Camera {
transform: Transform,
}
impl Camera {
pub fn new() -> Self {
Camera {
transform: Default::default(),
}
}
}
impl Spatial for Camera {
fn get_transform(&self) -> Transform {
self.transform
}
fn set_transform(&mut self, transform: Transform) {
self.transform = transform
}
}
impl_childbearing!(Camera, GameObject::Camera);
pub struct Mesh {
pub model: Model,
transform: Transform,
}
impl Mesh {
pub fn new(model: Model) -> Self {
Mesh {
model,
transform: Default::default(),
}
}
}
impl Spatial for Mesh {
fn get_transform(&self) -> Transform {
self.transform
}
fn set_transform(&mut self, transform: Transform) {
self.transform = transform;
}
}
impl_childbearing!(Mesh, GameObject::Mesh);