def test_bpy_collection(self): # bpy.data.collections[x].objects # A collection of references to standalone datablocks # test_diff_compute.Collection.test_bpy_collection collection = bpy.data.collections.new("Collection") for i in range(2): empty = bpy.data.objects.new(f"Unchanged{i}", None) collection.objects.link(empty) for i in range(2): empty = bpy.data.objects.new(f"Unlinked{i}", None) collection.objects.link(empty) self.proxy = BpyDataProxy() self.proxy.load(test_properties) self.collection_proxy = self.proxy.data("collections").search_one( "Collection") self.collection = bpy.data.collections["Collection"] for i in range(2): empty = bpy.data.objects.new(f"Added{i}", None) collection.objects.link(empty) for i in range(2): collection.objects.unlink(bpy.data.objects[f"Unlinked{i}"]) self.generate_all_uuids() collections_property = bpy.data.bl_rna.properties["scenes"] collection_delta = self.collection_proxy.diff(self.collection, self.collection.name, collections_property, self.proxy.context()) self.assertIsInstance(collection_delta, DeltaUpdate) collection_update = collection_delta.value self.assertIsInstance(collection_update, DatablockProxy) objects_delta = collection_update.data("objects", resolve_delta=False) self.assertIsInstance(objects_delta, DeltaUpdate) objects_update = objects_delta.value self.assertIsInstance(objects_update, DatablockRefCollectionProxy) # test_diff_compute.Collection.test_bpy_collection deltas = { delta.value._initial_name: delta for delta in objects_update._data.values() } proxies = {name: delta.value for name, delta in deltas.items()} for name in ("Added0", "Added1"): self.assertIsInstance(deltas[name], DeltaAddition) self.assertIsInstance(proxies[name], DatablockRefProxy) for name in ("Unlinked0", "Unlinked1"): self.assertIsInstance(deltas[name], DeltaDeletion) self.assertIsInstance(proxies[name], DatablockRefProxy)
def test_datablock_collection(self): # Scene.collection.objects # A collection of references to standalone datablocks # tests DatablockCollectionProxy.apply() # test_diff_apply.Collection.test_datablock_collection for i in range(2): empty = bpy.data.objects.new(f"Unchanged{i}", None) self.scene.collection.objects.link(empty) for i in range(2): empty = bpy.data.objects.new(f"Deleted{i}", None) self.scene.collection.objects.link(empty) self.proxy = BpyDataProxy() self.proxy.load(test_properties) self.scene_proxy = self.proxy.data("scenes").search_one("Scene") self.scene = bpy.data.scenes["Scene"] for i in range(2): empty = bpy.data.objects.new(f"Added{i}", None) self.scene.collection.objects.link(empty) for i in range(2): empty = bpy.data.objects[f"Deleted{i}"] self.scene.collection.objects.unlink(empty) self.generate_all_uuids() scene_delta = self.scene_proxy.diff(self.scene, self.scene.name, self.scenes_property, self.proxy.context()) # delta contains(deleted1, deleted 2, added1, added2) # reset for i in range(2): empty = bpy.data.objects[f"Deleted{i}"] self.scene.collection.objects.link(empty) for i in range(2): empty = bpy.data.objects[f"Added{i}"] self.scene.collection.objects.unlink(empty) # required because the Added{i} were created after proxy load and are not known by the proxy # at this time. IRL the depsgraph handler uses BpyBendDiff to find datablock additions, # then BpyDataProxy.update() self.proxy.load(test_properties) scene = bpy.data.scenes[self.scene.name] self.scene_proxy.apply(scene, bpy.data.scenes, self.scene.name, scene_delta, self.proxy.context()) self.assertIn("Unchanged0", self.scene.collection.objects) self.assertIn("Unchanged1", self.scene.collection.objects) self.assertIn("Added0", self.scene.collection.objects) self.assertIn("Added1", self.scene.collection.objects) self.assertNotIn("Deleted0", self.scene.collection.objects) self.assertNotIn("Deleted1", self.scene.collection.objects)
def test_key_int(self): # Scene.view_settings.curve_mapping.curves # A bpy_prop_collection with string keys # test_diff_compute.Collection.test_key_int self.scene.view_settings.use_curve_mapping = True points_remove = self.scene.view_settings.curve_mapping.curves[0].points points_remove.new(0.5, 0.5) points_add = self.scene.view_settings.curve_mapping.curves[1].points self.proxy = BpyDataProxy() self.proxy.load(test_properties) self.scene_proxy = self.proxy.data("scenes").search_one("Scene") self.scene = bpy.data.scenes["Scene"] points_remove.remove(points_remove[1]) points_add.new(2.0, 2.0) self.generate_all_uuids() scene_delta = self.scene_proxy.diff(self.scene, self.scene.name, self.scenes_property, self.proxy.context()) points_remove_proxy = (scene_delta.value.data("view_settings").data( "curve_mapping").data("curves").data(0).data("points")) self.assertIsInstance(points_remove_proxy, StructCollectionProxy) # points are ordered by location. removing the second one produces an update # at index 1 and a delete at index 2 point1 = points_remove_proxy.data(1) point1_update = point1.data("location", resolve_delta=False) self.assertIsInstance(point1_update, DeltaUpdate) location1 = point1_update.value self.assertAlmostEqual(location1[0], 1.0) self.assertAlmostEqual(location1[1], 1.0) point2 = points_remove_proxy.data(2, resolve_delta=False) self.assertIsInstance(point2, DeltaDeletion) points_add_proxy = (scene_delta.value.data("view_settings").data( "curve_mapping").data("curves").data(1).data("points")) self.assertIsInstance(points_add_proxy, StructCollectionProxy) self.assertIsInstance(points_add_proxy.data(2, resolve_delta=False), DeltaAddition) # points are ordered by location. removing the second one produces an update # at index 1 and a delete at index 2 point = points_add_proxy.data(2) location = point.data("location") self.assertAlmostEqual(location[0], 2.0) self.assertAlmostEqual(location[1], 2.0)
def test_blenddata_filtered(self): blend_data = self.proxy._data scene = blend_data["scenes"].search_one("Scene_0")._data self.assertTrue("eevee" in scene) filter_stack = copy.copy(test_filter) filter_stack.append({T.Scene: [TypeFilterOut(T.SceneEEVEE)]}) proxy = BpyDataProxy() proxy.load(SynchronizedProperties(filter_stack, property_order)) blend_data_ = proxy._data scene_ = blend_data_["scenes"].search_one("Scene_0")._data self.assertFalse("eevee" in scene_)
def test_camera_focus_object_idref(self): # test_misc.TestLoadProxy.test_camera_focus_object_idref cam = D.cameras["Camera_0"] cam.dof.focus_object = D.objects["Cube"] self.proxy = BpyDataProxy() self.proxy.load(test_properties) # load into proxy cam_proxy = self.proxy.data("cameras").search_one("Camera_0") focus_object_proxy = cam_proxy.data("dof").data("focus_object") self.assertIsInstance(focus_object_proxy, DatablockRefProxy) self.assertEqual(focus_object_proxy._datablock_uuid, D.objects["Cube"].mixer_uuid)
def init_protocol(self, vrtist_protocol: bool, shared_folders: List): if not vrtist_protocol: logger.warning("Generic protocol sync is ON") self.bpy_data_proxy = BpyDataProxy() if shared_folders is not None: logger.warning("Setting shared folders: " + str(shared_folders)) else: logger.warning("No shared folder set") self.bpy_data_proxy.set_shared_folders(shared_folders) else: logger.warning("VRtist protocol sync is ON") if self.bpy_data_proxy: self.bpy_data_proxy = None
def test_modify_value(self): # modify a vertex coordinate in a mesh # test_diff_compute.Aos.test_modify_value mesh = bpy.data.meshes.new("Mesh") mesh.vertices.add(4) for i in [0, 1, 2, 3]: v = 10 * i mesh.vertices[i].co = [v, v + 1, v + 2] self.proxy = BpyDataProxy() self.proxy.load(test_properties) mesh_proxy = self.proxy.data("meshes").search_one("Mesh") plane_mesh = bpy.data.meshes["Mesh"] expected_vertex = (-1.0, -2.0, -3.0) plane_mesh.vertices[0].co = expected_vertex expected_vertices = [list(vertex.co) for vertex in mesh.vertices] self.generate_all_uuids() mesh_delta = mesh_proxy.diff(plane_mesh, plane_mesh.name, None, self.proxy.context()) self.assertIsInstance(mesh_delta, DeltaUpdate) mesh_update = mesh_delta.value self.assertIsInstance(mesh_update, DatablockProxy) self.assertTrue(mesh_update.is_standalone_datablock) vertices_delta = mesh_update.data("vertices", resolve_delta=False) self.assertIsInstance(vertices_delta, DeltaUpdate) vertices_update = vertices_delta.value self.assertIsInstance(vertices_update, AosProxy) self.assertTrue(vertices_update) co_delta = vertices_update.data("co", resolve_delta=False) self.assertIsInstance(co_delta, DeltaUpdate) co_update = co_delta.value self.assertIsInstance(co_update, SoaElement) array_ = co_update._array self.assertEqual(len(array_), 4 * 3) vertices = [[ x, y, z ] for x, y, z in zip(array_[0::3], array_[1::3], array_[2::3])] self.assertEqual(vertices, expected_vertices)
def test_write_datablock_with_reference_camera_dof_target(self): # Write the whole camera datablock, including its reference to dof target camera_name = "Camera_0" camera = D.cameras[camera_name] # setup the scene and reload focus_object = D.objects["Cube"] camera.dof.focus_object = focus_object self.proxy = BpyDataProxy() self.proxy.load(synchronized_properties) camera.name = "camera_bak" camera_proxy = self.proxy.data("cameras").search_one(camera_name) camera_proxy.save(D.cameras, camera_name, self.proxy.context()) self.assertEqual(D.cameras[camera_name].dof.focus_object, focus_object)
def test_remove(self): # set reference from a valid datablock to None # test_diff_compute.StructDatablockRef.test_remove world1 = bpy.data.worlds.new("W1") self.scene.world = world1 self.proxy = BpyDataProxy() self.proxy.load(test_properties) self.scene.world = None self.generate_all_uuids() scene_delta = self.scene_proxy.diff(self.scene, self.scene.name, self.scenes_property, self.proxy.context()) # TODO fails. should a null ref be implemented as a DatablockRefProxy # with a null ref (uuid is None) # or what else self.assertIsInstance(scene_delta, DeltaUpdate) world_delta = scene_delta.value.data("world") self.assertIsInstance(world_delta, DeltaDeletion)
def test_add(self): # set reference from NOne to a valid datablock # test_diff_compute.StructDatablockRef.test_add self.scene.world = None self.proxy = BpyDataProxy() self.proxy.load(test_properties) world = bpy.data.worlds.new("W") self.scene.world = world self.generate_all_uuids() scene_delta = self.scene_proxy.diff(self.scene, self.scene.name, self.scenes_property, self.proxy.context()) self.assertIsInstance(scene_delta, DeltaUpdate) world_delta = scene_delta.value.data("world", resolve_delta=False) self.assertIsInstance(world_delta, DeltaUpdate) world_update = world_delta.value self.assertIsInstance(world_update, DatablockRefProxy) self.assertEqual(world_update._datablock_uuid, world.mixer_uuid)
def test_key_int(self): # Scene.view_settings.curve_mapping.curves # A bpy_prop_collection with string keys # test_diff_apply.Collection.test_key_int self.scene.view_settings.use_curve_mapping = True points0 = self.scene.view_settings.curve_mapping.curves[0].points points0.new(0.5, 0.5) points1 = self.scene.view_settings.curve_mapping.curves[1].points self.proxy = BpyDataProxy() self.proxy.load(test_properties) self.scene_proxy = self.proxy.data("scenes").search_one("Scene") self.scene = bpy.data.scenes["Scene"] points0.remove(points0[1]) points1.new(2.0, 2.0) self.generate_all_uuids() scene_delta = self.scene_proxy.diff(self.scene, self.scene.name, self.scenes_property, self.proxy.context()) # the delta contains : # curves[0]: Deletion of element 1 # curves[1]: Addition of element 2 # reset state points0.new(0.5, 0.5) points1.remove(points1[2]) scene = bpy.data.scenes[self.scene.name] self.scene_proxy.apply(scene, bpy.data.scenes, self.scene.name, scene_delta, self.proxy.context()) self.assertEqual(len(points0), 2) self.assertEqual(list(points0[0].location), [0.0, 0.0]) self.assertEqual(list(points0[1].location), [1.0, 1.0]) self.assertEqual(len(points1), 3) self.assertEqual(list(points1[0].location), [0.0, 0.0]) self.assertEqual(list(points1[1].location), [1.0, 1.0]) self.assertEqual(list(points1[2].location), [2.0, 2.0])
def test_key_str(self): # Scene.render.views # A bpy_prop_collection with string keys # tests StructCollectionProxy.apply() # test_diff_apply.Collection.test_key_str self.proxy = BpyDataProxy() self.proxy.load(test_properties) self.scene_proxy = self.proxy.data("scenes").search_one("Scene") self.scene = bpy.data.scenes["Scene"] view_right = self.scene.render.views["right"] self.scene.render.views.remove(view_right) view = self.scene.render.views.new("New") view = self.scene.render.views["left"] view_left_suffix_bak = view.file_suffix view.file_suffix = "new_suffix" self.generate_all_uuids() scene_delta = self.scene_proxy.diff(self.scene, self.scene.name, self.scenes_property, self.proxy.context()) # reset to initial state views = bpy.data.scenes["Scene"].render.views view_right = views.new("right") views["left"].file_suffix = view_left_suffix_bak view_new = views["New"] views.remove(view_new) scene = bpy.data.scenes[self.scene.name] self.scene_proxy.apply(scene, bpy.data.scenes, self.scene.name, scene_delta, self.proxy.context()) self.assertIn("New", views) self.assertIn("left", views) self.assertEqual(views["left"].file_suffix, "new_suffix") self.assertNotIn("right", views)
def test_write_datablock_with_reference_camera_dof_target(self): # Write the whole camera datablock, including its reference to dof target # test_write.TestWriteAttribute.test_write_datablock_with_reference_camera_dof_target camera_name = "Camera_0" camera = D.cameras[camera_name] # setup the scene and reload focus_object = D.objects["Cube"] camera.dof.focus_object = focus_object self.proxy = BpyDataProxy() self.proxy.load(synchronized_properties) camera.name = "camera_bak" camera_proxy = self.proxy.data("cameras").search_one(camera_name) camera_proxy._datablock_uuid = "__" + camera_proxy._datablock_uuid datablock, _ = camera_proxy.create_standalone_datablock( self.proxy.context()) self.assertEqual(datablock.dof.focus_object, focus_object)
def test_remove(self): # set reference from a valid datablock to None # test_diff_compute.StructDatablockRef.test_remove world1 = bpy.data.worlds.new("W1") self.scene.world = world1 self.proxy = BpyDataProxy() self.proxy.load(test_properties) self.scene.world = None self.generate_all_uuids() # delta contains valid ref to None scene_delta = self.scene_proxy.diff(self.scene, self.scene.name, self.scenes_property, self.proxy.context()) self.assertIsInstance(scene_delta, DeltaUpdate) world_delta = scene_delta.value.data("world", resolve_delta=False) self.assertIsInstance(world_delta, DeltaReplace) world_update = world_delta.value self.assertIsInstance(world_update, DatablockRefProxy) self.assertFalse(world_update)
def test_array_curvemap_shrink(self): bpy.ops.wm.open_mainfile(filepath=test_blend_file) light_name = "Light" light = D.lights["Light"] src_points = [(0.666, 0.777), (0.888, 0.999)] curve0 = light.falloff_curve.curves[0] for i, point in enumerate(src_points): curve0.points[i].location = point self.proxy = BpyDataProxy() self.proxy.load(synchronized_properties) light.name = "light_bak" light = None light_proxy = self.proxy.data("lights").search_one(light_name) light_proxy._datablock_uuid = "__" + light_proxy._datablock_uuid light, _ = light_proxy.create_standalone_datablock( self.proxy.context()) dst_curve = light.falloff_curve.curves[0] self.assertEqual(len(src_points), len(dst_curve.points)) # extend the dst curvemap to 3 points dst_points = [(0.111, 0.222), (0.333, 0.444), (0.555, 0.666)] curve0 = light.falloff_curve.curves[0] curve0.points.new(*dst_points[2]) for i, point in enumerate(dst_points): curve0.points[i].location = point self.assertEqual(len(dst_points), len(dst_curve.points)) # restore again, save needs to shrink light_proxy._datablock_uuid = "__" + light_proxy._datablock_uuid light, _ = light_proxy.create_standalone_datablock( self.proxy.context()) dst_curve = light.falloff_curve.curves[0] self.assertEqual(len(src_points), len(dst_curve.points)) for i, point in enumerate(src_points): for dst, expected in zip(dst_curve.points[i].location, point): self.assertAlmostEqual(dst, expected)
def execute(self, context): # Cannot import at module level, since it requires access to bpy.data which is not # accessible during module load from mixer.blender_data.bpy_data_proxy import BpyDataProxy from mixer.blender_data.filter import test_properties import cProfile import io import pstats from pstats import SortKey global proxy profile_cumulative = get_props().profile_cumulative profile_callers = get_props().profile_callers profile = profile_callers or profile_cumulative proxy = BpyDataProxy() if profile: pr = cProfile.Profile() pr.enable() t1 = time.time() proxy.load(test_properties) t2 = time.time() if profile: pr.disable() s = io.StringIO() sortby = SortKey.CUMULATIVE ps = pstats.Stats(pr, stream=s).sort_stats(sortby) if profile_cumulative: ps.print_stats() if profile_callers: ps.print_callers() print(s.getvalue()) logger.warning(f"Elapse: {t2 - t1} s.") non_empty = proxy.get_non_empty_collections() logger.info( f"Number of non empty collections in proxy: {len(non_empty)}") # Put breakpoint here and examinate non_empty dictionnary return {"FINISHED"}
def test_all_soa_grease_pencil(self): # test_misc.TestAosSoa.test_all_soa_grease_pencil import array bpy.ops.object.gpencil_add(type="STROKE") proxy = BpyDataProxy() proxy.load(test_properties) gp = proxy.data("grease_pencils").search_one("Stroke") gp_layer_lines = gp.data("layers").data(1) gp_points = gp_layer_lines.data("frames").data(0).data("strokes").data(0).data("points")._data expected = ( ("co", array.array, "f"), ("pressure", array.array, "f"), ("strength", array.array, "f"), ("uv_factor", array.array, "f"), ("uv_rotation", array.array, "f"), ) for name, type_, element_type in expected: self.assertIn("co", gp_points) item = gp_points[name] self.assertIsInstance(item, SoaElement) self.assertIsInstance(item._array, type_) if type_ is array.array: self.assertEqual(item._array.typecode, element_type) else: self.assertIsInstance(item._array[0], element_type) self.assertEqual(len(gp_points["pressure"]._array), len(gp_points["strength"]._array)) self.assertEqual(3 * len(gp_points["pressure"]._array), len(gp_points["co"]._array)) # Test path resolution for soa buffers stroke = bpy.data.grease_pencils["Stroke"] path = next(iter(gp._soas)) points_attribute, points_gp_points = gp.find_by_path(stroke, path) self.assertEqual(points_attribute, stroke.layers["Lines"].frames[0].strokes[0].points) self.assertIs(points_gp_points._data, gp_points)
def setUp(self): file = test_blend_file # file = r"D:\work\data\test_files\BlenderSS 2_82.blend" bpy.ops.wm.open_mainfile(filepath=file) self.proxy = BpyDataProxy() self.proxy.load(test_properties)
def setUp(self): bpy.ops.wm.open_mainfile(filepath=test_blend_file) self.proxy = BpyDataProxy() register_bl_equals(self, test_properties)
def setUp(self): bpy.ops.wm.open_mainfile(filepath=test_blend_file) self.bpy_data_proxy = BpyDataProxy() self.diff = BpyBlendDiff() bpy.data.worlds[0].name = "World" register_bl_equals(self, safe_properties)
def setUp(self): for w in D.worlds: D.worlds.remove(w) self.proxy = BpyDataProxy()