scene_graph/
lib.rs

1#![doc = include_str!("../README.md")]
2#![deny(rust_2018_idioms)]
3#![deny(missing_docs)]
4#![deny(rustdoc::broken_intra_doc_links)]
5
6use std::{cmp::Eq, collections::HashMap};
7use thunderdome::{Arena, Index};
8
9mod child_iter;
10mod detatch_iter;
11mod iter;
12mod iter_mut;
13
14pub use child_iter::SceneGraphChildIter;
15pub use detatch_iter::{DetachedNode, SceneGraphDetachIter};
16pub use iter::SceneGraphIter;
17pub use iter_mut::SceneGraphIterMut;
18
19/// The core structure of `scene-graph`. This forms a rose tree, similar to a geneological tree.
20/// In this crate, we use geneological terms like `parent`, `child`, and `sibling` to describe node
21/// relationships.
22///
23/// A scene graph is composed of nodes, which have children, which are other nodes.
24/// Nodes additionally have siblings, which is determined by order of insertion into the graph.
25///
26/// You can traverse the SceneGraph by `iter`, to iterate downwards over the entire graph, or
27/// `iter_on_node`, to iterate downward from a particular node. This crate has no ability to iterate
28/// upwards, but you can use `get` to find a node's parent. If iterating upwards if useful to your
29/// usecase, please file an issue. Additionally, there are mutable variants of all of these
30/// iterators available.
31#[derive(Debug)]
32pub struct SceneGraph<T> {
33    /// The root value of the scene graph.
34    pub root: T,
35    arena: Arena<Node<T>>,
36    root_children: Option<Children>,
37}
38
39impl<T> SceneGraph<T> {
40    /// Creates a new `SceneGraph`
41    pub const fn new(root: T) -> Self {
42        Self {
43            arena: Arena::new(),
44            root,
45            root_children: None,
46        }
47    }
48
49    /// Clears all nodes from `self`, leaving the `Root` in place. If you want to edit the root too,
50    /// just make a new SceneGraph.
51    ///
52    /// Note: this method maintains the underlying container's size, so future attaches could have
53    /// some performance gains.
54    pub fn clear(&mut self) {
55        self.arena.clear();
56        self.root_children = None;
57    }
58
59    /// Returns the number of NON-ROOT nodes in the graph.
60    pub fn len(&self) -> usize {
61        self.arena.len()
62    }
63
64    /// Checks if the SceneGraph contains only the root.
65    pub fn is_empty(&self) -> bool {
66        self.root_children.is_none()
67    }
68
69    /// Attaches a node to the root node, returning a handle to it.
70    ///
71    /// This is a convenience method which will never fail.
72    pub fn attach_at_root(&mut self, value: T) -> NodeIndex {
73        self.attach(NodeIndex::Root, value).unwrap()
74    }
75
76    /// Attaches a node to another node, returning a handle to it.
77    pub fn attach(&mut self, parent: NodeIndex, value: T) -> Result<NodeIndex, ParentNodeNotFound> {
78        // push that node!
79        let new_idx = self.arena.insert(Node::new(value, parent));
80        self.place_node(parent, new_idx)?;
81
82        Ok(NodeIndex::Branch(new_idx))
83    }
84
85    /// Attaches an entire scene graph to a place on this graph. The old root node will be at
86    /// the returned NodeIndex.
87    pub fn attach_graph(
88        &mut self,
89        parent: NodeIndex,
90        mut other_graph: SceneGraph<T>,
91    ) -> Result<(NodeIndex, HashMap<NodeIndex, NodeIndex>), ParentNodeNotFound> {
92        let other_root = other_graph.root;
93        let new_root_idx = self.attach(parent, other_root)?;
94
95        let mut helper_map = HashMap::new();
96        helper_map.insert(NodeIndex::Root, new_root_idx);
97
98        let detach_iter = SceneGraphDetachIter::new(&mut other_graph.arena, NodeIndex::Root, other_graph.root_children);
99
100        for detached_node in detach_iter {
101            let parent_place = helper_map.get(&detached_node.parent_idx).unwrap();
102            let new_idx = self.attach(*parent_place, detached_node.node_value).unwrap();
103
104            helper_map.insert(detached_node.node_idx, new_idx);
105        }
106
107        Ok((new_root_idx, helper_map))
108    }
109
110    /// Removes a given node from the scene graph, returning a new SceneGraph where the given
111    /// node is now the *root*.
112    ///
113    /// Note: this always returns `None` when the node doesn't exist, or when the `node_index` is
114    /// the Root.
115    pub fn detach(&mut self, node_index: NodeIndex) -> Option<SceneGraph<T>> {
116        let node_index = match node_index {
117            NodeIndex::Root => return None,
118            NodeIndex::Branch(idx) => idx,
119        };
120
121        let node = self.arena.remove(node_index)?;
122        let mut new_sg = SceneGraph::new(node.value);
123
124        let mut helper_map = std::collections::HashMap::new();
125        helper_map.insert(NodeIndex::Branch(node_index), NodeIndex::Root);
126
127        for detached_node in SceneGraphDetachIter::new(&mut self.arena, NodeIndex::Branch(node_index), node.children) {
128            println!("detached_node = {:#?}", detached_node);
129
130            let parent_place = match detached_node.parent_idx {
131                NodeIndex::Root => NodeIndex::Root,
132                NodeIndex::Branch(_) => *helper_map.get(&detached_node.parent_idx).unwrap(),
133            };
134            let new_idx = new_sg.attach(parent_place, detached_node.node_value).unwrap();
135
136            helper_map.insert(detached_node.node_idx, new_idx);
137        }
138
139        self.fix_parent(node.next_sibling, node.last_sibling, node.parent, node_index);
140
141        Some(new_sg)
142    }
143
144    /// Moves a node from one parent to another parent. If this operation returns `Err`, then
145    /// nothing will have happened to the node.
146    pub fn move_node(&mut self, moving_node_idx: NodeIndex, new_parent: NodeIndex) -> Result<(), NodeDoesNotExist> {
147        let moving_node_idx = match moving_node_idx {
148            NodeIndex::Root => return Err(NodeDoesNotExist),
149            NodeIndex::Branch(idx) => {
150                if !self.arena.contains(idx) {
151                    return Err(NodeDoesNotExist);
152                }
153
154                idx
155            }
156        };
157
158        if let NodeIndex::Branch(idx) = new_parent {
159            if !self.arena.contains(idx) {
160                return Err(NodeDoesNotExist);
161            }
162        }
163
164        // okay, now we hot swap em
165        let moving_node = self.arena.get_mut(moving_node_idx).expect("we checked earlier");
166        let old_parent = moving_node.parent;
167        moving_node.parent = new_parent;
168
169        let next_sibling = moving_node.next_sibling;
170        moving_node.next_sibling = None;
171        let last_sibling = moving_node.last_sibling;
172
173        // now let's fix our old dad
174        self.fix_parent(next_sibling, last_sibling, old_parent, moving_node_idx);
175
176        // place it!
177        self.place_node(new_parent, moving_node_idx)
178            .expect("we checked earlier");
179
180        Ok(())
181    }
182
183    /// Removes a node *without* returning anything. This can save a few allocations. This removes
184    /// all of its children as well.
185    pub fn remove(&mut self, node_index: NodeIndex) {
186        let index = match node_index {
187            NodeIndex::Root => panic!("you cannot remove the root"),
188            NodeIndex::Branch(index) => index,
189        };
190
191        let Some(node) = self.arena.remove(index) else { return };
192
193        // detach em all!
194        for _v in SceneGraphDetachIter::new(&mut self.arena, node_index, node.children) {}
195
196        self.fix_parent(node.next_sibling, node.last_sibling, node.parent, index);
197    }
198
199    /// Returns `true` is the given `node_index` is valid.
200    pub fn contains(&self, node_index: NodeIndex) -> bool {
201        match node_index {
202            NodeIndex::Root => true,
203            NodeIndex::Branch(idx) => self.arena.contains(idx),
204        }
205    }
206
207    /// Gets a given node based on `NodeIndex`. Note that the `Root` always returns `None`.
208    /// Simply access `root_value` to get the root value.
209    pub fn get(&self, node_index: NodeIndex) -> Option<&Node<T>> {
210        match node_index {
211            NodeIndex::Root => None,
212            NodeIndex::Branch(idx) => self.arena.get(idx),
213        }
214    }
215
216    /// Gets a given node based on `NodeIndex`. Note that the `Root` always returns `None`,
217    /// as it is not a true node. Use `get_children` to generically get children.
218    pub fn get_mut(&mut self, node_index: NodeIndex) -> Option<&mut Node<T>> {
219        match node_index {
220            NodeIndex::Root => None,
221            NodeIndex::Branch(idx) => self.arena.get_mut(idx),
222        }
223    }
224
225    /// Gets the root node's value.
226    pub fn root(&self) -> &T {
227        &self.root
228    }
229
230    /// Gets the root node's value mutably.
231    pub fn root_mut(&mut self) -> &mut T {
232        &mut self.root
233    }
234
235    /// Returns the parent NodeIndex of a given Node.
236    ///
237    /// This operation is O1 over the number of nodes in the SceneGraph.
238    /// Note: this returns `None` for the Root.
239    pub fn parent(&self, node_index: NodeIndex) -> Option<NodeIndex> {
240        self.get(node_index).map(|v| v.parent)
241    }
242
243    /// Iterate mutably over the Scene Graph in a depth first traversal.
244    pub fn iter_mut(&mut self) -> SceneGraphIterMut<'_, T> {
245        SceneGraphIterMut::new(self, NodeIndex::Root)
246    }
247
248    /// Iterate immutably over the Scene Graph in a depth first traversal.
249    pub fn iter(&self) -> SceneGraphIter<'_, T> {
250        self.iter_from_node(NodeIndex::Root).unwrap()
251    }
252
253    /// Iterate immutably over the Scene Graph out of order. This is useful for speed.
254    pub fn iter_out_of_order(&self) -> impl Iterator<Item = (NodeIndex, &T)> {
255        self.arena.iter().map(|(k, v)| (NodeIndex::Branch(k), &v.value))
256    }
257
258    /// Iterate immutably over the Scene Graph in a depth first traversal.
259    pub fn iter_from_node(&self, node_index: NodeIndex) -> Result<SceneGraphIter<'_, T>, NodeDoesNotExist> {
260        let (parent_value, children) = match node_index {
261            NodeIndex::Root => (&self.root, self.root_children.as_ref()),
262            NodeIndex::Branch(idx) => {
263                let node = self.arena.get(idx).ok_or(NodeDoesNotExist)?;
264
265                (&node.value, node.children.as_ref())
266            }
267        };
268
269        Ok(SceneGraphIter::new(self, parent_value, children))
270    }
271
272    /// Iterate immutably over the Scene Graph in a depth first traversal.
273    pub fn iter_mut_from_node(&mut self, node_index: NodeIndex) -> Result<SceneGraphIterMut<'_, T>, NodeDoesNotExist> {
274        match node_index {
275            NodeIndex::Root => {}
276            NodeIndex::Branch(idx) => {
277                if !self.arena.contains(idx) {
278                    return Err(NodeDoesNotExist);
279                }
280            }
281        };
282
283        Ok(SceneGraphIterMut::new(self, node_index))
284    }
285
286    /// Iterate while detaching over the Scene Graph in a depth first traversal.
287    ///
288    /// Note: the `root` will never be detached.
289    pub fn iter_detach_from_root(&mut self) -> SceneGraphDetachIter<'_, T> {
290        SceneGraphDetachIter::new(&mut self.arena, NodeIndex::Root, self.root_children.take())
291    }
292
293    /// Iterate while detaching over the Scene Graph in a depth first traversal.
294    /// This leaves the `node_index` given in the graph, but removes all its descendents.
295    pub fn iter_detach(&mut self, node_index: NodeIndex) -> Result<SceneGraphDetachIter<'_, T>, NodeDoesNotExist> {
296        let children = match node_index {
297            NodeIndex::Root => self.root_children.take(),
298            NodeIndex::Branch(br) => match self.arena.get_mut(br) {
299                Some(v) => v.children.take(),
300                None => return Err(NodeDoesNotExist),
301            },
302        };
303
304        Ok(SceneGraphDetachIter::new(&mut self.arena, node_index, children))
305    }
306
307    /// Iterate directly over only the *direct* children of `parent_index`.
308    ///
309    /// For example, given a graph:
310    /// ROOT:
311    ///     A
312    ///         B
313    ///         C
314    ///             D
315    /// using [iter_direct_children] and passing in the `parent_index` for `A` will only yield `B`
316    /// and `C`, *not* `D`. For that kind of depth first traversal, using `iter_on_node`.
317    ///
318    /// [iter_direct_children]: [Self::iter_direct_children]
319    pub fn iter_direct_children(
320        &self,
321        parent_index: NodeIndex,
322    ) -> Result<SceneGraphChildIter<'_, T>, NodeDoesNotExist> {
323        if let NodeIndex::Branch(idx) = parent_index {
324            self.arena.get(idx).ok_or(NodeDoesNotExist)?;
325        }
326
327        Ok(SceneGraphChildIter::new(self, parent_index))
328    }
329
330    /// Places a node as part of moving or attaching it.
331    fn place_node(&mut self, new_parent: NodeIndex, node_to_place: Index) -> Result<(), ParentNodeNotFound> {
332        // okay, now we gotta ATTACH ourselves back, without being monsters about it
333        let parent_children = match new_parent {
334            NodeIndex::Root => &mut self.root_children,
335            NodeIndex::Branch(idx) => &mut self.arena.get_mut(idx).ok_or(ParentNodeNotFound)?.children,
336        };
337
338        // slap ourselves in here
339        match parent_children.as_mut() {
340            Some(children) => {
341                let old_last = children.last;
342                children.last = node_to_place;
343
344                let mut last_sibling = &mut self.arena[old_last];
345                last_sibling.next_sibling = Some(node_to_place);
346
347                // fix this up too
348                self.arena[node_to_place].last_sibling = Some(old_last);
349            }
350            None => {
351                // this is the easy case
352                *parent_children = Some(Children {
353                    first: node_to_place,
354                    last: node_to_place,
355                });
356            }
357        };
358
359        Ok(())
360    }
361
362    /// Fixes a parent with a removed child.
363    fn fix_parent(
364        &mut self,
365        removed_next_sibling: Option<Index>,
366        removed_last_sibling: Option<Index>,
367        removed_parent: NodeIndex,
368        removed_idx: Index,
369    ) {
370        // fix up the parent if it was the first child...
371
372        let mut parent_children = match removed_parent {
373            NodeIndex::Root => self.root_children.unwrap(),
374            NodeIndex::Branch(idx) => self.arena[idx].children.unwrap(),
375        };
376
377        if parent_children.first == parent_children.last && parent_children.first == removed_idx {
378            match removed_parent {
379                NodeIndex::Root => self.root_children = None,
380                NodeIndex::Branch(idx) => self.arena[idx].children = None,
381            };
382        } else {
383            // extremely hard to follow the logic of this unwrap here, but if this branch is taken,
384            // then we're *never* the last child, which means we have a sibling.
385            if parent_children.first == removed_idx {
386                parent_children.first = removed_next_sibling.unwrap();
387            }
388
389            if parent_children.last == removed_idx {
390                parent_children.last = removed_last_sibling.unwrap();
391            }
392
393            if let Some(last_sibling) = removed_last_sibling {
394                let last_sibling = self.arena.get_mut(last_sibling).unwrap();
395                last_sibling.next_sibling = removed_next_sibling;
396            }
397
398            if let Some(next_sibling) = removed_next_sibling {
399                let next_sibling = self.arena.get_mut(next_sibling).unwrap();
400                next_sibling.last_sibling = removed_last_sibling;
401            }
402
403            // finally, dump our updated parent children back
404            match removed_parent {
405                NodeIndex::Root => self.root_children = Some(parent_children),
406                NodeIndex::Branch(idx) => self.arena[idx].children = Some(parent_children),
407            };
408        }
409    }
410}
411
412impl<'a, T> IntoIterator for &'a SceneGraph<T> {
413    type Item = (&'a T, &'a T);
414
415    type IntoIter = SceneGraphIter<'a, T>;
416
417    fn into_iter(self) -> Self::IntoIter {
418        self.iter()
419    }
420}
421
422impl<'a, T> IntoIterator for &'a mut SceneGraph<T> {
423    type Item = (&'a mut T, &'a mut T);
424
425    type IntoIter = SceneGraphIterMut<'a, T>;
426
427    fn into_iter(self) -> Self::IntoIter {
428        self.iter_mut()
429    }
430}
431
432/// A wrapper around the values given to the SceneGraph. This struct includes the data on the
433/// relationships to other nodes, in addition to the value placed at the node.
434#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash)]
435pub struct Node<T> {
436    /// The value contained within the node.
437    pub value: T,
438    parent: NodeIndex,
439    children: Option<Children>,
440    last_sibling: Option<Index>,
441    next_sibling: Option<Index>,
442}
443
444impl<T> Node<T> {
445    fn new(value: T, parent: NodeIndex) -> Self {
446        Self {
447            value,
448            parent,
449            last_sibling: None,
450            next_sibling: None,
451            children: None,
452        }
453    }
454
455    /// Returns true if this node has children.
456    pub fn has_children(&self) -> bool {
457        self.children.is_some()
458    }
459
460    /// Iterate directly over only the *direct* children of `parent_index`.
461    ///
462    /// For example, given a graph:
463    /// ROOT:
464    ///     A
465    ///         B
466    ///         C
467    ///             D
468    /// using `iter_direct_children` and passing in the `parent_index` for `A` will only yield `B`
469    /// and `C`, *not* `D`. For that kind of depth first traversal, using `iter_on_node`.
470    ///
471    /// Note: passing in a SceneGraph of a different kind than this node belongs to (but of the same
472    /// type) will create logic errors or panics.
473    pub fn iter_direct_children<'a>(&'a self, sg: &'a SceneGraph<T>) -> SceneGraphChildIter<'a, T> {
474        SceneGraphChildIter::with_children(sg, self.children.as_ref())
475    }
476
477    /// Returns the index of the parent.
478    pub fn parent(&self) -> NodeIndex {
479        self.parent
480    }
481}
482
483#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash)]
484struct Children {
485    first: Index,
486    last: Index,
487}
488
489impl<T> std::fmt::Debug for Node<T> {
490    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
491        f.debug_struct("Node")
492            .field("parent", &self.parent)
493            .field("children", &self.children)
494            .field("next_sibling", &self.next_sibling)
495            .finish()
496    }
497}
498
499/// A node index into the SceneGraph.
500#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash)]
501pub enum NodeIndex {
502    /// Signifies that the index corresponds to the root of the graph.
503    Root,
504
505    /// Signifies a non-root node.
506    Branch(thunderdome::Index),
507}
508
509impl NodeIndex {
510    /// Returns `true` if the node index is [`Root`].
511    ///
512    /// [`Root`]: NodeIndex::Root
513    #[must_use]
514    pub fn is_root(&self) -> bool {
515        matches!(self, Self::Root)
516    }
517}
518
519#[derive(Debug, PartialEq, Eq, thiserror::Error)]
520#[error("parent node not found")]
521/// The parent node requested was not found.
522pub struct ParentNodeNotFound;
523
524#[derive(Debug, PartialEq, Eq, thiserror::Error)]
525#[error("node does not exist")]
526/// The node does not exist.
527pub struct NodeDoesNotExist;
528
529#[cfg(test)]
530mod tests {
531    use super::*;
532
533    fn get_values(sg: &SceneGraph<&'static str>) -> Vec<&'static str> {
534        let mut out = vec![];
535        for (_, v) in sg.iter() {
536            out.push(*v);
537        }
538
539        out
540    }
541
542    #[test]
543    fn basic_attach() {
544        let mut sg = SceneGraph::new("Root");
545        let root_idx = NodeIndex::Root;
546        sg.attach(root_idx, "First Child").unwrap();
547        let second_child = sg.attach(root_idx, "Second Child").unwrap();
548        sg.attach(second_child, "First Grandchild").unwrap();
549
550        assert_eq!(get_values(&sg), vec!["First Child", "Second Child", "First Grandchild"]);
551    }
552
553    #[test]
554    fn attach_internals() {
555        let mut sg = SceneGraph::new("Root");
556
557        assert_eq!(sg.root_children, None);
558
559        let root_idx = NodeIndex::Root;
560
561        let first_idx = sg.attach(root_idx, "First Child").unwrap();
562
563        // assert_eq!(sg.get_root().num_children, 1);
564        assert_eq!(NodeIndex::Branch(sg.root_children.unwrap().first), first_idx);
565        assert_eq!(NodeIndex::Branch(sg.root_children.unwrap().last), first_idx);
566
567        let second_idx = sg.attach(root_idx, "Second Child").unwrap();
568
569        assert_eq!(NodeIndex::Branch(sg.root_children.unwrap().first), first_idx);
570        assert_eq!(NodeIndex::Branch(sg.root_children.unwrap().last), second_idx);
571
572        assert_eq!(
573            sg.get(first_idx).unwrap().next_sibling.map(NodeIndex::Branch),
574            Some(second_idx)
575        );
576        assert_eq!(sg.get(first_idx).unwrap().last_sibling, None);
577
578        assert_eq!(sg.get(second_idx).unwrap().next_sibling, None);
579        assert_eq!(
580            sg.get(second_idx).unwrap().last_sibling.map(NodeIndex::Branch),
581            Some(first_idx)
582        );
583    }
584
585    #[test]
586    fn detach_basic() {
587        let mut sg = SceneGraph::new("Root");
588        let first_child = sg.attach_at_root("First Child");
589        let second_child = sg.attach_at_root("Second Child");
590        let third_child = sg.attach_at_root("Third Child");
591
592        let second_child = sg.detach(second_child).unwrap();
593        assert_eq!(*second_child.root(), "Second Child");
594
595        assert_eq!(NodeIndex::Branch(sg.root_children.unwrap().first), first_child);
596        assert_eq!(NodeIndex::Branch(sg.root_children.unwrap().last), third_child);
597
598        assert_eq!(sg.get(first_child).unwrap().last_sibling, None);
599        assert_eq!(
600            sg.get(first_child).unwrap().next_sibling.map(NodeIndex::Branch),
601            Some(third_child)
602        );
603
604        assert_eq!(
605            sg.get(third_child).unwrap().last_sibling.map(NodeIndex::Branch),
606            Some(first_child)
607        );
608        assert_eq!(sg.get(third_child).unwrap().next_sibling, None);
609
610        assert_eq!(get_values(&sg), vec!["First Child", "Third Child"]);
611
612        let g = sg.attach(third_child, "First Grandchild").unwrap();
613        sg.attach(g, "Second Grandchild").unwrap();
614        let g_3 = sg.attach(g, "Third Grandchild").unwrap();
615        sg.attach(g_3, "First Greatgrandchild").unwrap();
616
617        let third_child_tree = sg.detach(third_child).unwrap();
618        assert_eq!(get_values(&sg), vec!["First Child"]);
619        assert_eq!(
620            get_values(&third_child_tree),
621            vec![
622                "First Grandchild",
623                "Second Grandchild",
624                "Third Grandchild",
625                "First Greatgrandchild"
626            ]
627        );
628        assert_eq!(*third_child_tree.root(), "Third Child");
629    }
630
631    #[test]
632    fn move_node() {
633        let mut sg = SceneGraph::new("Root");
634        let fg = sg.attach(NodeIndex::Root, "First Child").unwrap();
635        sg.attach(fg, "First Grandchild").unwrap();
636        sg.attach(fg, "Second Grandchild").unwrap();
637        sg.attach(fg, "Third Grandchild").unwrap();
638        let second_child = sg.attach(NodeIndex::Root, "Second Child").unwrap();
639
640        assert_eq!(
641            Vec::from_iter(sg.iter_direct_children(fg).unwrap().cloned()),
642            vec!["First Grandchild", "Second Grandchild", "Third Grandchild",]
643        );
644
645        sg.move_node(fg, second_child).unwrap();
646
647        assert_eq!(
648            Vec::from_iter(sg.iter_direct_children(NodeIndex::Root).unwrap().cloned()),
649            vec!["Second Child",]
650        );
651
652        assert_eq!(
653            Vec::from_iter(sg.iter_direct_children(fg).unwrap().cloned()),
654            vec!["First Grandchild", "Second Grandchild", "Third Grandchild",]
655        );
656
657        assert_eq!(
658            Vec::from_iter(sg.iter_direct_children(second_child).unwrap().cloned()),
659            vec!["First Child",]
660        );
661    }
662
663    #[test]
664    fn clear_works() {
665        let input_node: Vec<_> = (0..50_000).map(|v| format!("Node_{}", v)).collect();
666        let mut sg = SceneGraph::new("Root");
667
668        for v in input_node.iter() {
669            sg.attach_at_root(v);
670        }
671
672        sg.clear();
673
674        assert_eq!(sg.len(), 0);
675        assert!(sg.is_empty());
676        assert!(sg.root_children.is_none());
677        assert!(sg.arena.is_empty());
678    }
679}