use anyhow::Result;
use crate::sdf::Path;
use crate::usd::Stage;
use super::read::{read_inherited_animation_source, read_inherited_skeleton, read_skel_binding};
use super::tokens::{API_SKEL_BINDING, T_SKELETON, T_SKEL_ROOT};
use super::types::ReadSkelBinding;
#[derive(Debug, Clone)]
pub struct SkelBinding {
pub prim: String,
pub skeleton: Option<String>,
pub animation_source: Option<String>,
pub binding: ReadSkelBinding,
}
pub fn discover_bindings(stage: &Stage, skel_root: &Path) -> Result<Vec<SkelBinding>> {
let mut out = Vec::new();
let mut first_err: Result<()> = Ok(());
stage.traverse(|path| {
if first_err.is_err() || !path.has_prefix(skel_root) {
return;
}
let mut visit = || -> Result<()> {
let api = stage.api_schemas(path)?;
if !api.iter().any(|s| s == API_SKEL_BINDING) {
return Ok(());
}
let Some(binding) = read_skel_binding(stage, path)? else {
return Ok(());
};
let skeleton = read_inherited_skeleton(stage, path)?;
let animation_source = read_inherited_animation_source(stage, path)?;
out.push(SkelBinding {
prim: path.as_str().to_string(),
skeleton,
animation_source,
binding,
});
Ok(())
};
if let Err(e) = visit() {
first_err = Err(e);
}
})?;
first_err?;
Ok(out)
}
pub fn discover_skeletons(stage: &Stage, skel_root: &Path) -> Result<Vec<String>> {
let mut out = Vec::new();
let mut first_err: Result<()> = Ok(());
stage.traverse(|path| {
if first_err.is_err() || !path.has_prefix(skel_root) {
return;
}
match stage.type_name(path) {
Ok(Some(t)) if t == T_SKELETON => out.push(path.as_str().to_string()),
Ok(_) => {}
Err(e) => first_err = Err(e),
}
})?;
first_err?;
Ok(out)
}
pub fn find_skel_roots(stage: &Stage) -> Result<Vec<String>> {
let mut out = Vec::new();
let mut first_err: Result<()> = Ok(());
stage.traverse(|path| {
if first_err.is_err() {
return;
}
match stage.type_name(path) {
Ok(Some(t)) if t == T_SKEL_ROOT => out.push(path.as_str().to_string()),
Ok(_) => {}
Err(e) => first_err = Err(e),
}
})?;
first_err?;
Ok(out)
}