use nalgebra_glm::{identity, vec3, Mat4, Vec3, U4}; use std::cell::{Ref, RefCell}; use std::rc::Rc; struct Graph { root: NodeRef, } impl Graph { fn new() -> Graph { let mut node = Node::new(); node.is_root = true; Graph { root: node.into_ref(), } } } type NodeRef = Rc>; trait NodeExt { fn append_child(&self, child: &NodeRef); fn remove_child(&self, child: &NodeRef); } struct Node { rotation: Vec3, transform: Mat4, origin: Vec3, absolute_position: Option, children: Vec, parent: Option, is_root: bool, } impl Node { fn new() -> Node { Node { rotation: vec3(0.0, 0.0, 0.0), transform: identity::<_, U4>(), origin: vec3(0.0, 0.0, 0.0), absolute_position: None, children: vec![], parent: None, is_root: false, } } fn into_ref(self) -> NodeRef { Rc::new(RefCell::new(self)) } } impl NodeExt for NodeRef { fn append_child(&self, child: &NodeRef) { if Rc::ptr_eq(&self, child) { return; } if let Some(parent) = child.borrow().parent.clone() { parent.remove_child(&self) } self.borrow_mut().children.push(child.clone()) } fn remove_child(&self, child: &NodeRef) { let children = &mut self.borrow_mut().children; let mut offset: usize = 0; for i in 0..childs.len() { if Rc::ptr_eq(&childs[i - offset], child) { children.remove(i - offset); offset += 1; } } } } #[cfg(test)] pub mod test { use crate::*; #[test] pub fn it_works() { let node = Node::new().into_ref(); node.append_child(&node); node.remove_child(&node); let second_node = Node::new().into_ref(); node.append_child(&second_node); let graph = Graph::new(); graph.root.append_child(&node); assert_eq!(1, graph.root.borrow().children.len()); } }