openusd-rs 0.1.0

Work in progress, opinionated implementation of OpenUSD in pure Rust
Documentation
use super::{Attribute, Object};
use crate::{sdf, tf, usd};

/// [`usd::Prim`] is the sole persistent scenegraph object on a [`usd::Stage`],
/// and is the embodiment of a "Prim" as described in the *Universal Scene Description Composition Compendium*.
#[repr(transparent)]
pub struct Prim<'a>(Object<'a>);

impl<'a> Prim<'a> {
	pub(crate) fn new(stage: &'a usd::Stage, path: sdf::Path) -> Self {
		Prim(Object::new(stage, path))
	}

	pub fn specifier(&self) -> Option<sdf::Specifier> {
		self.stage()
			.data()
			.get(self.path(), &sdf::FIELD_KEYS.specifier)
			.map(|v| v.get::<sdf::Specifier>())
			.flatten()
	}

	pub fn get_attribute<'b>(&'b self, name: &tf::Token) -> Attribute<'b> {
		Attribute::new(self.stage(), self.path().append_property(name))
	}

	pub fn has_attribute(&self, name: &tf::Token) -> bool {
		self.stage()
			.data()
			.get(&self.path().append_property(name), &sdf::FIELD_KEYS.default)
			.is_some()
	}

	pub fn children<'b>(&'b self) -> ChildrenIter<'b> {
		ChildrenIter::new(self.stage(), self.path())
	}

	pub fn type_name(&self) -> tf::Token {
		self.metadata(&sdf::FIELD_KEYS.type_name)
			.unwrap_or_default()
	}
}

impl<'a> std::ops::Deref for Prim<'a> {
	type Target = Object<'a>;
	fn deref(&self) -> &Self::Target {
		unsafe { std::mem::transmute(self) }
	}
}

pub struct ChildrenIter<'a> {
	stage: &'a usd::Stage,
	base_path: sdf::Path,
	prim_children: Vec<tf::Token>,
	index: usize,
}

impl<'a> ChildrenIter<'a> {
	pub fn new(stage: &'a usd::Stage, path: &sdf::Path) -> Self {
		ChildrenIter {
			stage,
			base_path: path.clone(),
			prim_children: stage
				.data()
				.get(&path, &sdf::CHILDREN_KEYS.prim_children)
				.map(|v| v.get::<Vec<tf::Token>>())
				.flatten()
				.unwrap_or_default(),
			index: 0,
		}
	}
}

impl<'a> Iterator for ChildrenIter<'a> {
	type Item = Prim<'a>;

	fn next(&mut self) -> Option<Self::Item> {
		if self.index < self.prim_children.len() {
			let path = self.prim_children[self.index].clone();
			self.index += 1;
			Some(Prim::new(self.stage, self.base_path.append_child(&path)))
		} else {
			None
		}
	}
}