1717
1818import unittest
1919
20+ import maya .cmds as cmds
21+
22+ from pxr import Sdf , Usd
23+
24+ import mayaUsd .lib as mayaUsdLib
25+
2026
2127class testAdskUsdDebugTools (unittest .TestCase ):
2228 """
@@ -25,10 +31,101 @@ class testAdskUsdDebugTools(unittest.TestCase):
2531
2632 def testDebugToolsLoaded (self ):
2733 try :
34+ # Import the USD Python bindings first so the boost.python to/from-Python
35+ # converters for USD types (e.g. SdfPath) are registered.
36+ from pxr import Usd , Sdf
2837 import AdskUsdDebug
2938 except Exception as e :
3039 self .fail (f"Autodesk USD Debug Tools module not available or failed to load. { e } " )
3140
3241
42+ class testAdskUsdDebugToolsRemoveOpinionUndo (unittest .TestCase ):
43+ """
44+ Verify that removing an opinion through the Debug Tools composition editor
45+ can be undone.
46+ """
47+
48+ @classmethod
49+ def setUpClass (cls ):
50+ cmds .loadPlugin ('mayaUsdPlugin' )
51+
52+ def setUp (self ):
53+ # Skip if the Debug Tools component was not shipped in this build; the
54+ # smoke test above already reports a hard failure when it is expected.
55+ try :
56+ import AdskUsdDebug
57+ except Exception as e :
58+ self .skipTest (f"Autodesk USD Debug Tools module not available: { e } " )
59+
60+ cmds .file (force = True , new = True )
61+
62+ self .stage = Usd .Stage .CreateInMemory ()
63+
64+ # Mirror executeInCmd step 1: track the layer being edited so its inverse
65+ # edits are recorded by the undo manager.
66+ mayaUsdLib .UsdUndoManager .trackLayerStates (self .stage .GetRootLayer ())
67+
68+ cmds .select (clear = True )
69+
70+ def testRemoveOpinionUndoRedo (self ):
71+ '''Removing a single property opinion is undoable and redoable.'''
72+ from AdskUsdDebug import RemoveOpinion
73+
74+ prim = self .stage .DefinePrim ('/Foo' , 'Xform' )
75+ prim .CreateAttribute ('radius' , Sdf .ValueTypeNames .Double ).Set (2.0 )
76+ layerId = self .stage .GetRootLayer ().identifier
77+
78+ self .assertTrue (prim .GetAttribute ('radius' ).HasAuthoredValue ())
79+
80+ nbCmds = cmds .undoInfo (q = True )
81+
82+ with mayaUsdLib .UsdUndoBlock ():
83+ self .assertTrue (RemoveOpinion (self .stage , layerId , '/Foo.radius' ))
84+
85+ # The opinion is gone and exactly one command was added to the queue.
86+ self .assertFalse (prim .GetAttribute ('radius' ).HasAuthoredValue ())
87+ self .assertEqual (cmds .undoInfo (q = True ), nbCmds + 1 )
88+
89+ # Undo restores the removed opinion (value included).
90+ cmds .undo ()
91+ self .assertTrue (prim .GetAttribute ('radius' ).HasAuthoredValue ())
92+ self .assertEqual (prim .GetAttribute ('radius' ).Get (), 2.0 )
93+
94+ # Redo removes it again.
95+ cmds .redo ()
96+ self .assertFalse (prim .GetAttribute ('radius' ).HasAuthoredValue ())
97+
98+ def testRemoveOpinionsUndoRedo (self ):
99+ '''Removing several opinions in one edit is undoable as a single step.'''
100+ from AdskUsdDebug import OpinionRef , RemoveOpinions
101+
102+ prim = self .stage .DefinePrim ('/Foo' , 'Xform' )
103+ prim .CreateAttribute ('radius' , Sdf .ValueTypeNames .Double ).Set (2.0 )
104+ prim .CreateAttribute ('count' , Sdf .ValueTypeNames .Int ).Set (7 )
105+ layerId = self .stage .GetRootLayer ().identifier
106+
107+ nbCmds = cmds .undoInfo (q = True )
108+
109+ with mayaUsdLib .UsdUndoBlock ():
110+ self .assertTrue (RemoveOpinions (
111+ self .stage ,
112+ [
113+ OpinionRef (layerId , '/Foo.radius' ),
114+ OpinionRef (layerId , '/Foo.count' ),
115+ ]))
116+
117+ # Both opinions removed, batched into a single undoable command.
118+ self .assertFalse (prim .GetAttribute ('radius' ).HasAuthoredValue ())
119+ self .assertFalse (prim .GetAttribute ('count' ).HasAuthoredValue ())
120+ self .assertEqual (cmds .undoInfo (q = True ), nbCmds + 1 )
121+
122+ # A single undo restores both opinions.
123+ cmds .undo ()
124+ self .assertTrue (prim .GetAttribute ('radius' ).HasAuthoredValue ())
125+ self .assertTrue (prim .GetAttribute ('count' ).HasAuthoredValue ())
126+ self .assertEqual (prim .GetAttribute ('radius' ).Get (), 2.0 )
127+ self .assertEqual (prim .GetAttribute ('count' ).Get (), 7 )
128+
129+
33130if __name__ == '__main__' :
34131 unittest .main (verbosity = 2 )
0 commit comments