openusd_schemas/lib.rs
1//! Typed views for USD's standard schemas, over a composed
2//! [`Stage`](openusd::usd::Stage).
3//!
4//! Ask a `Mesh` for its points, a `Camera` for its focal length, a `Material`
5//! for the shader on its surface output, a `Skeleton` for its joints and
6//! skinning weights — as Rust types, rather than by attribute name and hand
7//! decoding. Every view authors as well as reads.
8//!
9//! Each sub-module is feature-gated so callers only compile what
10//! they need:
11//!
12//! | Feature | Module | Status |
13//! |---------|--------|--------|
14//! | `geom` | `geom` | `UsdGeom` reader (cross-cutting Imageable / Boundable today; full surface incoming). |
15//! | `physics` | `physics` | `UsdPhysics` reader (8 prim types, 7 single-apply APIs, multi-apply `LimitAPI` / `DriveAPI`). |
16//! | `skel` | `skel` | `UsdSkel` trait-views (SkelRoot / Skeleton as geom `Boundable`, SkelAnimation / BlendShape typed, SkelBindingAPI single-apply) + skinning toolkit (Topology, AnimMapper, SkeletonResolver, SkinningResolver, pure-math LBS); builds on the `geom` trait chain. |
17//! | `lux` | `lux` | `UsdLux` trait-views (8 concrete light prims + LightFilter + LightAPI / ShapingAPI / ShadowAPI / LightListAPI); builds on the `geom` trait chain. |
18//! | `shade` | `shade` | `UsdShade` trait-views (Shader / NodeGraph / Material via the `Connectable` interface, MaterialBindingAPI, UsdPreviewSurface reader). |
19//! | `render` | `render` | `UsdRender` trait-views (RenderSettings / Product via the `RenderSettingsBase` interface, Var / Pass / DenoisePass) + the computed render spec. |
20//! | `ui` | `ui` | `UsdUI` trait-views (typed `Backdrop` + single-apply `SceneGraphPrimAPI` / `NodeGraphNodeAPI`). |
21//! | `vol` | `vol` | `UsdVol` trait-views (`Volume` + `OpenVDBAsset` / `Field3DAsset`); builds on the `geom` trait chain. |
22//! | `media` | `media` | `UsdMedia` trait-views (`SpatialAudio` + `AssetPreviewsAPI`); builds on the `geom` trait chain. |
23//! | `proc` | `proc` | `UsdProc` trait-view (`GenerativeProcedural`, a `geom::Boundable`); builds on the `geom` trait chain. |
24//!
25//! These views read and author opinions; the property fallbacks a schema
26//! declares come from [`openusd::usd::SchemaRegistry`].
27
28use openusd::sdf;
29
30// The macros below generate paths into the core crate. Reaching it through
31// `$crate::openusd` keeps them bound to this crate's dependency rather than
32// to whatever `openusd` names at the expansion site.
33pub(crate) use ::openusd;
34
35#[cfg(any(
36 feature = "geom",
37 feature = "lux",
38 feature = "media",
39 feature = "physics",
40 feature = "proc",
41 feature = "render",
42 feature = "shade",
43 feature = "skel",
44 feature = "ui",
45 feature = "vol"
46))]
47mod common;
48
49/// Any failure a schema view can report: a schema-domain failure of its own,
50/// or a core failure ([`Core`](Self::Core)) from the composed queries and
51/// authoring calls the view is built on.
52///
53/// The schemas module is layered on the core the way a separate crate would
54/// be, so the core's [`Error`](openusd::Error) knows nothing of this type; this
55/// enum wraps the core error instead.
56#[derive(Debug, thiserror::Error)]
57#[non_exhaustive]
58pub enum SchemaError {
59 /// A core failure underneath the schema view.
60 #[error(transparent)]
61 Core(#[from] openusd::Error),
62
63 /// An xformOp names no kind this schema knows, so it has no value type
64 /// and would contribute nothing to the transform stack.
65 #[error("`{op}` is not an xformOp kind")]
66 UnknownXformOp {
67 /// The kind the op token named, with its `xformOp:` prefix and any
68 /// `:suffix` removed.
69 op: String,
70 },
71
72 /// An xformOp's matrix is singular, so the transform stack cannot be
73 /// inverted through it.
74 #[error("xformOp `{op}` matrix is singular and cannot be inverted")]
75 SingularTransform {
76 /// The offending op's attribute name.
77 op: String,
78 },
79
80 /// `!resetXformStack!` appears past the front of `xformOpOrder`, where it
81 /// no longer means anything.
82 #[error("xformOpOrder on `{prim}`: `!resetXformStack!` is only valid at index 0, found at index {index}")]
83 InvalidOpOrder {
84 /// The prim whose order is malformed.
85 prim: sdf::Path,
86 /// Where the reset token was found.
87 index: usize,
88 },
89
90 /// A shading connection chain exceeds the resolver's depth bound,
91 /// indicating a cycle or a pathologically deep graph.
92 #[error("connection chain at {attribute} is deeper than {max} hops")]
93 ConnectionDepthExceeded {
94 /// The attribute whose resolution hit the bound.
95 attribute: sdf::Path,
96 /// The bound that was hit.
97 max: usize,
98 },
99
100 /// A volume field relationship needs a non-empty field name.
101 #[error("Volume field name must not be empty")]
102 EmptyFieldName,
103
104 /// A render context that is neither the universal context nor a
105 /// namespaced identifier.
106 #[error("invalid render context {context:?}")]
107 InvalidRenderContext {
108 /// The rejected context string.
109 context: String,
110 },
111}
112
113/// Stage-tier authoring failures route through [`SchemaError::Core`], so a
114/// schema authoring helper propagates them with one `?`.
115impl From<openusd::usd::StageAuthoringError> for SchemaError {
116 fn from(error: openusd::usd::StageAuthoringError) -> Self {
117 Self::Core(error.into())
118 }
119}
120
121/// Composed-query failures route through [`SchemaError::Core`] likewise.
122impl From<openusd::pcp::QueryError> for SchemaError {
123 fn from(error: openusd::pcp::QueryError) -> Self {
124 Self::Core(error.into())
125 }
126}
127
128/// Path-parse failures route through [`SchemaError::Core`] likewise.
129impl From<sdf::PathParseError> for SchemaError {
130 fn from(error: sdf::PathParseError) -> Self {
131 Self::Core(error.into())
132 }
133}
134
135/// Cast failures route through [`SchemaError::Core`] likewise.
136impl From<sdf::CastError> for SchemaError {
137 fn from(error: sdf::CastError) -> Self {
138 Self::Core(error.into())
139 }
140}
141
142/// A value that does not fit an attribute's declared type surfaces as the
143/// authoring error it is.
144impl From<sdf::ValueTypeError> for SchemaError {
145 fn from(error: sdf::ValueTypeError) -> Self {
146 Self::Core(openusd::usd::StageAuthoringError::from(error).into())
147 }
148}
149
150#[cfg(feature = "geom")]
151pub mod geom;
152#[cfg(feature = "lux")]
153pub mod lux;
154#[cfg(feature = "media")]
155pub mod media;
156#[cfg(feature = "physics")]
157pub mod physics;
158#[cfg(feature = "proc")]
159pub mod proc;
160#[cfg(feature = "render")]
161pub mod render;
162#[cfg(feature = "shade")]
163pub mod shade;
164#[cfg(feature = "skel")]
165pub mod skel;
166#[cfg(feature = "ui")]
167pub mod ui;
168#[cfg(feature = "vol")]
169pub mod vol;