File: object_conversion.py

package info (click to toggle)
blender 5.0.1%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: experimental
  • size: 329,128 kB
  • sloc: cpp: 2,489,823; python: 349,859; ansic: 261,364; xml: 2,103; sh: 999; javascript: 317; makefile: 193
file content (170 lines) | stat: -rw-r--r-- 7,510 bytes parent folder | download
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
# SPDX-FileCopyrightText: 2020-2024 Blender Authors
#
# SPDX-License-Identifier: GPL-2.0-or-later

# To run all tests, use
# BLENDER_VERBOSE=1 ./bin/blender ../blender/tests/files/modeling/object_conversion.blend --python ../blender/tests/python/object_conversion.py -- --run-all-tests
# (that assumes the test is run from a build directory in the same directory as the source code)
import bpy
import os
import sys
import inspect

sys.path.append(os.path.dirname(os.path.realpath(__file__)))
from modules.mesh_test import SpecMeshTest, OperatorSpecObjectMode, RunTest


class ConversionTypeTestHelper:
    def __init__(self, tests):
        self.tests = tests
        self._failed_tests_list = []

    def run_all_tests(self):
        """
        Run all tests in self.tests list. Displays all failed tests at bottom.
        """
        for _, each_test in enumerate(self.tests):
            test_name = each_test.test_name
            success = self.run_test(test_name)

            if not success:
                self._failed_tests_list.append(test_name)

        if len(self._failed_tests_list) != 0:
            print("\nFollowing tests failed: {}".format(self._failed_tests_list))

            blender_path = bpy.app.binary_path
            blend_path = bpy.data.filepath
            frame = inspect.stack()[1]
            module = inspect.getmodule(frame[0])
            python_path = module.__file__

            print("Run following command to open Blender and run the failing test:")
            print("{} {} --python {} -- {} {}"
                  .format(blender_path, blend_path, python_path, "--run-test", "<test_name>"))

            raise Exception("Tests {} failed".format(self._failed_tests_list))

    def run_test(self, test_name: str):
        """
        Run a single test from self.tests list.

        :arg test_name: int - name of test
        :return: bool - True if test passed, False otherwise.
        """
        case = None
        for index, each_test in enumerate(self.tests):
            if test_name == each_test.test_name:
                case = self.tests[index]
                break

        if case is None:
            raise Exception('No test called {} found!'.format(test_name))

        test = case
        print("Running test '{}'".format(test.test_name))

        test_object = bpy.data.objects[test.from_object]
        with bpy.context.temp_override(object=test_object, selected_objects=[test_object]):
            bpy.context.view_layer.objects.active = test_object

            selection = test_object.select_get()
            test_object.select_set(True)
            retval = bpy.ops.object.convert(target=test.to_type, keep_original=True)
            test_object.select_set(False)

            if retval != {'FINISHED'}:
                raise RuntimeError("Unexpected operator return value: {}".format(retval))

        resulting_type = bpy.context.view_layer.objects.active.type
        bpy.ops.object.delete()
        if resulting_type != test.resulting_type:
            raise RuntimeError(
                "Converted object does not match expected type.\nTest '{}': Converting '{}' to '{}' expecting '{}' got '{}'\n" .format(
                    test.test_name,
                    test.from_object,
                    test.to_type,
                    test.resulting_type,
                    resulting_type))

        print("Success\n")
        return True


class ConversionPair:
    def __init__(self, test_name, from_object, to_type, resulting_type):
        self.test_name = test_name
        self.from_object = from_object
        self.to_type = to_type
        self.resulting_type = resulting_type


