From c93d94d2e19b75ec0f6852adcf912aa202098cbd Mon Sep 17 00:00:00 2001 From: Nathan Vegdahl Date: Tue, 14 Oct 2025 05:10:13 +0200 Subject: [PATCH] Anim: Add Python unit tests for vertex group Normalize All operator Follow-up to #147272. These tests are not exhaustive, but protect against regression of bug #147009. Pull Request: https://projects.blender.org/blender/blender/pulls/147422 --- tests/files/animation/vertex_groups.blend | 3 + tests/python/CMakeLists.txt | 7 +++ tests/python/vertex_group_painting.py | 76 +++++++++++++++++++++++ 3 files changed, 86 insertions(+) create mode 100644 tests/files/animation/vertex_groups.blend create mode 100644 tests/python/vertex_group_painting.py diff --git a/tests/files/animation/vertex_groups.blend b/tests/files/animation/vertex_groups.blend new file mode 100644 index 00000000000..f8479f00f1d --- /dev/null +++ b/tests/files/animation/vertex_groups.blend @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d22b1a372530a0feddd3456eb25e60e12af60c014fd6b15a19ef8cdb504f7749 +size 98575 diff --git a/tests/python/CMakeLists.txt b/tests/python/CMakeLists.txt index 9dabaccff6b..492fb9dbd20 100644 --- a/tests/python/CMakeLists.txt +++ b/tests/python/CMakeLists.txt @@ -604,6 +604,13 @@ if(TEST_SRC_DIR_EXISTS) -- --testdir "${TEST_SRC_DIR}/animation" ) + + add_blender_test( + vertex_group_painting + --python ${CMAKE_CURRENT_LIST_DIR}/vertex_group_painting.py + -- + --testdir "${TEST_SRC_DIR}/animation" + ) endif() # ------------------------------------------------------------------------------ diff --git a/tests/python/vertex_group_painting.py b/tests/python/vertex_group_painting.py new file mode 100644 index 00000000000..b89e5e65870 --- /dev/null +++ b/tests/python/vertex_group_painting.py @@ -0,0 +1,76 @@ +# SPDX-FileCopyrightText: 2025 Blender Authors +# +# SPDX-License-Identifier: GPL-2.0-or-later + +import unittest +import sys +import pathlib + +import bpy + +""" +blender -b --factory-startup --python tests/python/vertex_group_paint.py -- --testdir tests/files/animation/ +""" + + +class NormalizeAllTest(unittest.TestCase): + """Test for normalizing all vertex groups on a mesh.""" + + def setUp(self) -> None: + bpy.ops.wm.read_homefile(use_factory_startup=True) + self._load_test_file() + + # Make sure the initial state is what we expect/need for the tests. + self.cube = bpy.data.objects['Cube'] + self.assertEqual(bpy.context.active_object, self.cube) + self.assertEqual(len(self.cube.vertex_groups), 2) + + def _load_test_file(self): + blendpath = str(args.testdir / "vertex_groups.blend") + bpy.ops.wm.read_homefile(use_factory_startup=True) # Just to be sure. + bpy.ops.wm.open_mainfile(filepath=blendpath, load_ui=False) + + def test_normalize_all(self): + # Initial state. + self.cube.data.vertices[0].groups[0].weight = 0.375 + self.cube.data.vertices[0].groups[1].weight = 0.125 + self.cube.vertex_groups[0].lock_weight = False + self.cube.vertex_groups[1].lock_weight = False + + # Attempt to normalize all vertex groups. Should succeed. + bpy.ops.object.vertex_group_normalize_all(group_select_mode='ALL', lock_active=False) + self.assertEqual(self.cube.data.vertices[0].groups[0].weight, 0.75) + self.assertEqual(self.cube.data.vertices[0].groups[1].weight, 0.25) + + def test_normalize_all_locked(self): + # Initial state. + self.cube.data.vertices[0].groups[0].weight = 0.375 + self.cube.data.vertices[0].groups[1].weight = 0.125 + self.cube.vertex_groups[0].lock_weight = True + self.cube.vertex_groups[1].lock_weight = True + + # Attempt to normalize all vertex groups. Should fail, leaving the weights as-is. + with self.assertRaises(RuntimeError): + bpy.ops.object.vertex_group_normalize_all(group_select_mode='ALL', lock_active=False) + self.assertEqual(self.cube.data.vertices[0].groups[0].weight, 0.375) + self.assertEqual(self.cube.data.vertices[0].groups[1].weight, 0.125) + + +def main(): + global args + import argparse + + if '--' in sys.argv: + argv = [sys.argv[0]] + sys.argv[sys.argv.index('--') + 1:] + else: + argv = sys.argv + + parser = argparse.ArgumentParser() + parser.add_argument('--testdir', required=True, type=pathlib.Path) + args, remaining = parser.parse_known_args(argv) + + unittest.main(argv=remaining) + + +if __name__ == "__main__": + main()