-
Notifications
You must be signed in to change notification settings - Fork 222
Expand file tree
/
Copy pathtestComponentCreatorAddToComponentFromNodes.py
More file actions
308 lines (256 loc) · 14.4 KB
/
Copy pathtestComponentCreatorAddToComponentFromNodes.py
File metadata and controls
308 lines (256 loc) · 14.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
import unittest
import fixturesUtils
import mayaUsd.lib
import mayaUsd.ufe
import mayaUsd_createStageWithNewLayer
from maya import cmds
from pxr import Sdf, Usd
import ufe
from maya.internal.ufeSupport import ufeCmdWrapper as ufeCmd
from testComponentCreatorBase import _ComponentCreatorTestBase
class AddToComponentFromNodesTestCase(_ComponentCreatorTestBase, unittest.TestCase):
"""
Tests for usd_component_creator_plugin.create_component.add_to_component_from_nodes.
"""
@classmethod
def setUpClass(cls):
fixturesUtils.readOnlySetUpClass(__file__, initializeStandalone=False)
@classmethod
def tearDownClass(cls):
cls._resetDefaultTemplate()
return super().tearDownClass()
def setUp(self):
self._setUpCC()
# Clear the variant editor state so there is no lingering component from a
# previous test.
#from usd_component_creator_plugin import update_variant_editor_window
#update_variant_editor_window(None, force_update=True)
self._resetDefaultTemplate()
return super().setUp()
def _createInitialComponent(self, node_name='pCube1'):
"""Create a polyCube, build a single-node component, and return (proxy, desc)."""
from usd_component_creator_plugin import create_component_from_nodes
cmds.polyCube(name=node_name)
path = cmds.ls(node_name, long=True)[0]
before = self._snapshotProxyShapes()
create_component_from_nodes([path])
proxy = self._findNewProxyShape(before)
desc = self._getActiveDesc()
return proxy, desc
def testNoComponentDescReturnsFalse(self):
"""add_to_component_from_nodes with no desc and empty variant editor returns False."""
from usd_component_creator_plugin import add_to_component_from_nodes
cmds.polyCube(name='pCube1')
path = cmds.ls('pCube1', long=True)[0]
result = add_to_component_from_nodes([path], [('model', 'extra')],
is_replacing=False, component_desc=None)
self.assertFalse(result,
"add_to_component_from_nodes must return False when no component "
"description is available")
def testSanityReturnsTrueNoNewProxy(self):
"""add_to_component_from_nodes returns True and reuses the existing proxy shape."""
from usd_component_creator_plugin import add_to_component_from_nodes
proxy, desc = self._createInitialComponent('pCube1')
self.assertIsNotNone(desc, 'Could not get initial ComponentDescription')
first_vs = next(iter(desc.GetVariantSets().values()))
cmds.polyCube(name='pCube2')
path2 = cmds.ls('pCube2', long=True)[0]
before = self._snapshotProxyShapes()
# Add pCube2 to the existing default variant (not a new one)
result = add_to_component_from_nodes(
[path2],
[(first_vs.name, first_vs.default_variant)],
is_replacing=False,
component_desc=desc)
self.assertTrue(result, "add_to_component_from_nodes should return True on success")
new_proxy = self._findNewProxyShape(before)
self.assertIsNone(new_proxy, "No new proxy shape should be created when adding to an existing component")
def testDefaultVariantUnchanged(self):
"""Adding a node to an existing variant must not change the default_variant name."""
from usd_component_creator_plugin import add_to_component_from_nodes
proxy, desc = self._createInitialComponent('pCube1')
self.assertIsNotNone(desc, 'Could not get initial ComponentDescription')
first_vs = next(iter(desc.GetVariantSets().values()))
original_default = first_vs.default_variant
self.assertTrue(original_default, "There must be a default variant before the add")
cmds.polyCube(name='pCube2')
path2 = cmds.ls('pCube2', long=True)[0]
result = add_to_component_from_nodes(
[path2],
[(first_vs.name, original_default)],
is_replacing=False,
component_desc=desc)
self.assertTrue(result)
updated_desc = self._getActiveDesc()
self.assertIsNotNone(updated_desc, 'Could not get updated ComponentDescription')
updated_vs = next(iter(updated_desc.GetVariantSets().values()))
self.assertEqual(updated_vs.default_variant, original_default,
"default_variant must not change after add_to_component_from_nodes "
"(is_default_variant=False)")
def testDefaultVariantUnchangedWhenAddingToNonDefault(self):
"""Adding a node to a non-default variant must not change the default_variant name."""
import AdskUsdComponentCreator
from usd_component_creator_plugin import (
add_to_component_from_nodes,
create_multi_variants_component_from_nodes,
)
# Create a 2-variant component: 'AppleNode' is alphabetically first -> default variant.
for name in ('ZebraNode', 'AppleNode'):
cmds.polyCube(name=name)
paths = [cmds.ls(n, long=True)[0] for n in ('ZebraNode', 'AppleNode')]
before = self._snapshotProxyShapes()
create_multi_variants_component_from_nodes(paths)
proxy = self._findNewProxyShape(before)
self.assertIsNotNone(proxy)
desc = self._getActiveDesc()
self.assertIsNotNone(desc, 'Could not get ComponentDescription after multi-variant create')
first_vs = next(iter(desc.GetVariantSets().values()))
original_default = first_vs.default_variant
self.assertTrue(original_default, "There must be a default variant")
# Pick the non-default variant to add to
non_default_name = next(
n for n in first_vs.GetVariants().keys() if n != original_default)
cmds.polyCube(name='pCubeExtra')
path_extra = cmds.ls('pCubeExtra', long=True)[0]
result = add_to_component_from_nodes(
[path_extra],
[(first_vs.name, non_default_name)],
is_replacing=False,
component_desc=desc)
self.assertTrue(result)
updated_desc = self._getActiveDesc()
self.assertIsNotNone(updated_desc, 'Could not get updated ComponentDescription')
updated_vs = next(iter(updated_desc.GetVariantSets().values()))
self.assertEqual(updated_vs.default_variant, original_default,
"default_variant must not change when adding to a non-default variant "
"(is_default_variant=False)")
def testTargetedVariantUnchangedAfterAdd(self):
"""Adding a node to an existing variant must not change the targeted variant."""
import AdskUsdComponentCreator
from usd_component_creator_plugin import add_to_component_from_nodes
proxy, desc = self._createInitialComponent('pCube1')
self.assertIsNotNone(desc, 'Could not get initial ComponentDescription')
first_vs = next(iter(desc.GetVariantSets().values()))
default_name = first_vs.default_variant
self.assertTrue(default_name)
default_var_desc = first_vs.GetVariantDescription(default_name)
self.assertIsNotNone(default_var_desc)
# Verify: after create, default variant IS targeted
self.assertTrue(
AdskUsdComponentCreator.ComponentAPI.IsVariantTarget(
desc, [first_vs, default_var_desc]),
"Default variant must be targeted after create_component_from_nodes")
# Add a second node to the same existing default variant
cmds.polyCube(name='pCube2')
path2 = cmds.ls('pCube2', long=True)[0]
result = add_to_component_from_nodes(
[path2],
[(first_vs.name, default_name)],
is_replacing=False,
component_desc=desc)
self.assertTrue(result)
updated_desc = self._getActiveDesc()
if updated_desc is None:
stage = mayaUsd.ufe.getStage(proxy)
updated_desc = self._getDescFromStage(stage)
self.assertIsNotNone(updated_desc, 'Could not obtain updated ComponentDescription')
updated_vs = next(iter(updated_desc.GetVariantSets().values()))
updated_default_var_desc = updated_vs.GetVariantDescription(default_name)
self.assertIsNotNone(updated_default_var_desc)
# Check target did not change
self.assertTrue(
AdskUsdComponentCreator.ComponentAPI.IsVariantTarget(
updated_desc, [updated_vs, updated_default_var_desc]))
def testAddWithPurpose(self):
"""add_to_component_from_nodes with purpose specified."""
from usd_component_creator_plugin import add_to_component_from_nodes
proxy, desc = self._createInitialComponent('pCube1')
self.assertIsNotNone(desc, 'Could not get initial ComponentDescription')
first_vs = next(iter(desc.GetVariantSets().values()))
cmds.polyCube(name='pCube2')
path2 = cmds.ls('pCube2', long=True)[0]
before = self._snapshotProxyShapes()
# Add pCube2 to the existing default variant (not a new one)
result = add_to_component_from_nodes(
[path2],
[(first_vs.name, first_vs.default_variant)],
is_replacing=False,
component_desc=desc,
purpose='guide')
self.assertTrue(result, "add_to_component_from_nodes should return True on success")
new_proxy = self._findNewProxyShape(before)
self.assertIsNone(new_proxy, "No new proxy shape should be created when adding to an existing component")
stage = mayaUsd.ufe.getStage(proxy)
cube_path = Sdf.Path('/root/geo/pCube1')
cube_prim = stage.GetPrimAtPath(cube_path)
self.assertTrue(cube_prim.IsValid(), f"{cube_path} should be a valid prim")
purpose_scope_path = Sdf.Path('/root/geo/guide')
purpose_scope = stage.GetPrimAtPath(purpose_scope_path)
self.assertTrue(purpose_scope.IsValid(), f"{purpose_scope_path} should be a valid prim after add_to_component_from_nodes with purpose")
self.assertEqual(purpose_scope.GetTypeName(), "Scope")
purposed_path = Sdf.Path('/root/geo/guide/pCube2')
purposed_prim = stage.GetPrimAtPath(purposed_path)
self.assertTrue(purposed_prim.IsValid(), f"{purposed_path} should be a valid prim after add_to_component_from_nodes with purpose")
def testAddWithPurposeCollidingName(self):
"""add_to_component_from_nodes with purpose specified."""
from usd_component_creator_plugin import add_to_component_from_nodes
proxy, desc = self._createInitialComponent('pCube1')
self.assertIsNotNone(desc, 'Could not get initial ComponentDescription')
first_vs = next(iter(desc.GetVariantSets().values()))
cmds.setAttr('pCube1.translateX', 22.2)
before = self._snapshotProxyShapes()
# Add pCube1 to the existing default variant (not a new one) under a purpose.
# Because it will be placed under the purpose scope, its name will *not* conflict
# with the existing pCube1
result = add_to_component_from_nodes(
['pCube1'],
[(first_vs.name, first_vs.default_variant)],
is_replacing=False,
component_desc=desc,
purpose='guide')
self.assertTrue(result, "add_to_component_from_nodes should return True on success")
new_proxy = self._findNewProxyShape(before)
self.assertIsNone(new_proxy, "No new proxy shape should be created when adding to an existing component")
stage = mayaUsd.ufe.getStage(proxy)
cube_path = Sdf.Path('/root/geo/pCube1')
cube_prim = stage.GetPrimAtPath(cube_path)
self.assertTrue(cube_prim.IsValid(), f"{cube_path} should be a valid prim")
purposed_path = Sdf.Path('/root/geo/guide/pCube1')
purposed_prim = stage.GetPrimAtPath(purposed_path)
self.assertTrue(purposed_prim.IsValid(), f"{purposed_path} should be a valid prim after add_to_component_from_nodes with purpose")
translateAttr = purposed_prim.GetAttribute('xformOp:translate')
self.assertTrue(translateAttr)
self.assertAlmostEqual(translateAttr.Get()[0], 22.2)
def testAddWithCustomPurposeScopeName(self):
"""add_to_component_from_nodes with purpose specified and custom purpose scope names."""
from usd_component_creator_plugin import add_to_component_from_nodes
self._setCustomPurposeTemplate()
proxy, desc = self._createInitialComponent('pCube1')
self.assertIsNotNone(desc, 'Could not get initial ComponentDescription')
first_vs = next(iter(desc.GetVariantSets().values()))
cmds.polyCube(name='pCube2')
path2 = cmds.ls('pCube2', long=True)[0]
before = self._snapshotProxyShapes()
# Add pCube2 to the existing default variant (not a new one)
result = add_to_component_from_nodes(
[path2],
[(first_vs.name, first_vs.default_variant)],
is_replacing=False,
component_desc=desc,
purpose='guide')
self.assertTrue(result, "add_to_component_from_nodes should return True on success")
new_proxy = self._findNewProxyShape(before)
self.assertIsNone(new_proxy, "No new proxy shape should be created when adding to an existing component")
stage = mayaUsd.ufe.getStage(proxy)
cube_path = Sdf.Path('/root/geo/pCube1')
cube_prim = stage.GetPrimAtPath(cube_path)
self.assertTrue(cube_prim.IsValid(), f"{cube_path} should be a valid prim")
purpose_scope_path = Sdf.Path('/root/geo/gui')
purpose_scope = stage.GetPrimAtPath(purpose_scope_path)
self.assertTrue(purpose_scope.IsValid(), f"{purpose_scope_path} should be a valid prim after add_to_component_from_nodes with purpose")
self.assertEqual(purpose_scope.GetTypeName(), "Scope")
purposed_path = Sdf.Path('/root/geo/gui/pCube2')
purposed_prim = stage.GetPrimAtPath(purposed_path)
self.assertTrue(purposed_prim.IsValid(), f"{purposed_path} should be a valid prim after add_to_component_from_nodes with purpose")
if __name__ == '__main__':
fixturesUtils.runTests(globals())