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

Disconnected Fvp::PathInterface in code base, replaced with path mapper. #215

Open
wants to merge 1 commit into
base: dev
Choose a base branch
from
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,11 @@ class BlockPrimRemovalPropagationSceneIndex : public PXR_NS::HdSingleInputFilter
//from PathInterface
FVP_API
PrimSelections UfePathToPrimSelections(const Ufe::Path& appPath) const override{
return _pathInterface->UfePathToPrimSelections(appPath);
PXR_NAMESPACE_USING_DIRECTIVE

TF_FATAL_ERROR("Illegal call to deprecated %s", TF_FUNC_NAME().data());

return PrimSelections();
}

protected:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
//Local headers
#include "fvpLightsManagementSceneIndex.h"

#include <flowViewport/selection/fvpPathMapperRegistry.h>

//USD/Hydra headers
#include <pxr/imaging/hd/tokens.h>
#include <pxr/imaging/hd/retainedDataSource.h>
Expand Down Expand Up @@ -125,7 +127,7 @@ HdSceneIndexPrim LightsManagementSceneIndex::GetPrim(const SdfPath& primPath) co
//Convert ufe selection to SdfPath
SdfPathVector selectedLightsSdfPath;
for (const auto& snItem : ufeSelection) {
auto primSelections = _pathInterface.UfePathToPrimSelections(snItem->path());
auto primSelections = ufePathToPrimSelections(snItem->path());
for (const auto& primSelection : primSelections) {
selectedLightsSdfPath.push_back(primSelection.primPath);
}
Expand Down
22 changes: 2 additions & 20 deletions lib/flowViewport/sceneIndex/fvpMergingSceneIndex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,26 +36,8 @@ MergingSceneIndex::MergingSceneIndex() : HdMergingSceneIndex()

PrimSelections MergingSceneIndex::UfePathToPrimSelections(const Ufe::Path& appPath) const
{
// FLOW_VIEWPORT_TODO May be able to use a caching scheme for app path to
// scene index path conversion using the run-time ID of the UFE path, as it
// is likely that the input scene index that provided a previous answer
// will do so again. To be determined if the following direct approach has
// a measurable performance impact. PPT, 18-Sep-2023.

// Iterate over input scene indices and ask them to convert the path if
// they support the path interface.
auto inputScenes = GetInputScenes();
for (const auto& inputScene : inputScenes) {
// Unfortunate that we have to dynamic cast, as soon as we add an input
// scene we know whether it supports the PathInterface or not.
auto pathInterface = dynamic_cast<const PathInterface*>(&*inputScene);
if (pathInterface) {
auto primSelections = pathInterface->UfePathToPrimSelections(appPath);
if (!primSelections.empty()) {
return primSelections;
}
}
}
TF_FATAL_ERROR("Illegal call to deprecated %s", TF_FUNC_NAME().data());

return PrimSelections();
}

Expand Down
4 changes: 2 additions & 2 deletions lib/flowViewport/sceneIndex/fvpPathInterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ PathInterface::~PathInterface() {}
SdfPath PathInterface::SceneIndexPath(const Ufe::Path& appPath) const
{
auto primSelections = UfePathToPrimSelections(appPath);
if (!TF_VERIFY(primSelections.size() <= 1u)) {
throw PrimPathsCountOutOfRangeException(0, 1, primSelections.size());
if (!TF_VERIFY(primSelections.size() <= 2u)) {
throw PrimPathsCountOutOfRangeException(0, 2, primSelections.size());
}
return primSelections.empty() ? SdfPath() : primSelections.front().primPath;
}
Expand Down
22 changes: 11 additions & 11 deletions lib/flowViewport/sceneIndex/fvpPathInterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ namespace FVP_NS_DEF {
///
class PathInterface
{
public:
protected:

//! Return the prim path(s) corresponding to the argument application path,
//! as well as their associated selection data source(s).
Expand All @@ -52,26 +52,26 @@ class PathInterface
FVP_API
virtual PrimSelections UfePathToPrimSelections(const Ufe::Path& appPath) const = 0;

protected:

FVP_API
PathInterface() = default;

FVP_API
virtual ~PathInterface();

private:

//! Return the prim path corresponding to the argument application path,
//! for when an application path maps to at most a single prim path.
//! If no such path exists, an empty SdfPath should be returned.
//! \return Scene index path.
FVP_API
PXR_NS::SdfPath SceneIndexPath(const Ufe::Path& appPath) const;

//! Return the prim paths corresponding to the argument application path.
//! If no such paths exist, an empty SdfPathVector should be returned.
//! \return Scene index paths.
FVP_API
PXR_NS::SdfPathVector SceneIndexPaths(const Ufe::Path& appPath) const;

protected:

FVP_API
PathInterface() = default;

FVP_API
virtual ~PathInterface();
};

class PrimPathsCountOutOfRangeException : public std::out_of_range
Expand Down
19 changes: 2 additions & 17 deletions lib/flowViewport/sceneIndex/fvpSelectionSceneIndex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -269,25 +269,10 @@ bool SelectionSceneIndex::HasFullySelectedAncestorInclusive(const SdfPath& primP

PrimSelections SelectionSceneIndex::UfePathToPrimSelections(const Ufe::Path& appPath) const
{
auto primSelections = _inputSceneIndexPathInterface->UfePathToPrimSelections(appPath);
auto primSelections = ufePathToPrimSelections(appPath);

if (primSelections.empty()) {
// Path interface of input scene index didn't provide information.
// Try path mapper registry.
auto mapper = Fvp::PathMapperRegistry::Instance().GetMapper(appPath);

auto warnEmptyPath = [](const Ufe::Path& appPath) {
TF_WARN("SelectionSceneIndex::UfePathToPrimSelections(%s) returned no path, Hydra selection will be incorrect", Ufe::PathString::string(appPath).c_str());
};

if (!mapper) {
warnEmptyPath(appPath);
} else {
primSelections = mapper->UfePathToPrimSelections(appPath);
if (primSelections.empty()) {
warnEmptyPath(appPath);
}
}
TF_WARN("SelectionSceneIndex::UfePathToPrimSelections(%s) returned no path, Hydra selection will be incorrect", Ufe::PathString::string(appPath).c_str());
}

return primSelections;
Expand Down
4 changes: 4 additions & 0 deletions lib/flowViewport/selection/fvpPathMapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ namespace FVP_NS_DEF {

class PathMapper : public PathInterface
{
public:

using PathInterface::UfePathToPrimSelections;

protected:

FVP_API
Expand Down
94 changes: 82 additions & 12 deletions lib/flowViewport/selection/fvpPathMapperRegistry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ PXR_NAMESPACE_OPEN_SCOPE
TF_INSTANTIATE_SINGLETON(Fvp::PathMapperRegistry);
PXR_NAMESPACE_CLOSE_SCOPE

PXR_NAMESPACE_USING_DIRECTIVE

namespace FVP_NS_DEF {

/* static */
Expand All @@ -58,6 +60,17 @@ bool PathMapperRegistry::Unregister(const Ufe::Path& prefix)
return mappers.remove(prefix) != nullptr;
}

bool PathMapperRegistry::Update(const Ufe::Path& oldPrefix, const Ufe::Path& newPrefix)
{
auto mapper = GetMapper(oldPrefix);
if (!mapper) {
return false;
}
TF_AXIOM(Unregister(oldPrefix));
TF_AXIOM(Register(newPrefix, mapper));
return true;
}

void PathMapperRegistry::SetFallbackMapper(
const PathMapperConstPtr& pathMapper
)
Expand All @@ -70,14 +83,12 @@ PathMapperConstPtr PathMapperRegistry::GetFallbackMapper() const
return fallbackMapper;
}

PathMapperConstPtr PathMapperRegistry::GetMapper(const Ufe::Path& path) const
PathMapperConstPtr PathMapperRegistry::_GetMapper(const Ufe::Path& path) const
{
if (path.empty()) {
return nullptr;
}
TF_AXIOM(!path.empty());

if (mappers.empty()) {
return fallbackMapper;
return nullptr;
}

// We are looking for the closest ancestor of the argument. Internal trie
Expand All @@ -90,7 +101,7 @@ PathMapperConstPtr PathMapperRegistry::GetMapper(const Ufe::Path& path) const
// If we've reached a trie leaf node before the end of our path, there
// is no trie node with data as ancestor of the path.
if (!child) {
return fallbackMapper;
return nullptr;
}
trieNode = child;

Expand All @@ -101,28 +112,87 @@ PathMapperConstPtr PathMapperRegistry::GetMapper(const Ufe::Path& path) const
}
// We reached the end of the parent path without returning true, therefore
// there are no ancestors.
return fallbackMapper;
return nullptr;
}

PathMapperConstPtr PathMapperRegistry::GetMapper(const Ufe::Path& path) const
{
if (path.empty()) {
return nullptr;
}

auto mapper = _GetMapper(path);
return mapper ? mapper : fallbackMapper;
}

Fvp::PrimSelections ufePathToPrimSelections(const Ufe::Path& appPath)
PrimSelections PathMapperRegistry::UfePathToPrimSelections(
const Ufe::Path& appPath
)
{
PXR_NAMESPACE_USING_DIRECTIVE
if (appPath.empty()) {
return {};
}

Fvp::PrimSelections primSelections;
PrimSelections primSelections;

auto mapper = Fvp::PathMapperRegistry::Instance().GetMapper(appPath);
auto mapper = GetMapper(appPath);

if (!mapper) {
TF_WARN("No registered mapping for path %s, no prim path returned.", Ufe::PathString::string(appPath).c_str());
}
else {
primSelections = mapper->UfePathToPrimSelections(appPath);
if (primSelections.empty()) {
TF_WARN("Mapping for path %s returned no prim path.", Ufe::PathString::string(appPath).c_str());

mapper = GetFallbackMapper();

if (!mapper) {
TF_WARN("No registered fallback mapping, no prim path returned.");
}
else {
primSelections = mapper->UfePathToPrimSelections(appPath);
if (primSelections.empty()) {
TF_WARN("Mapping for path %s returned no prim path.", Ufe::PathString::string(appPath).c_str());
}
}
}
}

return primSelections;
}

bool PathMapperRegistry::HasMapper(const Ufe::Path& path) const
{
if (path.empty()) {
return false;
}
return _GetMapper(path) != nullptr;
}

PrimSelections ufePathToPrimSelections(const Ufe::Path& appPath)
{
return PathMapperRegistry::Instance().UfePathToPrimSelections(appPath);
}

SdfPathVector sceneIndexPaths(const Ufe::Path& appPath)
{
auto primSelections = ufePathToPrimSelections(appPath);

SdfPathVector outVector;
outVector.reserve(primSelections.size());
for (const auto& primSelection : primSelections) {
outVector.emplace_back(primSelection.primPath);
}
return outVector;
}

SdfPath sceneIndexPath(const Ufe::Path& appPath)
{
auto primSelections = ufePathToPrimSelections(appPath);
if (!TF_VERIFY(primSelections.size() <= 2u)) {
throw PrimPathsCountOutOfRangeException(0, 2, primSelections.size());
}
return primSelections.empty() ? SdfPath() : primSelections.front().primPath;
}

}
49 changes: 45 additions & 4 deletions lib/flowViewport/selection/fvpPathMapperRegistry.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,22 +68,41 @@ class PathMapperRegistry {
FVP_API
bool Unregister(const Ufe::Path& prefix);

//! Update path mapper with new prefix.
/*!
\return False if old prefix was not found in the registry, true otherwise.
*/
FVP_API
bool Update(const Ufe::Path& oldPrefix, const Ufe::Path& newPrefix);

//! Set a fallback path mapper. If set, it will be returned by
//! GetMapper() if no mapper is registered for a given argument path.
//! The fallback mapper is also invoked by UfePathToPrimSelections()
//! if the prefix-registered mapper returns an empty result.
//! A null pointer argument removes the fallback path mapper.
FVP_API
void SetFallbackMapper(const PathMapperConstPtr& pathMapper);
FVP_API
PathMapperConstPtr GetFallbackMapper() const;

//! Get a path mapper for the argument application path. This
//! mapper has a prefix that is an ancestor of the argument path. If no
//! path mapper is found, returns a null pointer.
FVP_API
PathMapperConstPtr GetMapper(const Ufe::Path& path) const;
PrimSelections UfePathToPrimSelections(const Ufe::Path& appPath);

//! Testing interface
FVP_API
bool HasMapper(const Ufe::Path& path) const;

private:

//! Calls _GetMapper(). If no path mapper is found, returns the
//! fallback path mapper.
PathMapperConstPtr GetMapper(const Ufe::Path& path) const;

//! Get a path mapper for the argument application path. This
//! mapper has a prefix that is an ancestor of the argument path. If no
//! path mapper is found, returns a null pointer.
PathMapperConstPtr _GetMapper(const Ufe::Path& path) const;

PathMapperRegistry() = default;
~PathMapperRegistry() = default;
PathMapperRegistry(const PathMapperRegistry&) = delete;
Expand All @@ -107,6 +126,28 @@ class PathMapperRegistry {
FVP_API
PrimSelections ufePathToPrimSelections(const Ufe::Path& appPath);

/**
* @brief Get the prim paths for a given application path.
*
* Calls ufePathToPrimSelections, then extracts the Hydra prim paths.
*
* @param[in] appPath The application path for which prim selections should be returned.
* @return Zero or more prim paths.
*/
FVP_API
PXR_NS::SdfPathVector sceneIndexPaths(const Ufe::Path& appPath);

/**
* @brief Get the first prim path for a given application path.
*
* Calls ufePathToPrimSelections, then extracts the first Hydra prim path.
*
* @param[in] appPath The application path for which prim selections should be returned.
* @return A prim path, empty if no prim path corresponds to the argument.
*/
FVP_API
PXR_NS::SdfPath sceneIndexPath(const Ufe::Path& appPath);

}

#endif
Loading