-
Notifications
You must be signed in to change notification settings - Fork 7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support loading pre-existing USD files #205
Conversation
@@ -13,11 +13,15 @@ enum class ChangedPrimType { | |||
OTHER, | |||
}; | |||
|
|||
enum class ChangeType { PROPERTY_CHANGED, PRIM_ADDED [[maybe_unused]], PRIM_MOVED [[maybe_unused]], PRIM_REMOVED }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I removed PRIM_MOVED
from this list. USD gives us two resync notifications: first a remove, then an add. Treating them as separate events is actually easier in our code.
@@ -153,7 +154,6 @@ pxr::SdfPath Context::addTilesetUrl(const std::string& name, const std::string& | |||
|
|||
tilesetUsd.GetUrlAttr().Set<std::string>(url); | |||
|
|||
AssetRegistry::getInstance().addTileset(tilesetPath); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here and below: these functions are now only responsible for adding the USD prims. The USD notification system will let us know when the prims are added at which point the tileset/imagery will be added to the asset registry and the OmniTileset/OmniImagery objects will be created.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we be worried about any race conditions during the very brief time that the tileset has been added and the notification hasn't been handled?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think so... right now the update loop is the only thing that cares about OmniTileset
objects and it's happy to wait until they are created.
bool inSubtree(const pxr::SdfPath& path, const pxr::SdfPath& descendantPath) { | ||
if (path == descendantPath) { | ||
return true; | ||
} | ||
|
||
for (const auto& ancestorPath : descendantPath.GetAncestorsRange()) { | ||
if (ancestorPath == path) { | ||
return true; | ||
} | ||
} | ||
|
||
return false; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was hoping there would be a path.isDescendant(otherPath)
but couldn't find it. Maybe I'm overlooking it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There isn't. The only way to collect all of the descendant paths is to traverse the stage. There are a few helper functions for taking action on descendant paths but they all assume you have a vector of all of the paths you care about rather than actually handling traversal themselves and just check for a particular prefix to say "yup, this is descendant" in that list you provide.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great but I have one minor question before I approve.
@@ -153,7 +154,6 @@ pxr::SdfPath Context::addTilesetUrl(const std::string& name, const std::string& | |||
|
|||
tilesetUsd.GetUrlAttr().Set<std::string>(url); | |||
|
|||
AssetRegistry::getInstance().addTileset(tilesetPath); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we be worried about any race conditions during the very brief time that the tileset has been added and the notification hasn't been handled?
bool inSubtree(const pxr::SdfPath& path, const pxr::SdfPath& descendantPath) { | ||
if (path == descendantPath) { | ||
return true; | ||
} | ||
|
||
for (const auto& ancestorPath : descendantPath.GetAncestorsRange()) { | ||
if (ancestorPath == path) { | ||
return true; | ||
} | ||
} | ||
|
||
return false; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There isn't. The only way to collect all of the descendant paths is to traverse the stage. There are a few helper functions for taking action on descendant paths but they all assume you have a vector of all of the paths you care about rather than actually handling traversal themselves and just check for a particular prefix to say "yup, this is descendant" in that list you provide.
for (const auto& path : resyncedPaths) { | ||
if (path.IsPrimPath()) { | ||
if (UsdUtil::primExists(path)) { | ||
onPrimAdded(path); | ||
} else { | ||
onPrimRemoved(path); | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Much cleaner. I like it.
// This comes up when a tileset with imagery is moved or renamed. | ||
const auto stage = UsdUtil::getUsdStage(); | ||
const auto prim = stage->GetPrimAtPath(primPath); | ||
for (const auto& descendant : prim.GetAllDescendants()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't think of this before, but do we have to use GetAllDescendants()
here instead of something more performant like GetAllChildren()
? Ultimately, anything that relies on subtree range iteration is going to be less performant than direct traversal, but that may be what we actually need here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we need to use GetAllDescendants()
here
Say the tree looks like
- RandomXForm_1
- RandomXForm_2
- Tileset_1
- Imagery_1
- Tileset_1
- RandomXForm_2
If RandomXForm_1
is renamed to MyXForm
we need to handle all tilesets and imagery in the subtree.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense. Although I'm wondering what the difference is between GetAllChildren()
and GetAllDescendants()
then. Not something to worry about for this PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Though I just realized the scenario above won't work at all due to a bug. The type check shouldn't be surrounding the whole body.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, you're totally right, this should be GetAllChildren
. At one point this function wasn't recursive and GetAllDescendants
made more sense. I pushed a fix for that and my comment above.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Dismissing my approval pending a bug fix.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch with that bug. 🚢
Fixes #174. Review #204 first.
I tested a variety of situations while working on this PR: