1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
//! `Geometry` object (mesh).

use anyhow::{format_err, Error};

use crate::v7400::{
    data::mesh::{layer::LayerHandle, ControlPoints, PolygonVertices, RawPolygonVertices},
    object::{deformer, geometry::GeometryHandle, model, TypedObjectHandle},
};

define_object_subtype! {
    /// `Geometry` node handle (mesh).
    MeshHandle: GeometryHandle
}

impl<'a> MeshHandle<'a> {
    /// Returns an iterator of parent model objects.
    pub fn models(&self) -> impl Iterator<Item = model::MeshHandle<'a>> {
        self.destination_objects()
            .filter(|obj| obj.label().is_none())
            .filter_map(|obj| obj.object_handle())
            .filter_map(|obj| match obj.get_typed() {
                TypedObjectHandle::Model(model::TypedModelHandle::Mesh(o)) => Some(o),
                _ => None,
            })
    }

    /// Returns a child deformer skin if available.
    pub fn skins(&self) -> impl Iterator<Item = deformer::SkinHandle<'a>> {
        self.source_objects()
            .filter(|obj| obj.label().is_none())
            .filter_map(|obj| obj.object_handle())
            .filter_map(|obj| match obj.get_typed() {
                TypedObjectHandle::Deformer(deformer::TypedDeformerHandle::Skin(o)) => Some(o),
                _ => None,
            })
    }

    /// Returns a child deformer blendshapes if available.
    pub fn blendshapes(&self) -> impl Iterator<Item = deformer::BlendShapeHandle<'a>> {
        self.source_objects()
            .filter(|obj| obj.label().is_none())
            .filter_map(|obj| obj.object_handle())
            .filter_map(|obj| match obj.get_typed() {
                TypedObjectHandle::Deformer(deformer::TypedDeformerHandle::BlendShape(o)) => {
                    Some(o)
                }
                _ => None,
            })
    }

    /// Returns control points.
    pub(crate) fn control_points(&self) -> Result<ControlPoints<'a>, Error> {
        self.node()
            .children_by_name("Vertices")
            .next()
            .ok_or_else(|| format_err!("`Vertices` child node not found for geometry mesh"))?
            .attributes()
            .get(0)
            .ok_or_else(|| format_err!("`Vertices` node has no attributes"))?
            .get_arr_f64_or_type()
            .map(ControlPoints::new)
            .map_err(|ty| {
                format_err!(
                    "`Vertices` has wrong type attribute: expected `[f64]` but got {:?}`",
                    ty
                )
            })
    }

    /// Returns polygon vertices without control points.
    pub(crate) fn raw_polygon_vertices(&self) -> Result<RawPolygonVertices<'a>, Error> {
        self.node()
            .children_by_name("PolygonVertexIndex")
            .next()
            .ok_or_else(|| {
                format_err!("`PolygonVertexIndex` child node not found for geometry mesh")
            })?
            .attributes()
            .get(0)
            .ok_or_else(|| format_err!("`PolygonVertexIndex` node has no attributes"))?
            .get_arr_i32_or_type()
            .map(RawPolygonVertices::new)
            .map_err(|ty| {
                format_err!(
                    "`PolygonVertexIndex` has wrong type attribute: expected `[i32]` but got {:?}`",
                    ty
                )
            })
    }

    /// Returns polygon vertices (control point indices) and control points.
    pub fn polygon_vertices(&self) -> Result<PolygonVertices<'a>, Error> {
        let control_points = self.control_points()?;
        let raw_polygon_vertices = self.raw_polygon_vertices()?;
        Ok(PolygonVertices::new(control_points, raw_polygon_vertices))
    }

    /// Returns layers.
    pub fn layers(&self) -> impl Iterator<Item = LayerHandle<'a>> {
        self.node().children_by_name("Layer").map(LayerHandle::new)
    }
}