Resolving relative paths from Sdf.Layer.subLayerPaths

Hello!

I’ve opened a layer with Sdf.Layer.FindOrOpen() and it has a few relative sublayers. Is there a way to resolve these paths relative to the layer that I’ve opened? I can easily just use python to join them and resolve them but is there a way by creating a resolver context and the asset resolver to do that for me (some bad pseudocode)

layer = Sdf.Layer.FindOrOpen(‘/path/to/asset.usd’)
ctx = Ar.ResolverContext([‘/path/to/asset.usd’])
resolver = Ar.GetResolver()
for sublayer in layer.subLayerPaths:
print (resolver.Resolve(sublayer, ctx))

Thanks!

1 Like

I’m certainly not an expert on asset resolution, but I believe the answer is yes. I tend to prefer making the asset paths absolute before resolving them since it feels a little higher level, though binding a specific resolver context should be possible too.

Using absolute paths:

layer = Sdf.Layer.FindOrOpen("/path/to/asset.usd")
resolver = Ar.GetResolver()
for sublayer in layer.subLayerPaths:
    print(resolver.Resolve(layer.ComputeAbsolutePath(sublayer)))

Using resolver context:

layer = Sdf.Layer.FindOrOpen("/path/to/asset.usd")
resolver = Ar.GetResolver()
ctx = resolver.CreateDefaultContextForAsset(
    layer.repositoryPath or layer.realPath
)
with Ar.ResolverContextBinder(ctx):
    for sublayer in layer.subLayerPaths:
        print(resolver.Resolve(sublayer))
3 Likes

@jackohoeg makes some great points about absolute paths and contexts! The ComputeAbsolutePath() solution should always work (though it, too, may be affected by an ArResolverContext, so if there is an active/session context that is not already bound, you’d want to first bind it as in the second example.

The second example won’t work properly for “anchored paths” (e.g. with the ArDefaultResolver, those that start with “./” like @./anchored/layer.usd@). As of Ar 2.0, the preferred pattern to do this would be something like:

layer = Sdf.Layer.FindOrOpen("/path/to/asset.usd")
resolver = Ar.GetResolver()
lyrResolved = layer.resolvedPath
ctx = resolver.CreateDefaultContextForAsset(lyrResolved)

with Ar.ResolverContextBinder(ctx):
    for sublayer in layer.subLayerPaths:
        print(resolver.Resolve(resolver.CreateIdentifier(sublayer, lyrResolved)))
1 Like

(the reason for possibly preferring the second approach is that ComputeAbsolutePath() does more work than is strictly required by your query).

1 Like

Thank you both for the answers!