Skip to content
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

Replace DataProducersNodeHashCodeToSdfPathRegistry with path mapping. #247

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions lib/flowViewport/selection/fvpPathMapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,11 @@ class PathMapper
FVP_API
virtual PrimSelections UfePathToPrimSelections(const Ufe::Path& appPath) const = 0;

//! Return the path mapper's name. Intended for debugging.
//! \return Path mapper name.
FVP_API
virtual std::string Name() const = 0;

protected:

FVP_API
Expand Down
2 changes: 1 addition & 1 deletion lib/flowViewport/selection/fvpPathMapperRegistry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ PathMapperConstPtr PathMapperRegistry::GetMapper(const Ufe::Path& path) const

PrimSelections PathMapperRegistry::UfePathToPrimSelections(
const Ufe::Path& appPath
)
) const
{
if (appPath.empty()) {
return {};
Expand Down
2 changes: 1 addition & 1 deletion lib/flowViewport/selection/fvpPathMapperRegistry.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ class PathMapperRegistry {
PathMapperConstPtr GetFallbackMapper() const;

FVP_API
PrimSelections UfePathToPrimSelections(const Ufe::Path& appPath);
PrimSelections UfePathToPrimSelections(const Ufe::Path& appPath) const;

//! Testing interface
FVP_API
Expand Down
30 changes: 18 additions & 12 deletions lib/flowViewport/selection/fvpPrefixPathMapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,44 +17,50 @@
#include <flowViewport/selection/fvpPrefixPathMapper.h>
#include <flowViewport/fvpUtils.h>

#include <ufe/pathString.h>

// Need Pixar namespace for TF_ diagnostics macros.
PXR_NAMESPACE_USING_DIRECTIVE

namespace FVP_NS_DEF {

PrefixPathMapper::PrefixPathMapper(
Ufe::Rtid rtid,
const Ufe::Path& appPathPrefix,
const PXR_NS::SdfPath& sceneIndexPathPrefix
) : _rtid(rtid), _appPathPrefix(appPathPrefix),
) : _appPathPrefix(appPathPrefix),
_sceneIndexPathPrefix(sceneIndexPathPrefix)
{}

PrimSelections PrefixPathMapper::UfePathToPrimSelections(const Ufe::Path& appPath) const
{
// We only handle scene items from our assigned run time ID.
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One of the important changes in this pull request. Restricting the path mapper to only deal with one kind of UFE data model is overly restrictive, because the main point is mapping a Ufe::Path prefix into a Hydra scene index SdfPath prefix, regardless of which data model(s) are involved. This was making the path mapping overly complex.

if (appPath.runTimeId() != _rtid) {
return {};
}

// If the data model object application path does not match the path we
// translate, return an empty path.
if (!appPath.startsWith(_appPathPrefix)) {
return {};
}

// The scene index path is composed of 2 parts, in order:
// The scene index path is composed of 2 parts, the second of which is
// optional:
// 1) The scene index path prefix, which is fixed on construction.
// 2) The second segment of the UFE path, with each UFE path component
// becoming an SdfPath component.
PXR_NS::SdfPath primPath = _sceneIndexPathPrefix;
TF_AXIOM(appPath.nbSegments() == 2);
const auto& secondSegment = appPath.getSegments()[1];
for (const auto& pathComponent : secondSegment) {
primPath = primPath.AppendChild(TfToken(pathComponent.string()));
if (appPath.nbSegments() == 2) {
const auto& secondSegment = appPath.getSegments()[1];
for (const auto& pathComponent : secondSegment) {
primPath = primPath.AppendChild(TfToken(pathComponent.string()));
}
}

return PrimSelections{PrimSelection{primPath}};
}

std::string PrefixPathMapper::Name() const
{
std::ostringstream oss;
oss << "PrefixPathMapper " << Ufe::PathString::string(_appPathPrefix)
<< " --> " << _sceneIndexPathPrefix.GetText() << std::endl;
return oss.str();
}

}
10 changes: 4 additions & 6 deletions lib/flowViewport/selection/fvpPrefixPathMapper.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// Copyright 2024 Autodesk
// Copyright 2025 Autodesk
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you don't need to change the year since this file was created in 2024, but it's very minor.

//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand All @@ -19,7 +19,6 @@
#include <flowViewport/api.h>
#include <flowViewport/selection/fvpPathMapper.h>

#include <ufe/rtid.h>
#include <ufe/path.h>

namespace FVP_NS_DEF {
Expand All @@ -28,8 +27,6 @@ namespace FVP_NS_DEF {
///
/// This simple path handler performs application path to scene index path
/// mapping by substituting a scene index prefix for an application path prefix.
/// The prefix mapper applies only to application paths of a specific UFE run
/// time.
///

class PrefixPathMapper : public PathMapper
Expand All @@ -38,17 +35,18 @@ class PrefixPathMapper : public PathMapper

FVP_API
PrefixPathMapper(
Ufe::Rtid rtid,
const Ufe::Path& appPathPrefix,
const PXR_NS::SdfPath& sceneIndexPathPrefix
);

FVP_API
PrimSelections UfePathToPrimSelections(const Ufe::Path& appPath) const override;

FVP_API
virtual std::string Name() const;

private:

const Ufe::Rtid _rtid{0}; // 0 is invalid
const Ufe::Path _appPathPrefix;
const PXR_NS::SdfPath _sceneIndexPathPrefix;
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -947,7 +947,7 @@ void MhFlowViewportAPILocator::addedToModelCb()
// for selection highlighting.
_appPath = getUfePath();
auto pathMapper = std::make_shared<Fvp::PrefixPathMapper>(
ufeRunTimeId, _appPath, _pathPrefix);
_appPath, _pathPrefix);
TF_AXIOM(Fvp::PathMapperRegistry::Instance().Register(_appPath, pathMapper));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@
//Flow viewport headers
#include <flowViewport/API/fvpVersionInterface.h>
#include <flowViewport/API/fvpDataProducerSceneIndexInterface.h>
#include <flowViewport/selection/fvpPrefixPathMapper.h>
#include <flowViewport/selection/fvpPathMapperRegistry.h>

//Hydra headers
#include <pxr/base/vt/array.h>
Expand Down Expand Up @@ -138,6 +140,8 @@ class MhFootPrint : public MPxLocatorNode
// Callback when the footprint node is removed from model (delete)
void removedFromModelCb();

Ufe::Path getUfePath() const;

//Attributes
static MObject mSize;
static MObject mWorldS;
Expand Down Expand Up @@ -176,6 +180,7 @@ class MhFootPrint : public MPxLocatorNode
MCallbackId _nodeRemovedFromModelCbId{0};

SdfPath _pathPrefix;
Ufe::Path _appPath{};
};

namespace
Expand Down Expand Up @@ -596,6 +601,13 @@ void* MhFootPrint::creator()
return new MhFootPrint();
}

Ufe::Path MhFootPrint::getUfePath() const
{
MDagPath dagPath;
TF_AXIOM(MDagPath::getAPathTo(thisMObject(), dagPath) == MS::kSuccess);
return Ufe::Path(UfeExtensions::dagPathToUfePathSegment(dagPath));
}

void MhFootPrint::addedToModelCb()
{
_pathPrefix = SdfPath(TfStringPrintf("/MhFootPrint_%p", this));
Expand All @@ -612,13 +624,20 @@ void MhFootPrint::addedToModelCb()
auto pickHandler = std::make_shared<FootPrintPickHandler>(obj);
TF_AXIOM(MayaHydra::PickHandlerRegistry::Instance().Register(_pathPrefix, pickHandler));

// No need for a path mapper: the parts of the footprint are not selectable
// individually, only the Maya shape, so the built-in Maya path mapper does
// the job of path mapping for the footprint node.
// Register a path mapper to map application UFE paths to scene index paths,
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove reliance on DataProducersNodeHashCodeToSdfPathRegistry, use path mapping instead, as is done in FlowViewportAPILocator.

// for selection highlighting.
_appPath = getUfePath();
auto pathMapper = std::make_shared<Fvp::PrefixPathMapper>(_appPath, _pathPrefix);
TF_AXIOM(Fvp::PathMapperRegistry::Instance().Register(_appPath, pathMapper));
}

void MhFootPrint::removedFromModelCb()
{
// Unregister our path mapper. Use stored UFE path, as at this point
// our locator node is no longer in the Maya scene, so we cannot obtain
// an MDagPath for it.
TF_AXIOM(Fvp::PathMapperRegistry::Instance().Unregister(_appPath));

// Unregister our pick handler.
TF_AXIOM(MayaHydra::PickHandlerRegistry::Instance().Unregister(_pathPrefix));

Expand Down
21 changes: 9 additions & 12 deletions lib/mayaHydra/hydraExtensions/sceneIndex/mayaHydraSceneIndex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,8 @@ class MayaPathMapper : public Fvp::PathMapper
return _piSi.UfePathToPrimSelections(appPath);
}

std::string Name() const { return "MayaPathMapper"; }

private:
// Non-owning reference to prevent ownership cycle.
const MayaHydraSceneIndex& _piSi;
Expand Down Expand Up @@ -788,20 +790,15 @@ Fvp::PrimSelections MayaHydraSceneIndex::UfePathToPrimSelections(const Ufe::Path
MDagPath shapeDagPath(dagPath);
shapeDagPath.extendToShape();

// Check if this Maya node has a special path mapper associated with it.
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove reliance on DataProducersNodeHashCodeToSdfPathRegistry, use path mapping instead.

Ufe::Path shapeAppPath{UfeExtensions::dagPathToUfePathSegment(shapeDagPath)};
const auto& pmr = Fvp::PathMapperRegistry::Instance();
if (pmr.HasMapper(shapeAppPath)) {
return pmr.UfePathToPrimSelections(shapeAppPath);
}

SdfPath primPath = GetPrimPath((extendToShape) ? shapeDagPath : dagPath, isSprim);

//Check if this maya node has a special SdfPath associated with it, this is for custom or maya usd data producers scene indices.
//The class MhDataProducersMayaNodeToSdfPathRegistry does a mapping between Maya nodes and USD paths.
//The maya nodes registered in this class are used by data producers as a parent to all
//primitives. This class is used when the user selects one of these
//maya nodes to return the matching SdfPath so that all prims child of this maya node are
//highlighted.

const SdfPath matchingPath = FVP_NS::DataProducersNodeHashCodeToSdfPathRegistry::Instance().GetPath(MObjectHandle(shapeDagPath.node()).hashCode());
if (! matchingPath.IsEmpty()) {
primPath = matchingPath;
}

TF_DEBUG(MAYAHYDRALIB_SCENE_INDEX)
.Msg(" mapped to scene index path %s.\n", primPath.GetText());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,8 @@ class UsdPathMapper : public Fvp::PathMapper
return _psSi.UfePathToPrimSelections(appPath);
}

std::string Name() const override { return "UsdPathMapper"; }

private:
// Non-owning reference to prevent ownership cycle.
const MayaUsdProxyShapeSceneIndex& _psSi;
Expand Down Expand Up @@ -331,18 +333,19 @@ Fvp::PrimSelections MayaUsdProxyShapeSceneIndex::UfePathToPrimSelections(
const Ufe::Path& appPath
) const
{
// We only handle USD objects, so if the UFE path is not a USD object,
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove single UFE run-time restriction, path mapping should only deal with paths.

// early out with failure.
if (appPath.runTimeId() != UfeExtensions::getUsdRunTimeId()) {
return {};
}

// If the data model object application path does not match the path we
// translate, return an empty path.
if (!appPath.startsWith(_sceneIndexAppPath)) {
return {};
}

// If the application path is our prefix, just return the
// corresponding scene index path.
if (appPath == _sceneIndexAppPath) {
return Fvp::PrimSelections{Fvp::PrimSelection{
_sceneIndexPathPrefix}};
}

// The scene index path is composed of 2 parts, in order:
// 1) The scene index path prefix, which is fixed on construction.
// 2) The second segment of the UFE path, with each UFE path component
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ class TestPathMapper : public Fvp::PathMapper {

Fvp::PrimSelections
UfePathToPrimSelections(const Ufe::Path&) const override { return {}; }

std::string Name() const { return "TestPathMapper"; }
};

}
Expand Down