diff options
author | Campbell Barton <ideasman42@gmail.com> | 2021-07-29 03:52:11 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2021-07-29 04:09:21 +0300 |
commit | bc0a7d3fae5cfbe76ff84b76cb0ce48fe46adea5 (patch) | |
tree | 32a3a121b4c87b20daacfd95f2e00a1102a3a3de /tests | |
parent | 2453dc1b0ecad21a84b45e8c900a16cc42fa12f1 (diff) |
PyAPI: support multi-dimensional arrays for bpy.props vector types
- Multi-dimensional boolean, int and float vector types are supported.
- A sequence of int's for the "size" is used to declare dimensions.
- Nested sequences are required for default arguments.
Now it's possible to define matrix properties, for e.g:
bpy.props.FloatVectorProperty(size=(4, 4), subtype='MATRIX')
Diffstat (limited to 'tests')
-rw-r--r-- | tests/python/bl_pyapi_prop_array.py | 120 |
1 files changed, 118 insertions, 2 deletions
diff --git a/tests/python/bl_pyapi_prop_array.py b/tests/python/bl_pyapi_prop_array.py index ac1082c009e..2f38b67d7a1 100644 --- a/tests/python/bl_pyapi_prop_array.py +++ b/tests/python/bl_pyapi_prop_array.py @@ -2,18 +2,61 @@ # ./blender.bin --background -noaudio --python tests/python/bl_pyapi_prop_array.py -- --verbose import bpy +from bpy.props import ( + BoolVectorProperty, + FloatVectorProperty, + IntVectorProperty, +) import unittest import numpy as np +id_inst = bpy.context.scene +id_type = bpy.types.Scene + + +# ----------------------------------------------------------------------------- +# Utility Functions + +def seq_items_xform(data, xform_fn): + """ + Recursively expand items using `xform_fn`. + """ + if hasattr(data, "__len__"): + return tuple(seq_items_xform(v, xform_fn) for v in data) + return xform_fn(data) + + +def seq_items_as_tuple(data): + """ + Return nested sequences as a nested tuple. + Useful when comparing different kinds of nested sequences. + """ + return seq_items_xform(data, lambda v: v) + + +def seq_items_as_dims(data): + """ + Nested length calculation, extracting the length from each sequence. + Where a 4x4 matrix returns ``(4, 4)`` for example. + """ + return ((len(data),) + seq_items_as_dims(data[0])) if hasattr(data, "__len__") else () + + +# ----------------------------------------------------------------------------- +# Tests class TestPropArray(unittest.TestCase): def setUp(self): - bpy.types.Scene.test_array_f = bpy.props.FloatVectorProperty(size=10) - bpy.types.Scene.test_array_i = bpy.props.IntVectorProperty(size=10) + id_type.test_array_f = FloatVectorProperty(size=10) + id_type.test_array_i = IntVectorProperty(size=10) scene = bpy.context.scene self.array_f = scene.test_array_f self.array_i = scene.test_array_i + def tearDown(self): + del id_type.test_array_f + del id_type.test_array_i + def test_foreach_getset_i(self): with self.assertRaises(TypeError): self.array_i.foreach_set(range(5)) @@ -79,6 +122,79 @@ class TestPropArray(unittest.TestCase): self.assertEqual(v1, v2) +class TestPropArrayMultiDimensional(unittest.TestCase): + + def setUp(self): + self._initial_dir = set(dir(id_type)) + + def tearDown(self): + for member in (set(dir(id_type)) - self._initial_dir): + delattr(id_type, member) + + def test_defaults(self): + # The data is in int format, converted into float & bool to avoid duplication. + default_data = ( + # 1D. + (1,), + (1, 2), + (1, 2, 3), + (1, 2, 3, 4), + # 2D. + ((1,),), + ((1,), (11,)), + ((1, 2), (11, 22)), + ((1, 2, 3), (11, 22, 33)), + ((1, 2, 3, 4), (11, 22, 33, 44)), + # 3D. + (((1,),),), + ((1,), (11,), (111,)), + ((1, 2), (11, 22), (111, 222),), + ((1, 2, 3), (11, 22, 33), (111, 222, 333)), + ((1, 2, 3, 4), (11, 22, 33, 44), (111, 222, 333, 444)), + ) + for data in default_data: + for (vector_prop_fn, xform_fn) in ( + (BoolVectorProperty, lambda v: bool(v % 2)), + (FloatVectorProperty, lambda v: float(v)), + (IntVectorProperty, lambda v: v), + ): + data_native = seq_items_xform(data, xform_fn) + size = seq_items_as_dims(data) + id_type.temp = vector_prop_fn(size=size, default=data_native) + data_as_tuple = seq_items_as_tuple(id_inst.temp) + self.assertEqual(data_as_tuple, data_native) + del id_type.temp + + def test_matrix(self): + data = ((1, 2, 3, 4), (11, 22, 33, 44), (111, 222, 333, 444), (1111, 2222, 3333, 4444),) + data_native = seq_items_xform(data, lambda v: float(v)) + id_type.temp = FloatVectorProperty(size=(4, 4), subtype='MATRIX', default=data_native) + data_as_tuple = seq_items_as_tuple(id_inst.temp) + self.assertEqual(data_as_tuple, data_native) + del id_type.temp + + def test_matrix_with_callbacks(self): + # """ + # Internally matrices have rows/columns swapped, + # This test ensures this is being done properly. + # """ + data = ((1, 2, 3, 4), (11, 22, 33, 44), (111, 222, 333, 444), (1111, 2222, 3333, 4444),) + data_native = seq_items_xform(data, lambda v: float(v)) + local_data = {"array": data} + + def get_fn(id_arg): + return local_data["array"] + + def set_fn(id_arg, value): + local_data["array"] = value + + id_type.temp = FloatVectorProperty(size=(4, 4), subtype='MATRIX', get=get_fn, set=set_fn) + id_inst.temp = data_native + data_as_tuple = seq_items_as_tuple(id_inst.temp) + self.assertEqual(data_as_tuple, data_native) + del id_type.temp + + if __name__ == '__main__': import sys sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []) |