Skip to content

Commit

Permalink
Merge pull request #237 from Autodesk/tremblp/MAYA-102361/rename_fixes
Browse files Browse the repository at this point in the history
Tremblp/maya 102361/rename fixes
  • Loading branch information
Krystian Ligenza authored Feb 11, 2020
2 parents 4a8f0a7 + 30db4e2 commit b83b17f
Show file tree
Hide file tree
Showing 15 changed files with 454 additions and 80 deletions.
6 changes: 5 additions & 1 deletion lib/ufe/Global.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
#include "UsdTransform3dHandler.h"
#include "UsdSceneItemOpsHandler.h"

#include <ufe/rtid.h>
#include <ufe/runTimeMgr.h>
#include <ufe/hierarchyHandler.h>
#include <ufe/ProxyShapeHierarchyHandler.h>
Expand Down Expand Up @@ -130,5 +129,10 @@ MStatus finalize()
return MS::kSuccess;
}

Ufe::Rtid getUsdRunTimeId()
{
return g_USDRtid;
}

} // namespace ufe
} // namespace MayaUsd
6 changes: 6 additions & 0 deletions lib/ufe/Global.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@

#include "../base/api.h"

#include <ufe/rtid.h>

#include <maya/MStatus.h>

MAYAUSD_NS_DEF {
Expand All @@ -32,5 +34,9 @@ MStatus initialize();
MAYAUSD_CORE_PUBLIC
MStatus finalize();

//! Return the run-time ID allocated to USD.
MAYAUSD_CORE_PUBLIC
Ufe::Rtid getUsdRunTimeId();

} // namespace ufe
} // namespace MayaUsd
22 changes: 19 additions & 3 deletions lib/ufe/ProxyShapeHierarchy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "ProxyShapeHierarchy.h"
#include "Utils.h"

#include <ufe/log.h>
#include <ufe/pathComponent.h>
#include <ufe/pathSegment.h>
#include <ufe/rtid.h>
Expand All @@ -37,7 +38,9 @@ extern Ufe::Rtid g_USDRtid;
// ProxyShapeHierarchy
//------------------------------------------------------------------------------

ProxyShapeHierarchy::ProxyShapeHierarchy(Ufe::HierarchyHandler::Ptr mayaHierarchyHandler)
ProxyShapeHierarchy::ProxyShapeHierarchy(
const Ufe::HierarchyHandler::Ptr& mayaHierarchyHandler
)
: Ufe::Hierarchy()
, fMayaHierarchyHandler(mayaHierarchyHandler)
{
Expand All @@ -48,11 +51,22 @@ ProxyShapeHierarchy::~ProxyShapeHierarchy()
}

/*static*/
ProxyShapeHierarchy::Ptr ProxyShapeHierarchy::create(Ufe::HierarchyHandler::Ptr mayaHierarchyHandler)
ProxyShapeHierarchy::Ptr ProxyShapeHierarchy::create(const Ufe::HierarchyHandler::Ptr& mayaHierarchyHandler)
{
return std::make_shared<ProxyShapeHierarchy>(mayaHierarchyHandler);
}

/*static*/
ProxyShapeHierarchy::Ptr ProxyShapeHierarchy::create(
const Ufe::HierarchyHandler::Ptr& mayaHierarchyHandler,
const Ufe::SceneItem::Ptr& item
)
{
auto hierarchy = create(mayaHierarchyHandler);
hierarchy->setItem(item);
return hierarchy;
}

