Skip to main content

openusd_rs/usd/
prim.rs

1use super::{Attribute, Object};
2use crate::{sdf, tf, usd};
3
4/// [`usd::Prim`] is the sole persistent scenegraph object on a [`usd::Stage`],
5/// and is the embodiment of a "Prim" as described in the *Universal Scene Description Composition Compendium*.
6#[repr(transparent)]
7pub struct Prim<'a>(Object<'a>);
8
9impl<'a> Prim<'a> {
10	pub(crate) fn new(stage: &'a usd::Stage, path: sdf::Path) -> Self {
11		Prim(Object::new(stage, path))
12	}
13
14	pub fn specifier(&self) -> Option<sdf::Specifier> {
15		self.stage()
16			.data()
17			.get(self.path(), &sdf::FIELD_KEYS.specifier)
18			.map(|v| v.get::<sdf::Specifier>())
19			.flatten()
20	}
21
22	pub fn get_attribute<'b>(&'b self, name: &tf::Token) -> Attribute<'b> {
23		Attribute::new(self.stage(), self.path().append_property(name))
24	}
25
26	pub fn has_attribute(&self, name: &tf::Token) -> bool {
27		self.stage()
28			.data()
29			.get(&self.path().append_property(name), &sdf::FIELD_KEYS.default)
30			.is_some()
31	}
32
33	pub fn children<'b>(&'b self) -> ChildrenIter<'b> {
34		ChildrenIter::new(self.stage(), self.path())
35	}
36
37	pub fn type_name(&self) -> tf::Token {
38		self.metadata(&sdf::FIELD_KEYS.type_name)
39			.unwrap_or_default()
40	}
41}
42
43impl<'a> std::ops::Deref for Prim<'a> {
44	type Target = Object<'a>;
45	fn deref(&self) -> &Self::Target {
46		unsafe { std::mem::transmute(self) }
47	}
48}
49
50pub struct ChildrenIter<'a> {
51	stage: &'a usd::Stage,
52	base_path: sdf::Path,
53	prim_children: Vec<tf::Token>,
54	index: usize,
55}
56
57impl<'a> ChildrenIter<'a> {
58	pub fn new(stage: &'a usd::Stage, path: &sdf::Path) -> Self {
59		ChildrenIter {
60			stage,
61			base_path: path.clone(),
62			prim_children: stage
63				.data()
64				.get(&path, &sdf::CHILDREN_KEYS.prim_children)
65				.map(|v| v.get::<Vec<tf::Token>>())
66				.flatten()
67				.unwrap_or_default(),
68			index: 0,
69		}
70	}
71}
72
73impl<'a> Iterator for ChildrenIter<'a> {
74	type Item = Prim<'a>;
75
76	fn next(&mut self) -> Option<Self::Item> {
77		if self.index < self.prim_children.len() {
78			let path = self.prim_children[self.index].clone();
79			self.index += 1;
80			Some(Prim::new(self.stage, self.base_path.append_child(&path)))
81		} else {
82			None
83		}
84	}
85}