fbxcel_dom/v7400/object/
scene.rs

1//! `Document` node.
2
3use anyhow::{format_err, Error};
4
5use crate::v7400::object::{ObjectHandle, ObjectId};
6
7/// `Document` node (`Scene` object) handle.
8///
9/// `Document` node (`Scene` object) contains root object ID of a scene.
10#[derive(Debug, Clone, Copy)]
11pub struct SceneHandle<'a> {
12    /// Object handle.
13    object: ObjectHandle<'a>,
14}
15
16impl<'a> SceneHandle<'a> {
17    /// Creates a new `SceneHandle` if the given object is `Document` node.
18    pub(crate) fn new(object: ObjectHandle<'a>) -> Option<Self> {
19        let is_document_node = object
20            .document()
21            .objects_cache()
22            .document_nodes()
23            .contains(&object.object_node_id());
24        if !is_document_node {
25            return None;
26        }
27        Some(Self { object })
28    }
29
30    /// Returns the root object ID of the scene.
31    pub fn root_object_id(&self) -> Result<ObjectId, Error> {
32        self.object
33            .node()
34            .children_by_name("RootNode")
35            .next()
36            .ok_or_else(|| format_err!("`RootNode` not found for scene object node"))?
37            .attributes()
38            .get(0)
39            .ok_or_else(|| format_err!("Attributes not found for `RootNode`"))?
40            .get_i64_or_type()
41            .map(ObjectId::new)
42            .map_err(|ty| {
43                format_err!(
44                    "Unexpected attribute type for `RootNode`: expected `i64` but got {:?}",
45                    ty
46                )
47            })
48    }
49
50    /// Returns the root object of the scene.
51    ///
52    /// Note that this returns `Err(_)` if the object has no corresponding node.
53    /// This can happen for valid FBX data.
54    pub fn root_object(&self) -> Result<ObjectHandle<'_>, Error> {
55        self.root_object_id()?
56            .to_object_handle(self.object.document())
57            .ok_or_else(|| {
58                format_err!(
59                    "Root object of the scene has no corresponding node: object_id={:?}",
60                    self.object.object_id()
61                )
62            })
63    }
64}
65
66impl<'a> std::ops::Deref for SceneHandle<'a> {
67    type Target = ObjectHandle<'a>;
68
69    fn deref(&self) -> &Self::Target {
70        &self.object
71    }
72}