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

Selection highlighting, picking of MhFootPrint node, with test. #228

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
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,14 @@
#include <maya/MGlobal.h>
#include <maya/MFnDagNode.h>
#include <maya/MModelMessage.h>
#include <maya/MDagPath.h>
#include <maya/MSelectionList.h>
#include <maya/MPointArray.h>

// MayaHydra headers.
#include <mayaHydraLib/pick/mhPickHandler.h>
#include <mayaHydraLib/pick/mhPickHandlerRegistry.h>
#include <ufeExtensions/Global.h>

//Flow viewport headers
#include <flowViewport/API/fvpVersionInterface.h>
Expand All @@ -50,6 +58,7 @@
//Hydra headers
#include <pxr/base/vt/array.h>
#include <pxr/base/gf/vec3f.h>
#include <pxr/imaging/hdx/pickTask.h>
#include <pxr/imaging/hd/tokens.h>
#include <pxr/imaging/hd/retainedSceneIndex.h>
#include <pxr/imaging/hd/retainedDataSource.h>
Expand All @@ -63,6 +72,40 @@ PXR_NAMESPACE_USING_DIRECTIVE
namespace {
void nodeAddedToModel(MObject& node, void* clientData);
void nodeRemovedFromModel(MObject& node, void* clientData);

// Pick handler for the footprint node.

class FootPrintPickHandler : public MayaHydra::PickHandler {
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Foot print node had no pick handler, picking did not work.

public:

FootPrintPickHandler(MObject& footPrintObj) : _footPrintObj(footPrintObj) {}

bool handlePickHit(
const Input& pickInput, Output& pickOutput
) const override
{
// Foot print parts are not selectable individually: only the complete
// Maya shape object is selectable.
//
// Conceptually we could append a picked Maya object either to the
// classic Maya MSelectionList selection or to the "MayaSelectTool"
// named UFE selection (which provides input for the global selection).
// However, the Maya select context filters out Maya items added to the
// "MayaSelectTool" named UFE selection, so add to the MSelectionList.
MDagPath dagPath;
TF_AXIOM(MDagPath::getAPathTo(_footPrintObj, dagPath) == MS::kSuccess);
pickOutput.mayaSelection.add(dagPath);
const auto& wsPt = pickInput.pickHit.worldSpaceHitPoint;
pickOutput.mayaWorldSpaceHitPts.append(wsPt[0], wsPt[1], wsPt[2]);

return true;
}

private:

MObject _footPrintObj;
};

}

//---------------------------------------------------------------------------
Expand Down Expand Up @@ -131,6 +174,8 @@ class MhFootPrint : public MPxLocatorNode

MCallbackId _nodeAddedToModelCbId{0};
MCallbackId _nodeRemovedFromModelCbId{0};

SdfPath _pathPrefix;
};

namespace
Expand Down Expand Up @@ -409,7 +454,8 @@ namespace {
//Trigger a call to compute so that everything is initialized
MhFootPrint* footPrintInstance = reinterpret_cast<MhFootPrint*>(clientData);
footPrintInstance->updateFootPrintPrims();
footPrintInstance->addedToModelCb();
// No need to call footPrintInstance->addedToModelCb(), as reading the
// file will add the node to the model.
}
}

Expand Down Expand Up @@ -552,19 +598,30 @@ void* MhFootPrint::creator()

void MhFootPrint::addedToModelCb()
{
static const SdfPath noPrefix = SdfPath::AbsoluteRootPath();
_pathPrefix = SdfPath(TfStringPrintf("/MhFootPrint_%p", this));
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Lack of path prefix meant that the prefix was the Hydra scene index root. Thus, when foot print node was selected, the Hydra scene index root was selected, and all its children received selection highlighting, which is the normal and correct way to highlight children of a selected prim. Unfortunately, this meant that the whole scene was selection highlighted... Fixed with a proper Hydra scene index prefix.


//Add the callback when an attribute of this node changes
MObject obj = thisMObject();
_cbAttributeChangedId = MNodeMessage::addAttributeChangedCallback(obj, attributeChangedCallback, ((void*)this));

//Data producer scene index interface is used to add the retained scene index to all viewports with all render delegates
auto& dataProducerSceneIndexInterface = Fvp::DataProducerSceneIndexInterface::get();
dataProducerSceneIndexInterface.addDataProducerSceneIndex(_retainedSceneIndex, noPrefix, (void*)&obj, FvpViewportAPITokens->allViewports,FvpViewportAPITokens->allRenderers);
dataProducerSceneIndexInterface.addDataProducerSceneIndex(_retainedSceneIndex, _pathPrefix, (void*)&obj);
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Removed default arguments.


// Register a pick handler for our prefix with the pick handler registry.
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.
}