void ProxyShapeHierarchy::setItem(const Ufe::SceneItem::Ptr& item)
{
// Our USD root prim is from the stage, which is from the item. So if we are
Expand Down Expand Up @@ -95,8 +109,10 @@ Ufe::SceneItem::Ptr ProxyShapeHierarchy::sceneItem() const
bool ProxyShapeHierarchy::hasChildren() const
{
const UsdPrim& rootPrim = getUsdRootPrim();
if (!rootPrim.IsValid())
if (!rootPrim.IsValid()) {
UFE_LOG("invalid root prim in ProxyShapeHierarchy::hasChildren()");
return false;
}
return !rootPrim.GetChildren().empty();
}

Expand Down
8 changes: 6 additions & 2 deletions lib/ufe/ProxyShapeHierarchy.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class MAYAUSD_CORE_PUBLIC ProxyShapeHierarchy : public Ufe::Hierarchy
public:
typedef std::shared_ptr<ProxyShapeHierarchy> Ptr;

ProxyShapeHierarchy(Ufe::HierarchyHandler::Ptr mayaHierarchyHandler);
ProxyShapeHierarchy(const Ufe::HierarchyHandler::Ptr& mayaHierarchyHandler);
~ProxyShapeHierarchy() override;

// Delete the copy/move constructors assignment operators.
Expand All @@ -48,7 +48,11 @@ class MAYAUSD_CORE_PUBLIC ProxyShapeHierarchy : public Ufe::Hierarchy
ProxyShapeHierarchy& operator=(ProxyShapeHierarchy&&) = delete;

//! Create a ProxyShapeHierarchy from a UFE hierarchy handler.
static ProxyShapeHierarchy::Ptr create(Ufe::HierarchyHandler::Ptr mayaHierarchyHandler);
static ProxyShapeHierarchy::Ptr create(const Ufe::HierarchyHandler::Ptr& mayaHierarchyHandler);
static ProxyShapeHierarchy::Ptr create(
const Ufe::HierarchyHandler::Ptr& mayaHierarchyHandler,
const Ufe::SceneItem::Ptr& item
);

void setItem(const Ufe::SceneItem::Ptr& item);

Expand Down
9 changes: 4 additions & 5 deletions lib/ufe/ProxyShapeHierarchyHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,15 @@
#include "ProxyShapeHierarchyHandler.h"
#include "Utils.h"

#include <ufe/ProxyShapeHierarchy.h>

MAYAUSD_NS_DEF {
namespace ufe {

ProxyShapeHierarchyHandler::ProxyShapeHierarchyHandler(Ufe::HierarchyHandler::Ptr mayaHierarchyHandler)
: Ufe::HierarchyHandler()
, fMayaHierarchyHandler(mayaHierarchyHandler)
{
fProxyShapeHierarchy = ProxyShapeHierarchy::create(mayaHierarchyHandler);
}
{}

ProxyShapeHierarchyHandler::~ProxyShapeHierarchyHandler()
{
Expand All @@ -45,8 +45,7 @@ Ufe::Hierarchy::Ptr ProxyShapeHierarchyHandler::hierarchy(const Ufe::SceneItem::
{
if (isAGatewayType(item->nodeType()))
{
fProxyShapeHierarchy->setItem(item);
return fProxyShapeHierarchy;
return ProxyShapeHierarchy::create(fMayaHierarchyHandler, item);
}
else
{
Expand Down
2 changes: 0 additions & 2 deletions lib/ufe/ProxyShapeHierarchyHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
#include "../base/api.h"

#include <ufe/hierarchyHandler.h>
#include <ufe/ProxyShapeHierarchy.h>

MAYAUSD_NS_DEF {
namespace ufe {
Expand Down Expand Up @@ -59,7 +58,6 @@ class MAYAUSD_CORE_PUBLIC ProxyShapeHierarchyHandler : public Ufe::HierarchyHand

private:
Ufe::HierarchyHandler::Ptr fMayaHierarchyHandler;
ProxyShapeHierarchy::Ptr fProxyShapeHierarchy;

}; // ProxyShapeHierarchyHandler

Expand Down
44 changes: 24 additions & 20 deletions lib/ufe/StagesSubject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -196,32 +196,36 @@ void StagesSubject::stageChanged(UsdNotice::ObjectsChanged const& notice, UsdSta
for (const auto& changedPath : notice.GetResyncedPaths())
{
const std::string& usdPrimPathStr = changedPath.GetPrimPath().GetString();
// Assume proxy shapes (and thus stages) cannot be instanced. We can
// therefore map the stage to a single UFE path. Lifting this
// restriction would mean sending one add or delete notification for
// each Maya Dag path instancing the proxy shape / stage.
Ufe::Path ufePath = stagePath(sender) + Ufe::PathSegment(usdPrimPathStr, g_USDRtid, '/');
auto prim = stage->GetPrimAtPath(changedPath);
// Changed paths could be xformOps.
// These are considered as invalid null prims
if (prim.IsValid() && !InPathChange::inPathChange())
{
auto sceneItem = Ufe::Hierarchy::createItem(ufePath);

// AL LayerCommands.addSubLayer test will cause Maya to crash
// if we don't filter invalid sceneItems. This patch is provided
// to prevent crashes, but more investigation will have to be
// done to understand why ufePath in case of sub layer
// creation causes Ufe::Hierarchy::createItem to fail.
if (!sceneItem)
continue;

if (prim.IsActive())
{
auto notification = Ufe::ObjectAdd(sceneItem);
Ufe::Scene::notifyObjectAdd(notification);
}
else
{
auto notification = Ufe::ObjectPostDelete(sceneItem);
Ufe::Scene::notifyObjectDelete(notification);
}
auto sceneItem = Ufe::Hierarchy::createItem(ufePath);

// AL LayerCommands.addSubLayer test will cause Maya to crash
// if we don't filter invalid sceneItems. This patch is provided
// to prevent crashes, but more investigation will have to be
// done to understand why ufePath in case of sub layer
// creation causes Ufe::Hierarchy::createItem to fail.
if (!sceneItem)
continue;

if (prim.IsActive())
{
auto notification = Ufe::ObjectAdd(sceneItem);
Ufe::Scene::notifyObjectAdd(notification);
}
else
{
auto notification = Ufe::ObjectPostDelete(sceneItem);
Ufe::Scene::notifyObjectDelete(notification);
}
}
}

Expand Down
80 changes: 71 additions & 9 deletions lib/ufe/UsdStageMap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,43 @@
//

#include "UsdStageMap.h"
#include "Utils.h"

#include <maya/MFnDagNode.h>

#include <cassert>

namespace {

MObjectHandle proxyShapeHandle(const Ufe::Path& path)
{
// Get the MObjectHandle from the tail of the MDagPath. Remove the leading
// '|world' component.
auto noWorld = path.popHead().string();
auto dagPath = MayaUsd::ufe::nameToDagPath(noWorld);
MObjectHandle handle(dagPath.node());
if (!handle.isValid()) {
TF_CODING_ERROR("'%s' is not a path to a proxy shape node.",
noWorld.c_str());
}
return handle;
}

// Assuming proxy shape nodes cannot be instanced, simply return the first path.
Ufe::Path firstPath(const MObjectHandle& handle)
{
if (!TF_VERIFY(handle.isValid(),
"Cannot get path from invalid object handle")) {
return Ufe::Path();
}

MDagPath dagPath;
auto status = MFnDagNode(handle.object()).getPath(dagPath);
CHECK_MSTATUS(status);
return MayaUsd::ufe::dagPathToUfe(dagPath);
}

}

MAYAUSD_NS_DEF {
namespace ufe {
Expand All @@ -31,32 +68,57 @@ UsdStageMap g_StageMap;

void UsdStageMap::addItem(const Ufe::Path& path, UsdStageWeakPtr stage)
{
fPathToStage[path] = stage;
fStageToPath[stage] = path;
// We expect a path to the proxy shape node, therefore a single segment.
auto nbSegments =
#ifdef UFE_V0_2_6_FEATURES_AVAILABLE
path.nbSegments();
#else
path.getSegments().size();
#endif
if (nbSegments != 1) {
TF_CODING_ERROR("A proxy shape node path can have only one segment, path '%s' has %lu", path.string().c_str(), nbSegments);
return;
}

// Convert the tail of the UFE path to an MObjectHandle.
auto proxyShape = proxyShapeHandle(path);
if (!proxyShape.isValid()) {
return;
}

// Could get the stage from the proxy shape object in the stage() method,
// but since it's given here, simply store it.
fObjectToStage[proxyShape] = stage;
fStageToObject[stage] = proxyShape;
}

UsdStageWeakPtr UsdStageMap::stage(const Ufe::Path& path) const
{
auto proxyShape = proxyShapeHandle(path);
if (!proxyShape.isValid()) {
return nullptr;
}

// A stage is bound to a single Dag proxy shape.
auto iter = fPathToStage.find(path);
if (iter != std::end(fPathToStage))
auto iter = fObjectToStage.find(proxyShape);
if (iter != std::end(fObjectToStage))
return iter->second;
return nullptr;
}

Ufe::Path UsdStageMap::path(UsdStageWeakPtr stage) const
{
// A stage is bound to a single Dag proxy shape.
auto iter = fStageToPath.find(stage);
if (iter != std::end(fStageToPath))
return iter->second;
auto iter = fStageToObject.find(stage);
if (iter != std::end(fStageToObject))
return firstPath(iter->second);
return Ufe::Path();
}

void UsdStageMap::clear()
{
fPathToStage.clear();
fStageToPath.clear();
fObjectToStage.clear();
fStageToObject.clear();
}

} // namespace ufe
Expand Down
35 changes: 26 additions & 9 deletions lib/ufe/UsdStageMap.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,22 +22,37 @@
#include <pxr/usd/usd/stage.h>
#include <pxr/base/tf/hash.h>

#include <maya/MObjectHandle.h>

#include <unordered_map>

// Allow for use of MObjectHandle with std::unordered_map.
namespace std {
template <> struct hash<MObjectHandle> {
std::size_t operator()(const MObjectHandle& handle) const {
return static_cast<std::size_t>(handle.hashCode());
}
};
}

PXR_NAMESPACE_USING_DIRECTIVE

MAYAUSD_NS_DEF {
namespace ufe {

//! \brief USD Stage Map
/*!
Map of AL_usdmaya_ProxyShape UFE path to corresponding stage.
Map of stage to corresponding AL_usdmaya_ProxyShape UFE path. Ideally, we
would support dynamically computing the path for the AL_usdmaya_ProxyShape
node, but we assume here it will not be reparented. We will also assume that
a USD stage will not be instanced (even though nothing in the data model
prevents it).
Two-way map of proxy shape UFE path to corresponding stage.
We will assume that a USD proxy shape will not be instanced (even though
nothing in the data model prevents it). To support renaming and repathing,
we store an MObjectHandle in the maps, which is invariant to renaming and
repathing, and compute the path on access. This is slower than a scheme
where we cache using the Ufe::Path, but such a cache must be refreshed on
rename and repath, which is non-trivial, since there is no guarantee on the
order of notification of Ufe observers. An earlier implementation with
rename observation had the Maya Outliner (which observes rename) access the
UsdStageMap on rename before the UsdStageMap had been updated.
*/
class MAYAUSD_CORE_PUBLIC UsdStageMap
{
Expand All @@ -64,8 +79,10 @@ class MAYAUSD_CORE_PUBLIC UsdStageMap

private:
// We keep two maps for fast lookup when there are many proxy shapes.
std::unordered_map<Ufe::Path, UsdStageWeakPtr> fPathToStage;
TfHashMap<UsdStageWeakPtr, Ufe::Path, TfHash> fStageToPath;
using ObjectToStage = std::unordered_map<MObjectHandle, UsdStageWeakPtr>;
using StageToObject = TfHashMap<UsdStageWeakPtr, MObjectHandle, TfHash>;
ObjectToStage fObjectToStage;
StageToObject fStageToObject;

}; // UsdStageMap

Expand Down
Loading

0 comments on commit b83b17f

Please sign in to comment.