use anyhow::Result;
use crate::sdf;
use crate::usd::{Attribute, Prim, Stage};
use super::impl_proc_schema;
use super::tokens as tok;
use crate::schemas::common::get_typed;
#[derive(Clone, derive_more::Deref)]
pub struct GenerativeProcedural(Prim);
impl GenerativeProcedural {
pub fn define(stage: &Stage, path: impl Into<sdf::Path>) -> Result<Self> {
Ok(Self(
stage.define_prim(path)?.set_type_name(tok::T_GENERATIVE_PROCEDURAL)?,
))
}
pub fn get(stage: &Stage, path: impl Into<sdf::Path>) -> Result<Option<Self>> {
get_typed(stage, path, tok::T_GENERATIVE_PROCEDURAL).map(|o| o.map(Self))
}
pub fn procedural_system_attr(&self) -> Attribute {
self.attribute(tok::A_PROCEDURAL_SYSTEM)
}
pub fn create_procedural_system_attr(&self) -> Result<Attribute> {
Ok(self
.create_attribute(tok::A_PROCEDURAL_SYSTEM, "token")?
.set_custom(false)?
.set_variability(sdf::Variability::Uniform)?)
}
}
impl_proc_schema!(boundable GenerativeProcedural);
#[cfg(test)]
mod tests {
use super::*;
use crate::schemas::geom::Boundable;
#[test]
fn generative_procedural_roundtrip() -> Result<()> {
let stage = Stage::builder().in_memory("anon.usda")?;
let p = GenerativeProcedural::define(&stage, "/World/Proc")?;
p.create_procedural_system_attr()?
.set(sdf::Value::Token("Houdini".into()))?;
let p = GenerativeProcedural::get(&stage, "/World/Proc")?.expect("GenerativeProcedural");
assert_eq!(
p.procedural_system_attr().get::<sdf::Value>()?,
Some(sdf::Value::Token("Houdini".into()))
);
assert_eq!(p.extent_attr().get::<sdf::Value>()?, None);
assert!(GenerativeProcedural::get(&stage, "/Missing")?.is_none());
Ok(())
}
#[test]
fn get_rejects_non_procedural() -> Result<()> {
let stage = Stage::builder().in_memory("anon.usda")?;
stage.define_prim("/NotProc")?.set_type_name("Scope")?;
assert!(GenerativeProcedural::get(&stage, "/NotProc")?.is_none());
Ok(())
}
}