USD: Add test coverage for parent-child transforms during animation
Makes use of recently added test data to ensure proper handling of child objects, with animated transform constraints, parented to other objects who also have animated transform constraints. Also uses the `colored_print` module to better segment the test output. Pull Request: https://projects.blender.org/blender/blender/pulls/133600
This commit is contained in:
committed by
Jesse Yurkovich
parent
3e11cfb1d0
commit
d4c2d73864
Submodule tests/data updated: 6147e32e51...02bedf6aa5
@@ -3,6 +3,7 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
import math
|
||||
import os
|
||||
import pathlib
|
||||
import pprint
|
||||
import sys
|
||||
@@ -12,6 +13,10 @@ from pxr import Gf, Sdf, Usd, UsdGeom, UsdShade, UsdSkel, UsdUtils, UsdVol
|
||||
|
||||
import bpy
|
||||
|
||||
sys.path.append(str(pathlib.Path(__file__).parent.absolute()))
|
||||
from modules.colored_print import (print_message, use_message_colors)
|
||||
|
||||
|
||||
args = None
|
||||
|
||||
|
||||
@@ -21,17 +26,23 @@ class AbstractUSDTest(unittest.TestCase):
|
||||
cls._tempdir = tempfile.TemporaryDirectory()
|
||||
cls.testdir = args.testdir
|
||||
cls.tempdir = pathlib.Path(cls._tempdir.name)
|
||||
|
||||
return cls
|
||||
if os.environ.get("BLENDER_TEST_COLOR") is not None:
|
||||
use_message_colors()
|
||||
|
||||
def setUp(self):
|
||||
self.assertTrue(
|
||||
self.testdir.exists(), "Test dir {0} should exist".format(self.testdir)
|
||||
)
|
||||
self.assertTrue(self.testdir.exists(), "Test dir {0} should exist".format(self.testdir))
|
||||
print_message(self._testMethodName, 'SUCCESS', 'RUN')
|
||||
|
||||
def tearDown(self):
|
||||
self._tempdir.cleanup()
|
||||
|
||||
result = self._outcome.result
|
||||
ok = all(test != self for test, _ in result.errors + result.failures)
|
||||
if not ok:
|
||||
print_message(self._testMethodName, 'FAILURE', 'FAILED')
|
||||
else:
|
||||
print_message(self._testMethodName, 'SUCCESS', 'PASSED')
|
||||
|
||||
def export_and_validate(self, **kwargs):
|
||||
"""Export and validate the resulting USD file."""
|
||||
|
||||
@@ -926,6 +937,15 @@ class USDExportTest(AbstractUSDTest):
|
||||
self.assertEqual(rot_samples, [1.0])
|
||||
self.assertEqual(scale_samples, [1.0])
|
||||
|
||||
prim = stage.GetPrimAtPath("/root/cube_anim_xform/cube_anim_child")
|
||||
self.assertEqual(prim.GetTypeName(), "Xform")
|
||||
loc_samples = UsdGeom.Xformable(prim).GetTranslateOp().GetTimeSamples()
|
||||
rot_samples = UsdGeom.Xformable(prim).GetRotateXYZOp().GetTimeSamples()
|
||||
scale_samples = UsdGeom.Xformable(prim).GetScaleOp().GetTimeSamples()
|
||||
self.assertEqual(loc_samples, [1.0])
|
||||
self.assertEqual(rot_samples, [1.0, 2.0, 3.0, 4.0])
|
||||
self.assertEqual(scale_samples, [1.0])
|
||||
|
||||
# Validate the armature animation
|
||||
prim = stage.GetPrimAtPath("/root/Armature/Armature")
|
||||
self.assertEqual(prim.GetTypeName(), "Skeleton")
|
||||
@@ -1548,7 +1568,7 @@ def main():
|
||||
parser.add_argument("--testdir", required=True, type=pathlib.Path)
|
||||
args, remaining = parser.parse_known_args(argv)
|
||||
|
||||
unittest.main(argv=remaining)
|
||||
unittest.main(argv=remaining, verbosity=0)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
import math
|
||||
import os
|
||||
import pathlib
|
||||
import sys
|
||||
import tempfile
|
||||
@@ -11,6 +12,10 @@ from pxr import Ar, Gf, Sdf, Usd, UsdGeom, UsdShade
|
||||
|
||||
import bpy
|
||||
|
||||
sys.path.append(str(pathlib.Path(__file__).parent.absolute()))
|
||||
from modules.colored_print import (print_message, use_message_colors)
|
||||
|
||||
|
||||
args = None
|
||||
|
||||
|
||||
@@ -18,6 +23,8 @@ class AbstractUSDTest(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.testdir = args.testdir
|
||||
if os.environ.get("BLENDER_TEST_COLOR") is not None:
|
||||
use_message_colors()
|
||||
|
||||
def setUp(self):
|
||||
self._tempdir = tempfile.TemporaryDirectory()
|
||||
@@ -28,12 +35,21 @@ class AbstractUSDTest(unittest.TestCase):
|
||||
self.assertTrue(self.tempdir.exists(),
|
||||
'Temp dir {0} should exist'.format(self.tempdir))
|
||||
|
||||
print_message(self._testMethodName, 'SUCCESS', 'RUN')
|
||||
|
||||
# Make sure we always start with a known-empty file.
|
||||
bpy.ops.wm.open_mainfile(filepath=str(self.testdir / "empty.blend"))
|
||||
|
||||
def tearDown(self):
|
||||
self._tempdir.cleanup()
|
||||
|
||||
result = self._outcome.result
|
||||
ok = all(test != self for test, _ in result.errors + result.failures)
|
||||
if not ok:
|
||||
print_message(self._testMethodName, 'FAILURE', 'FAILED')
|
||||
else:
|
||||
print_message(self._testMethodName, 'SUCCESS', 'PASSED')
|
||||
|
||||
|
||||
class USDImportTest(AbstractUSDTest):
|
||||
# Utility function to round each component of a vector to a few digits. The "+ 0" is to
|
||||
@@ -577,6 +593,7 @@ class USDImportTest(AbstractUSDTest):
|
||||
|
||||
# Validate some simple aspects of the animated objects which prove that they're animating.
|
||||
ob_xform = bpy.data.objects["cube_anim_xform"]
|
||||
ob_xform_child = bpy.data.objects["cube_anim_child_mesh"]
|
||||
ob_shapekeys = bpy.data.objects["cube_anim_keys"]
|
||||
ob_arm = bpy.data.objects["column_anim_armature"]
|
||||
ob_arm2_side_a = bpy.data.objects["side_a"]
|
||||
@@ -585,7 +602,10 @@ class USDImportTest(AbstractUSDTest):
|
||||
|
||||
bpy.context.scene.frame_set(1)
|
||||
self.assertEqual(len(ob_xform.constraints), 1)
|
||||
self.assertEqual(len(ob_xform_child.constraints), 1)
|
||||
self.assertEqual(self.round_vector(ob_xform.matrix_world.translation), [0.0, -2.0, 0.0])
|
||||
self.assertEqual(self.round_vector(ob_xform_child.matrix_world.translation), [0.0, -2.0, 1.0])
|
||||
self.assertEqual(self.round_vector(ob_xform_child.matrix_world.to_euler('XYZ')), [0.0, 0.0, 0.0])
|
||||
self.assertEqual(self.round_vector(ob_shapekeys.dimensions), [1.0, 1.0, 1.0])
|
||||
self.assertEqual(self.round_vector(ob_arm.dimensions), [0.4, 0.4, 3.0])
|
||||
self.assertEqual(self.round_vector(ob_arm2_side_a.dimensions), [0.5, 0.0, 0.5])
|
||||
@@ -595,7 +615,10 @@ class USDImportTest(AbstractUSDTest):
|
||||
|
||||
bpy.context.scene.frame_set(5)
|
||||
self.assertEqual(len(ob_xform.constraints), 1)
|
||||
self.assertEqual(len(ob_xform_child.constraints), 1)
|
||||
self.assertEqual(self.round_vector(ob_xform.matrix_world.translation), [3.0, -2.0, 0.0])
|
||||
self.assertEqual(self.round_vector(ob_xform_child.matrix_world.translation), [3.0, -2.0, 1.0])
|
||||
self.assertEqual(self.round_vector(ob_xform_child.matrix_world.to_euler('XYZ')), [0.0, 1.5708, 0.0])
|
||||
self.assertEqual(self.round_vector(ob_shapekeys.dimensions), [0.1, 0.1, 0.1])
|
||||
self.assertEqual(self.round_vector(ob_arm.dimensions), [1.65545, 0.4, 2.38953])
|
||||
self.assertEqual(self.round_vector(ob_arm2_side_a.dimensions), [0.25, 0.0, 0.25])
|
||||
@@ -1911,7 +1934,7 @@ def main():
|
||||
parser.add_argument('--testdir', required=True, type=pathlib.Path)
|
||||
args, remaining = parser.parse_known_args(argv)
|
||||
|
||||
unittest.main(argv=remaining)
|
||||
unittest.main(argv=remaining, verbosity=0)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -36,9 +36,9 @@ def print_message(message, type=None, status=''):
|
||||
elif status == 'OK':
|
||||
status_text = " OK "
|
||||
elif status == 'PASSED':
|
||||
status_text = " PASSED "
|
||||
status_text = " PASSED "
|
||||
elif status == 'FAILED':
|
||||
status_text = " FAILED "
|
||||
status_text = " FAILED "
|
||||
else:
|
||||
status_text = status
|
||||
if status_text:
|
||||
|
||||
Reference in New Issue
Block a user