def main():
    tests = [
        SpecMeshTest('Mesh 1', 'Cube', 'Cube_Mesh',
                     [OperatorSpecObjectMode('convert', {'target': 'MESH'})]),
        SpecMeshTest('Mesh 2', 'CubeWithEdges', 'CubeWithEdges_Mesh',
                     [OperatorSpecObjectMode('convert', {'target': 'MESH'})]),
        SpecMeshTest('Mesh 3', 'Plane', 'Plane_Mesh',
                     [OperatorSpecObjectMode('convert', {'target': 'MESH'})]),
        SpecMeshTest('Mesh 4', 'HollowPlane', 'HollowPlane_Mesh',
                     [OperatorSpecObjectMode('convert', {'target': 'MESH'})]),
        SpecMeshTest('Mesh 5', 'Suzanne', 'Suzanne_Mesh',
                     [OperatorSpecObjectMode('convert', {'target': 'MESH'})]),
        SpecMeshTest('Mesh 6', 'BezierCircle', 'BezierCircle_Mesh',
                     [OperatorSpecObjectMode('convert', {'target': 'MESH'})]),
        SpecMeshTest('Mesh 7', 'BezierCurve', 'BezierCurve_Mesh',
                     [OperatorSpecObjectMode('convert', {'target': 'MESH'})]),
        SpecMeshTest('Mesh 8', 'Text', 'Text_Mesh',
                     [OperatorSpecObjectMode('convert', {'target': 'MESH'})]),
    ]

    type_tests = [
        ConversionPair('Legacy Curves 1', 'Cube', 'CURVE', 'MESH'),
        ConversionPair('Legacy Curves 2', 'CubeWithEdges', 'CURVE', 'CURVE'),
        ConversionPair('Legacy Curves 3', 'Plane', 'CURVE', 'CURVE'),
        ConversionPair('Legacy Curves 4', 'HollowPlane', 'CURVE', 'CURVE'),
        ConversionPair('Legacy Curves 5', 'Suzanne', 'CURVE', 'GREASEPENCIL'),
        ConversionPair('Legacy Curves 6', 'BezierCircle', 'CURVE', 'CURVE'),
        ConversionPair('Legacy Curves 7', 'BezierCurve', 'CURVE', 'CURVE'),
        ConversionPair('Legacy Curves 8', 'Text', 'CURVE', 'CURVE'),
        ConversionPair('Curves 1', 'Cube', 'CURVES', 'MESH'),
        ConversionPair('Curves 2', 'CubeWithEdges', 'CURVES', 'MESH'),
        ConversionPair('Curves 3', 'Plane', 'CURVES', 'MESH'),
        ConversionPair('Curves 4', 'HollowPlane', 'CURVES', 'MESH'),
        ConversionPair('Curves 5', 'Suzanne', 'CURVES', 'CURVES'),
        ConversionPair('Curves 6', 'BezierCircle', 'CURVES', 'CURVES'),
        ConversionPair('Curves 7', 'BezierCurve', 'CURVES', 'CURVES'),
        ConversionPair('Curves 8', 'Text', 'CURVES', 'CURVES'),
        ConversionPair('GreasePencil 1', 'Cube', 'GREASEPENCIL', 'GREASEPENCIL'),
        ConversionPair('GreasePencil 2', 'CubeWithEdges', 'GREASEPENCIL', 'GREASEPENCIL'),
        ConversionPair('GreasePencil 3', 'Plane', 'GREASEPENCIL', 'GREASEPENCIL'),
        ConversionPair('GreasePencil 4', 'HollowPlane', 'GREASEPENCIL', 'GREASEPENCIL'),
        ConversionPair('GreasePencil 5', 'Suzanne', 'GREASEPENCIL', 'GREASEPENCIL'),
        ConversionPair('GreasePencil 6', 'BezierCircle', 'GREASEPENCIL', 'GREASEPENCIL'),
        ConversionPair('GreasePencil 7', 'BezierCurve', 'GREASEPENCIL', 'GREASEPENCIL'),
        ConversionPair('GreasePencil 8', 'Text', 'GREASEPENCIL', 'GREASEPENCIL'),
        ConversionPair('GreasePencil 9', 'Suzanne_Curves', 'GREASEPENCIL', 'GREASEPENCIL'),
        ConversionPair('GreasePencil 10', 'BezierCircle_Curves', 'GREASEPENCIL', 'GREASEPENCIL'),
        ConversionPair('GreasePencil 11', 'BezierCurve_Curves', 'GREASEPENCIL', 'GREASEPENCIL'),
    ]

    operator_test = RunTest(tests)
    all_type_tests = ConversionTypeTestHelper(type_tests)

    command = list(sys.argv)
    for i, cmd in enumerate(command):
        if cmd == "--run-all-tests":
            operator_test.do_compare = True
            operator_test.run_all_tests()
            all_type_tests.run_all_tests()
            break
        elif cmd == "--run-test":
            name = command[i + 1]
            operator_test.do_compare = False
            operator_test.run_test(name)
            break


if __name__ == "__main__":
    main()