-
Notifications
You must be signed in to change notification settings - Fork 202
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
Making visibility Undo/Redo correct. #1056
Changes from all commits
b24e690
7004631
865d479
88a3a5f
1a2008a
43bf1b1
8bac473
585cca0
16457bf
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -42,6 +42,10 @@ class MAYAUSD_CORE_PUBLIC UsdObject3d : public Ufe::Object3d | |
bool visibility() const override; | ||
void setVisibility(bool vis) override; | ||
|
||
#if UFE_PREVIEW_VERSION_NUM >= 2034 | ||
Ufe::UndoableCommand::Ptr setVisibleCmd(bool vis) override; | ||
#endif | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added guard around "setVisibleCmd" since this feature is available in UFE V.2034 or later. |
||
private: | ||
UsdSceneItem::Ptr fItem; | ||
UsdPrim fPrim; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
// | ||
// Copyright 2020 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 "UsdUndoVisibleCommand.h" | ||
|
||
#include <mayaUsd/undo/UsdUndoBlock.h> | ||
|
||
#include <pxr/usd/usdGeom/imageable.h> | ||
|
||
namespace MAYAUSD_NS_DEF { | ||
namespace ufe { | ||
|
||
UsdUndoVisibleCommand::UsdUndoVisibleCommand(const UsdPrim& prim, bool vis) | ||
: Ufe::UndoableCommand() | ||
, _prim(prim) | ||
, _visible(vis) | ||
{ | ||
} | ||
|
||
UsdUndoVisibleCommand::~UsdUndoVisibleCommand() { } | ||
|
||
UsdUndoVisibleCommand::Ptr UsdUndoVisibleCommand::create(const UsdPrim& prim, bool vis) | ||
{ | ||
if (!prim) { | ||
return nullptr; | ||
} | ||
return std::make_shared<UsdUndoVisibleCommand>(prim, vis); | ||
} | ||
|
||
void UsdUndoVisibleCommand::execute() | ||
{ | ||
UsdUndoBlock undoBlock(&_undoableItem); | ||
|
||
_visible ? UsdGeomImageable(_prim).MakeVisible() : UsdGeomImageable(_prim).MakeInvisible(); | ||
} | ||
|
||
void UsdUndoVisibleCommand::redo() { _undoableItem.redo(); } | ||
|
||
void UsdUndoVisibleCommand::undo() { _undoableItem.undo(); } | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. On execute(), we create an undoBlock to capture the edit and then visibility is set via UsdGeomImageable MakeVisible()/MakeInvisible() methods. |
||
} // namespace ufe | ||
} // namespace MAYAUSD_NS_DEF |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
// | ||
// Copyright 2020 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. | ||
// | ||
#pragma once | ||
|
||
#include <mayaUsd/base/api.h> | ||
#include <mayaUsd/undo/UsdUndoableItem.h> | ||
|
||
#include <pxr/usd/usd/prim.h> | ||
|
||
#include <ufe/undoableCommand.h> | ||
|
||
PXR_NAMESPACE_USING_DIRECTIVE | ||
|
||
namespace MAYAUSD_NS_DEF { | ||
namespace ufe { | ||
|
||
//! \brief UsdUndoVisibleCommand | ||
class MAYAUSD_CORE_PUBLIC UsdUndoVisibleCommand : public Ufe::UndoableCommand | ||
{ | ||
public: | ||
typedef std::shared_ptr<UsdUndoVisibleCommand> Ptr; | ||
|
||
UsdUndoVisibleCommand(const UsdPrim& prim, bool vis); | ||
~UsdUndoVisibleCommand() override; | ||
|
||
// Delete the copy/move constructors assignment operators. | ||
UsdUndoVisibleCommand(const UsdUndoVisibleCommand&) = delete; | ||
UsdUndoVisibleCommand& operator=(const UsdUndoVisibleCommand&) = delete; | ||
UsdUndoVisibleCommand(UsdUndoVisibleCommand&&) = delete; | ||
UsdUndoVisibleCommand& operator=(UsdUndoVisibleCommand&&) = delete; | ||
|
||
//! Create a UsdUndoVisibleCommand object | ||
static UsdUndoVisibleCommand::Ptr create(const UsdPrim& prim, bool vis); | ||
|
||
private: | ||
void execute() override; | ||
void undo() override; | ||
void redo() override; | ||
|
||
UsdPrim _prim; | ||
|
||
bool _visible; | ||
|
||
UsdUndoableItem _undoableItem; | ||
|
||
}; // UsdUndoVisibleCommand | ||
|
||
} // namespace ufe | ||
} // namespace MAYAUSD_NS_DEF |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -23,6 +23,8 @@ | |
|
||
from pxr import Usd, UsdGeom | ||
|
||
import mayaUsd.ufe | ||
|
||
import maya.cmds as cmds | ||
import maya.api.OpenMaya as OpenMaya | ||
|
||
|
@@ -228,3 +230,175 @@ def testVisibility(self): | |
ufe.Object3d.removeObserver(visObs) | ||
self.assertFalse(ufe.Object3d.hasObserver(visObs)) | ||
self.assertEqual(ufe.Object3d.nbObservers(), 0) | ||
|
||
@unittest.skipIf(os.getenv('UFE_PREVIEW_VERSION_NUM', '0000') < '2034', 'testUndoVisibleCmd is only available in UFE preview version 0.2.34 and greater') | ||
def testUndoVisibleCmd(self): | ||
|
||
''' Verify the token / attribute values for visibility after performing undo/redo ''' | ||
|
||
cmds.file(new=True, force=True) | ||
|
||
# create a Capsule via contextOps menu | ||
import mayaUsd_createStageWithNewLayer | ||
mayaUsd_createStageWithNewLayer.createStageWithNewLayer() | ||
proxyShapePath = ufe.PathString.path('|stage1|stageShape1') | ||
proxyShapeItem = ufe.Hierarchy.createItem(proxyShapePath) | ||
proxyShapeContextOps = ufe.ContextOps.contextOps(proxyShapeItem) | ||
proxyShapeContextOps.doOp(['Add New Prim', 'Capsule']) | ||
|
||
# create an Object3d interface. | ||
capsulePath = ufe.PathString.path('|stage1|stageShape1,/Capsule1') | ||
capsuleItem = ufe.Hierarchy.createItem(capsulePath) | ||
capsulePrim = mayaUsd.ufe.ufePathToPrim(ufe.PathString.string(capsulePath)) | ||
object3d = ufe.Object3d.object3d(capsuleItem) | ||
|
||
# stage / primSpec | ||
stage = mayaUsd.ufe.getStage(str(proxyShapePath)) | ||
primSpec = stage.GetEditTarget().GetPrimSpecForScenePath('/Capsule1'); | ||
|
||
# initially capsuleItem should be visible. | ||
self.assertTrue(object3d.visibility()) | ||
|
||
# make it invisible. | ||
visibleCmd = object3d.setVisibleCmd(False) | ||
visibleCmd.execute() | ||
|
||
# get the visibility "attribute" | ||
visibleAttr = capsulePrim.GetAttribute('visibility') | ||
|
||
# expect the visibility attribute to be 'invisible' | ||
self.assertEqual(visibleAttr.Get(), 'invisible') | ||
|
||
# visibility "token" must exists now in the USD data model | ||
self.assertTrue(bool(primSpec and UsdGeom.Tokens.visibility in primSpec.attributes)) | ||
|
||
# undo | ||
visibleCmd.undo() | ||
|
||
# expect the visibility attribute to be 'inherited' | ||
self.assertEqual(visibleAttr.Get(), 'inherited') | ||
|
||
# visibility token must not exists now in the USD data model after undo | ||
self.assertFalse(bool(primSpec and UsdGeom.Tokens.visibility in primSpec.attributes)) | ||
|
||
# capsuleItem must be visible now | ||
self.assertTrue(object3d.visibility()) | ||
|
||
# redo | ||
visibleCmd.redo() | ||
|
||
# expect the visibility attribute to be 'invisible' | ||
self.assertEqual(visibleAttr.Get(), 'invisible') | ||
|
||
# visibility token must exists now in the USD data model after redo | ||
self.assertTrue(bool(primSpec and UsdGeom.Tokens.visibility in primSpec.attributes)) | ||
|
||
# capsuleItem must be invisible now | ||
self.assertFalse(object3d.visibility()) | ||
|
||
@unittest.skipIf(os.getenv('UFE_PREVIEW_VERSION_NUM', '0000') < '2034', 'testMayaHideAndShowHiddenUndoCommands is only available in UFE preview version 0.2.34 and greater') | ||
def testMayaHideAndShowHiddenUndoCommands(self): | ||
''' Verify the token / attribute values for visibility via "hide", "showHidden" commands + Undo/Redo ''' | ||
|
||
cmds.file(new=True, force=True) | ||
|
||
# create a Capsule and Cylinder via contextOps menu | ||
import mayaUsd_createStageWithNewLayer | ||
mayaUsd_createStageWithNewLayer.createStageWithNewLayer() | ||
proxyShapePath = ufe.PathString.path('|stage1|stageShape1') | ||
proxyShapeItem = ufe.Hierarchy.createItem(proxyShapePath) | ||
proxyShapeContextOps = ufe.ContextOps.contextOps(proxyShapeItem) | ||
proxyShapeContextOps.doOp(['Add New Prim', 'Capsule']) | ||
proxyShapeContextOps.doOp(['Add New Prim', 'Cylinder']) | ||
|
||
# capsule | ||
capsulePath = ufe.PathString.path('|stage1|stageShape1,/Capsule1') | ||
capsuleItem = ufe.Hierarchy.createItem(capsulePath) | ||
capsulePrim = mayaUsd.ufe.ufePathToPrim(ufe.PathString.string(capsulePath)) | ||
|
||
# cylinder | ||
cylinderPath = ufe.PathString.path('|stage1|stageShape1,/Cylinder1') | ||
cylinderItem = ufe.Hierarchy.createItem(cylinderPath) | ||
cylinderPrim = mayaUsd.ufe.ufePathToPrim(ufe.PathString.string(cylinderPath)) | ||
|
||
# stage / primSpec | ||
stage = mayaUsd.ufe.getStage(str(proxyShapePath)) | ||
primSpecCapsule = stage.GetEditTarget().GetPrimSpecForScenePath('/Capsule1'); | ||
primSpecCylinder = stage.GetEditTarget().GetPrimSpecForScenePath('/Cylinder1'); | ||
|
||
# select capsule and cylinder prims | ||
ufe.GlobalSelection.get().append(capsuleItem) | ||
ufe.GlobalSelection.get().append(cylinderItem) | ||
|
||
# hide selected items | ||
cmds.hide(cs=True) | ||
|
||
# get the visibility "attribute" | ||
capsuleVisibleAttr = capsulePrim.GetAttribute('visibility') | ||
cylinderVisibleAttr = cylinderPrim.GetAttribute('visibility') | ||
|
||
# expect the visibility attribute to be 'invisible' | ||
self.assertEqual(capsuleVisibleAttr.Get(), 'invisible') | ||
self.assertEqual(cylinderVisibleAttr.Get(), 'invisible') | ||
|
||
# visibility "token" must exists now in the USD data model | ||
self.assertTrue(bool(primSpecCapsule and UsdGeom.Tokens.visibility in primSpecCapsule.attributes)) | ||
self.assertTrue(bool(primSpecCylinder and UsdGeom.Tokens.visibility in primSpecCylinder.attributes)) | ||
|
||
# undo | ||
cmds.undo() | ||
|
||
# expect the visibility attribute to be 'inherited' | ||
self.assertEqual(capsuleVisibleAttr.Get(), 'inherited') | ||
self.assertEqual(cylinderVisibleAttr.Get(), 'inherited') | ||
|
||
# visibility token must not exists now in the USD data model after undo | ||
self.assertFalse(bool(primSpecCapsule and UsdGeom.Tokens.visibility in primSpecCapsule.attributes)) | ||
self.assertFalse(bool(primSpecCylinder and UsdGeom.Tokens.visibility in primSpecCylinder.attributes)) | ||
|
||
# undo | ||
cmds.redo() | ||
|
||
# expect the visibility attribute to be 'invisible' | ||
self.assertEqual(capsuleVisibleAttr.Get(), 'invisible') | ||
self.assertEqual(cylinderVisibleAttr.Get(), 'invisible') | ||
|
||
# visibility "token" must exists now in the USD data model | ||
self.assertTrue(bool(primSpecCapsule and UsdGeom.Tokens.visibility in primSpecCapsule.attributes)) | ||
self.assertTrue(bool(primSpecCylinder and UsdGeom.Tokens.visibility in primSpecCylinder.attributes)) | ||
|
||
# hide selected items again | ||
cmds.hide(cs=True) | ||
|
||
# right after, call showHidden -all to make everything visible again | ||
cmds.showHidden( all=True ) | ||
|
||
# expect the visibility attribute to be 'inherited' | ||
self.assertEqual(capsuleVisibleAttr.Get(), 'inherited') | ||
self.assertEqual(cylinderVisibleAttr.Get(), 'inherited') | ||
|
||
# This time, expect the visibility token to exists in the USD data model | ||
self.assertTrue(bool(primSpecCapsule and UsdGeom.Tokens.visibility in primSpecCapsule.attributes)) | ||
self.assertTrue(bool(primSpecCylinder and UsdGeom.Tokens.visibility in primSpecCylinder.attributes)) | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would have been nice to undo / redo showHidden --- should be quick to add and we'd put this one to rest. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good point. Addressed in 585cca0 |
||
# undo the showHidden command | ||
cmds.undo() | ||
|
||
# expect the visibility attribute to be 'invisible' | ||
self.assertEqual(capsuleVisibleAttr.Get(), 'invisible') | ||
self.assertEqual(cylinderVisibleAttr.Get(), 'invisible') | ||
|
||
# visibility "token" must exists now in the USD data model | ||
self.assertTrue(bool(primSpecCapsule and UsdGeom.Tokens.visibility in primSpecCapsule.attributes)) | ||
self.assertTrue(bool(primSpecCylinder and UsdGeom.Tokens.visibility in primSpecCylinder.attributes)) | ||
|
||
# redo | ||
cmds.redo() | ||
|
||
# expect the visibility attribute to be 'inherited' | ||
self.assertEqual(capsuleVisibleAttr.Get(), 'inherited') | ||
self.assertEqual(cylinderVisibleAttr.Get(), 'inherited') | ||
|
||
# visibility "token" must exists now in the USD data model | ||
self.assertTrue(bool(primSpecCapsule and UsdGeom.Tokens.visibility in primSpecCapsule.attributes)) | ||
self.assertTrue(bool(primSpecCylinder and UsdGeom.Tokens.visibility in primSpecCylinder.attributes)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't we check that the scene item supports the Object3d interface? At this point it should, because we put up the menu entry for it, so perhaps we can just assert.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great point. I am working on it as we speak.
Addressed in 7004631
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ppt-adsk @seando-adsk
Added a test for backing the new UsdUndoVisibleCommand :
865d479
Added a new test for backing up the UFE command integration on Maya side for both "hide" and "showHidden" commands :
43bf1b1