void MhFootPrint::removedFromModelCb()
{
// Unregister our pick handler.
TF_AXIOM(MayaHydra::PickHandlerRegistry::Instance().Unregister(_pathPrefix));

//Remove the callback
if (_cbAttributeChangedId){
CHECK_MSTATUS(MMessage::removeCallback(_cbAttributeChangedId));
Expand Down
30 changes: 30 additions & 0 deletions test/lib/mayaUsd/render/mayaToHydra/cpp/testHydraPrim.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,12 @@
#include <ufe/path.h>
#include <ufe/pathString.h>

#include <pxr/imaging/hd/sceneIndexPrimView.h>

#include <gtest/gtest.h>

#include <regex>

PXR_NAMESPACE_USING_DIRECTIVE

using namespace MayaHydra;
Expand Down Expand Up @@ -108,3 +112,29 @@ TEST(TestHydraPrim, translation)
constexpr double epsilon{1e-7};
ASSERT_TRUE(GfIsClose(primTranslation, expectedTranslation, epsilon));
}

TEST(TestHydraPrim, countPrims)
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

New utility to count Hydra scene index prims, given a regular expression.

{
const auto& sceneIndices = GetTerminalSceneIndices();
auto siRoot = sceneIndices.front();

auto [argc, argv] = getTestingArgs();
ASSERT_EQ(argc, 2);

const std::regex r{argv[0]};
std::smatch m;
const int expectedNbMatches{std::stoi(argv[1])};
int nbMatches{0};

for (const auto& primPath :
HdSceneIndexPrimView(siRoot, SdfPath::AbsoluteRootPath())) {
// Can't match temporary string, see
// https://stackoverflow.com/questions/27391016
const std::string element = primPath.GetElementString();
if (std::regex_search(element, m, r)) {
++nbMatches;
}
}

ASSERT_EQ(nbMatches, expectedNbMatches);
}
35 changes: 35 additions & 0 deletions test/lib/mayaUsd/render/mayaToHydra/testFootPrintNode.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ class TestFootPrintNode(mtohUtils.MayaHydraBaseTestCase): #Subclassing mtohUtils
IMAGE_DIFF_FAIL_PERCENT = 0.1
imageVersion = None

_requiredPlugins = ['mayaHydraCppTests']

@classmethod
def setUpClass(cls):
super(TestFootPrintNode, cls).setUpClass()
Expand Down Expand Up @@ -257,5 +259,38 @@ def test_Load(self):
#using imageVersion as the color is different for this image under usd 24.11+
self.assertSnapshotClose("loadingFootPrintScene.png", self.IMAGE_DIFF_FAIL_THRESHOLD, self.IMAGE_DIFF_FAIL_PERCENT, self.imageVersion)

# Test selection highlighting. When the footprint node is selected, only
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Without the fixes for picking and selection highlighting, these two tests fail.

With the fixes, these two tests pass.

# its two Hydra scene index prims (heel and sole) should have a
# _SelectionHighlight mirror hierarchy, and no other prim.
def test_selectionHighlight(self):
with PluginLoaded('mayaHydraFootPrintNode'):
# Create a cube.
cmds.polyCube()

cmds.refresh()

# Create a footprint node. It will be selected.
cmds.createNode('MhFootPrint')

cmds.refresh()

# Traverse the scene starting at the root, and count the number
# of _SelectionHighlight mirror hierarchies. There should be 2,
# one for the heel and one for the sole of the footprint node.
cmds.mayaHydraCppTest('.*_SelectionHighlight', 2, f="TestHydraPrim.countPrims")

# Test picking. Once picked, the footprint node must appear in the global
# selection.
def test_picking(self):
with PluginLoaded('mayaHydraFootPrintNode'):

cmds.createNode('MhFootPrint')

cmds.refresh()

cmds.mayaHydraCppTest('|transform1|MhFootPrint1', f="TestUsdPicking.pickPrim")

self.assertEqual(['MhFootPrint1'], cmds.ls(sl=True))

if __name__ == '__main__':
fixturesUtils.runTests(globals())
Loading