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

T bailp/maya 112769/usd prim selectability #1673

Merged
merged 9 commits into from
Aug 31, 2021
9 changes: 9 additions & 0 deletions lib/mayaUsd/render/vp2RenderDelegate/proxyRenderDelegate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <mayaUsd/base/tokens.h>
#include <mayaUsd/nodes/proxyShapeBase.h>
#include <mayaUsd/nodes/stageData.h>
#include <mayaUsd/utils/selectability.h>
#include <mayaUsd/utils/util.h>

#include <pxr/base/tf/diagnostic.h>
Expand Down Expand Up @@ -896,6 +897,8 @@ void ProxyRenderDelegate::updateSelectionGranularity(
const MDagPath& path,
MHWRender::MSelectionContext& selectionContext)
{
Selectability::prepareForSelection();

// The component level is coarse-grain, causing Maya to produce undesired face/edge selection
// hits, as well as vertex selection hits that are required for point snapping. Switch to the
// new vertex selection level if available in order to produce vertex selection hits only.
Expand Down Expand Up @@ -1012,6 +1015,12 @@ bool ProxyRenderDelegate::getInstancedSelectionPath(
UsdPrim prim = _proxyShapeData->UsdStage()->GetPrimAtPath(usdPath);
const UsdPrim topLevelPrim = _proxyShapeData->UsdStage()->GetPrimAtPath(topLevelPath);

// Enforce selectability metadata.
if (!Selectability::isSelectable(prim)) {
dagPath = MDagPath();
return true;
}

// Resolve the selection based on the point instances pick mode.
// Note that in all cases except for "Instances" when the picked
// PointInstancer is *not* an instance proxy, we reset the instanceIndex to
Expand Down
12 changes: 11 additions & 1 deletion lib/mayaUsd/utils/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ target_sources(${PROJECT_NAME}
diagnosticDelegate.cpp
query.cpp
plugRegistryHelper.cpp
selectability.cpp
stageCache.cpp
undoHelperCommand
util.cpp
Expand All @@ -23,16 +24,20 @@ set(HEADERS
customLayerData.h
converter.h
diagnosticDelegate.h
hash.h
query.h
plugRegistryHelper.h
selectability.h
stageCache.h
undoHelperCommand.h
util.h
utilFileSystem.h
utilSerialization.h
hash.h
)

set(PLUGINFO
plugInfo.json)

# -----------------------------------------------------------------------------
# promote headers
# -----------------------------------------------------------------------------
Expand All @@ -44,3 +49,8 @@ mayaUsd_promoteHeaderList(HEADERS ${HEADERS} SUBDIR utils)
install(FILES ${HEADERS}
DESTINATION ${CMAKE_INSTALL_PREFIX}/include/${PROJECT_NAME}/utils/
)

install(FILES ${PLUGINFO}
DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/usd/mayaUsd_Utils/resources
)

21 changes: 21 additions & 0 deletions lib/mayaUsd/utils/plugInfo.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# plugInfo.json
{
"Plugins": [
{
"Info": {
"SdfMetadata": {
# Selectability controls Maya viewport selectability with the mouse.
# It is enforced via the ProxyRenderDelegate via its getInstancedSelectionPath()
# function.
"mayaSelectability": {
"type": "token",
"appliesTo": "prims"
}
}
},
"Name": "MayaUsdRenderMetadata",
"Type": "resource"
}
]
}

108 changes: 108 additions & 0 deletions lib/mayaUsd/utils/selectability.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
//
// Copyright 2021 Autodesk
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#include "selectability.h"

#include <pxr/base/tf/hashmap.h>

PXR_NAMESPACE_OPEN_SCOPE

/*! \brief The tokens used in the selectability metadata.
*/
TfToken Selectability::MetadataToken("mayaSelectability");
TfToken Selectability::InheritToken("inherit");
TfToken Selectability::OnToken("on");
TfToken Selectability::OffToken("off");

namespace {
// Very simple selectability cache for prims to avoid rechecking the metadata.
using Data = bool;
using SelectabilityCache = TfHashMap<UsdPrim, Data, boost::hash<UsdPrim>>;

// Use a function to retrieve the cache, as this exploits the C++ guaranteed
// initialization of static in funtions.
SelectabilityCache& getCache()
{
static SelectabilityCache cache;
return cache;
}

void clearCache() { getCache().clear(); }

// Check selectability for a prim and recurse to parent if inheriting.
bool isSelectableUncached(UsdPrim prim)
{
const Selectability::State state = Selectability::getLocalState(prim);
switch (state) {
case Selectability::kOn: return true;
case Selectability::kOff: return false;
case Selectability::kInherit: return Selectability::isSelectable(prim.GetParent());
default:
TF_CODING_ERROR("Unsupported selectability enum value: %d", (int)state);
return Selectability::isSelectable(prim.GetParent());
}
}
} // namespace

/*! \brief Do any internal preparation for selection needed.
*/
void Selectability::prepareForSelection() { clearCache(); }

/*! \brief Compute the selectability of a prim, considering inheritance.
*/
bool Selectability::isSelectable(UsdPrim prim)
{
// The reason we treat invalid prim as selectable is two-fold:
//
// - We loop inheritance until we reach an invalid parent prim, and prim are selectable
// by default.
// - We don't want to influence selectability of things that are not prim that are being
// tested by accident.
if (!prim.IsValid())
return true;

auto& cache = getCache();
const auto pos = cache.find(prim);
if (pos != cache.end())
return pos->second;

const bool selectable = isSelectableUncached(prim);
cache[prim] = selectable;
return selectable;
}

/*! \brief Retrieve the local selectability state of a prim, without any inheritance.
*/
Selectability::State Selectability::getLocalState(const UsdPrim& prim)
{
TfToken selectability;
if (!prim.GetMetadata(MetadataToken, &selectability))
return kInherit;

if (selectability == OffToken) {
return kOff;
} else if (selectability == OnToken) {
return kOn;
} else if (selectability == InheritToken) {
return kInherit;
} else {
TF_WARN(
"Invalid token value for maya selectability will be treated as inherit: %s",
selectability.data());
return kInherit;
}
}

PXR_NAMESPACE_CLOSE_SCOPE
61 changes: 61 additions & 0 deletions lib/mayaUsd/utils/selectability.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
//
// Copyright 2021 Autodesk
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#ifndef MAYAUSD_SELECTABILITY_H
#define MAYAUSD_SELECTABILITY_H

#include <pxr/base/tf/token.h>
#include <pxr/usd/usd/prim.h>

PXR_NAMESPACE_OPEN_SCOPE

/*! \brief Determine the selectability status of a prim.
*/

class Selectability
{
public:
/*! \brief The possible states of selectability.
*/
enum State
{
kInherit,
kOn,
kOff
};

/*! \brief The tokens used in the selectability metadata.
*/
static TfToken MetadataToken;
static TfToken InheritToken;
static TfToken OnToken;
static TfToken OffToken;

/*! \brief Prepare any internal data needed for selection prior to selection queries.
*/
static void prepareForSelection();

/*! \brief Compute the selectability of a prim, considering inheritance.
*/
static bool isSelectable(UsdPrim prim);

/*! \brief Retrieve the local selectability state of a prim, without any inheritance.
*/
static State getLocalState(const UsdPrim& prim);
};

PXR_NAMESPACE_CLOSE_SCOPE

#endif // MAYAUSD_SELECTABILITY_H
2 changes: 2 additions & 0 deletions test/lib/mayaUsd/render/vp2RenderDelegate/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ list(APPEND TEST_SCRIPT_FILES
if(CMAKE_UFE_V2_FEATURES_AVAILABLE)
list(APPEND TEST_SCRIPT_FILES
testVP2RenderDelegateDuplicateProxy.py
testVP2RenderDelegateSelectability.py
testVP2RenderDelegateSelectabilityPointInstanceSelection.py
testVP2RenderDelegateInteractiveWorkflows.py
)
endif()
Expand Down
Loading