Given a UsdEditTarget
, I am interested to know whether a stronger opinion exists on a given prim attribute, and in layer is this opinion located in the stage layer stack.
This post is kind of a post mortem as I think I have found a way to do so, but it does not feel the most straightforward way so I am looking at recommendation on how to do so in the most canonical and efficient way.
For the context of such queries, I am in a small editor offering to make edits on some prim attributes (e.g. a material editor), and to choose in which UsdEditTarget
to make those.
However, depending on your UsdEditTarget
, it is possible that edits you make have no visible effects because there exists a stronger opinion for this already. This is what I want to report in my editor and tell the user where and what is that stronger opinion.
For example, given the following layer stack:
- Stage-session.usda
- Stage.usda
- LayerFoo.usda
And that /Materials/Default/inputs:baseColor = (1, 0, 0)
exists in 1. Stage-session.usda
Then if you try to set /Materials/Default/inputs:baseColor = (0, 0, 1)
in 2. Stage.usda
.
The resolved value for /Materials/Default/inputs:baseColor
after the value resolution is still (1, 0, 0)
because 1. Stage-session.usda
has a stronger opinion than 2. Stage.usda
.
To detect this I use the following:
const PXR_NS::UsdEditTarget current_edit_target = ...;
const PXR_NS::UsdShadeMaterial material = ...;
const PXR_NS::UsdResolveTarget resolve_target_stronger = material .GetPrim().MakeResolveTargetStrongerThanEditTarget(current_edit_target);
for (const PXR_NS::UsdShadeInput& input : material.GetInputs(false))
{
const PXR_NS::UsdAttributeQuery query(input.GetAttr(), resolve_target_stronger);
if (attribute_query_stronger.HasValue())
{
// A stronger opinion exists on this input
}
}
The above tells me that a stronger opinion but not where.
UsdAttributeQuery
has an underlying UsdResolveInfo
which contains this information but it is not exposed in the API, is there any reason why it is not exposed ?
I could then try to re-run the value resolution myself calling UsdAttribute::GetResolveInfo()
but this has a couple of drawbacks:
- It will re-run the value resolution instead of re-using the one from
UsdAttributeQuery
- It is not contextual to my
UsdEditTarget
Ignoring those for a moment, even if I get my hands the UsdResolveInfo
I want.
Its public API only expose how to get the corresponding PcpNode
with UsdResolveInfo::GetNode
.
I am lacking knowledge how to leverage this the pcp
API to retrieve in which layer the stronger opinion is.
And like with UsdAttributeQuery
it seems the information I need is there but not available in the public API.
Tt seems that UdsResolveInfo
already hold the layer I am interest with _layer
, is there any reason why it is not exposed ?
Anyway getting to the conclusion, after poking a bit more at the USD API I have realised that I can get the piece of information by using the Usd_Resolver
I have and navigating value resolution myself and search for a strong opinion.
for (PXR_NS::Usd_Resolver resolver(&resolve_target_stronger); resolver.IsValid(); resolver.NextLayer())
{
const PXR_NS::SdfLayerRefPtr& resolved_layer = resolver.GetLayer();
if (const PXR_NS::SdfAttributeSpecHandle resolved_attribute_spec =
resolved_layer->GetAttributeAtPath(resolver.GetLocalPath(input.GetFullName())))
{
if (resolved_attribute_spec->HasDefaultValue())
{
// If I reach this part, it means I have found a stronger opinion for this material input, and it is located in `resolved_layer`
break;
}
}
}
It seems to work well for my use case, but as said at the beginning I am looking for advices and recommendation to do this efficiently, and answer on my questions about why some information are not exposed through the public API ?