diff --git a/.gitignore b/.gitignore index bed8f4f..23786bf 100644 --- a/.gitignore +++ b/.gitignore @@ -10,4 +10,7 @@ config multi_user_updater/ # sphinx build folder -_build \ No newline at end of file +_build + +# ignore generated zip generated from blender_addon_tester +*.zip \ No newline at end of file diff --git a/multi_user/bl_types/bl_action.py b/multi_user/bl_types/bl_action.py index 1fc8138..8b994e6 100644 --- a/multi_user/bl_types/bl_action.py +++ b/multi_user/bl_types/bl_action.py @@ -154,8 +154,8 @@ class BlAction(BlDatablock): load_fcurve(dumped_fcurve, fcurve) target.id_root = data['id_root'] - def _dump(self, pointer=None): - assert(pointer) + def _dump(self, instance=None): + assert(instance) dumper = Dumper() dumper.exclude_filter = [ 'name_full', @@ -170,11 +170,11 @@ class BlAction(BlDatablock): 'users' ] dumper.depth = 1 - data = dumper.dump(pointer) + data = dumper.dump(instance) data["fcurves"] = [] - for fcurve in self.pointer.fcurves: + for fcurve in self.instance.fcurves: data["fcurves"].append(dump_fcurve(fcurve, use_numpy=True)) return data diff --git a/multi_user/bl_types/bl_armature.py b/multi_user/bl_types/bl_armature.py index 98bef98..1f556ed 100644 --- a/multi_user/bl_types/bl_armature.py +++ b/multi_user/bl_types/bl_armature.py @@ -46,7 +46,7 @@ class BlArmature(BlDatablock): if parent_object is None: parent_object = bpy.data.objects.new( - data['user_name'], self.pointer) + data['user_name'], self.instance) parent_object.uuid = data['user'] is_object_in_master = ( @@ -81,10 +81,10 @@ class BlArmature(BlDatablock): bpy.ops.object.mode_set(mode='EDIT') for bone in data['bones']: - if bone not in self.pointer.edit_bones: - new_bone = self.pointer.edit_bones.new(bone) + if bone not in self.instance.edit_bones: + new_bone = self.instance.edit_bones.new(bone) else: - new_bone = self.pointer.edit_bones[bone] + new_bone = self.instance.edit_bones[bone] bone_data = data['bones'].get(bone) @@ -94,7 +94,7 @@ class BlArmature(BlDatablock): new_bone.head_radius = bone_data['head_radius'] if 'parent' in bone_data: - new_bone.parent = self.pointer.edit_bones[data['bones'] + new_bone.parent = self.instance.edit_bones[data['bones'] [bone]['parent']] new_bone.use_connect = bone_data['use_connect'] @@ -109,8 +109,8 @@ class BlArmature(BlDatablock): if 'EDIT' in current_mode: bpy.ops.object.mode_set(mode='EDIT') - def _dump_implementation(self, data, pointer=None): - assert(pointer) + def _dump_implementation(self, data, instance=None): + assert(instance) dumper = Dumper() dumper.depth = 4 @@ -126,13 +126,13 @@ class BlArmature(BlDatablock): 'layers' ] - data = dumper.dump(pointer) + data = dumper.dump(instance) - for bone in pointer.bones: + for bone in instance.bones: if bone.parent: data['bones'][bone.name]['parent'] = bone.parent.name # get the parent Object - object_users = utils.get_datablock_users(pointer)[0] + object_users = utils.get_datablock_users(instance)[0] data['user'] = object_users.uuid data['user_name'] = object_users.name diff --git a/multi_user/bl_types/bl_camera.py b/multi_user/bl_types/bl_camera.py index 178d578..0ca33e6 100644 --- a/multi_user/bl_types/bl_camera.py +++ b/multi_user/bl_types/bl_camera.py @@ -45,8 +45,8 @@ class BlCamera(BlDatablock): if dof_settings: loader.load(target.dof, dof_settings) - def _dump_implementation(self, data, pointer=None): - assert(pointer) + def _dump_implementation(self, data, instance=None): + assert(instance) # TODO: background image support @@ -80,6 +80,6 @@ class BlCamera(BlDatablock): 'sensor_height', 'sensor_width', ] - return dumper.dump(pointer) + return dumper.dump(instance) diff --git a/multi_user/bl_types/bl_collection.py b/multi_user/bl_types/bl_collection.py index 1bf3e17..312906b 100644 --- a/multi_user/bl_types/bl_collection.py +++ b/multi_user/bl_types/bl_collection.py @@ -48,35 +48,41 @@ class BlCollection(BlDatablock): # Load other meshes metadata target.name = data["name"] - # link objects + # Objects for object in data["objects"]: - object_ref = utils.find_from_attr('uuid', object, bpy.data.objects) - if object_ref and object_ref.name not in target.objects.keys(): + object_ref = bpy.data.objects.get(object) + + if object_ref is None: + continue + + if object not in target.objects.keys(): target.objects.link(object_ref) for object in target.objects: - if object.uuid not in data["objects"]: + if object.name not in data["objects"]: target.objects.unlink(object) # Link childrens for collection in data["children"]: - collection_ref = utils.find_from_attr( - 'uuid', collection, bpy.data.collections) - if collection_ref and collection_ref.name not in target.children.keys(): + collection_ref = bpy.data.collections.get(collection) + + if collection_ref is None: + continue + if collection_ref.name not in target.children.keys(): target.children.link(collection_ref) for collection in target.children: - if collection.uuid not in data["children"]: + if collection.name not in data["children"]: target.children.unlink(collection) - def _dump_implementation(self, data, pointer=None): - assert(pointer) + def _dump_implementation(self, data, instance=None): + assert(instance) data = {} - data['name'] = pointer.name + data['name'] = instance.name # dump objects collection_objects = [] - for object in pointer.objects: + for object in instance.objects: if object not in collection_objects: collection_objects.append(object.name) @@ -84,7 +90,7 @@ class BlCollection(BlDatablock): # dump children collections collection_children = [] - for child in pointer.children: + for child in instance.children: if child not in collection_children: collection_children.append(child.name) @@ -95,10 +101,9 @@ class BlCollection(BlDatablock): def _resolve_deps_implementation(self): deps = [] - for child in self.pointer.children: + for child in self.instance.children: deps.append(child) - for object in self.pointer.objects: + for object in self.instance.objects: deps.append(object) return deps - diff --git a/multi_user/bl_types/bl_curve.py b/multi_user/bl_types/bl_curve.py index b2ec720..caa1754 100644 --- a/multi_user/bl_types/bl_curve.py +++ b/multi_user/bl_types/bl_curve.py @@ -84,14 +84,14 @@ class BlCurve(BlDatablock): # new_spline.points[point_index], data['splines'][spline]["points"][point_index]) loader.load(new_spline, spline) - def _dump_implementation(self, data, pointer=None): - assert(pointer) + def _dump_implementation(self, data, instance=None): + assert(instance) dumper = Dumper() - data = dumper.dump(pointer) + data = dumper.dump(instance) data['splines'] = {} - for index, spline in enumerate(pointer.splines): + for index, spline in enumerate(instance.splines): dumper.depth = 2 spline_data = dumper.dump(spline) # spline_data['points'] = np_dump_collection(spline.points, SPLINE_POINT) @@ -99,10 +99,10 @@ class BlCurve(BlDatablock): spline_data['bezier_points'] = np_dump_collection(spline.bezier_points, SPLINE_BEZIER_POINT) data['splines'][index] = spline_data - if isinstance(pointer, T.SurfaceCurve): + if isinstance(instance, T.SurfaceCurve): data['type'] = 'SURFACE' - elif isinstance(pointer, T.TextCurve): + elif isinstance(instance, T.TextCurve): data['type'] = 'FONT' - elif isinstance(pointer, T.Curve): + elif isinstance(instance, T.Curve): data['type'] = 'CURVE' return data diff --git a/multi_user/bl_types/bl_datablock.py b/multi_user/bl_types/bl_datablock.py index ed58f27..fc8d03f 100644 --- a/multi_user/bl_types/bl_datablock.py +++ b/multi_user/bl_types/bl_datablock.py @@ -99,54 +99,54 @@ class BlDatablock(ReplicatedDatablock): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) - pointer = kwargs.get('pointer', None) + instance = kwargs.get('instance', None) # TODO: use is_library_indirect - self.is_library = (pointer and hasattr(pointer, 'library') and - pointer.library) or \ + self.is_library = (instance and hasattr(instance, 'library') and + instance.library) or \ (self.data and 'library' in self.data) - if self.pointer and hasattr(self.pointer, 'uuid'): - self.pointer.uuid = self.uuid + if instance and hasattr(instance, 'uuid'): + instance.uuid = self.uuid self.diff_method = DIFF_BINARY - def _resolve(self): + @property + def instance(self): datablock_ref = None datablock_root = getattr(bpy.data, self.bl_id) datablock_ref = utils.find_from_attr('uuid', self.uuid, datablock_root) # In case of lost uuid (ex: undo), resolve by name and reassign it - # TODO: avoid reference storing if not datablock_ref: - datablock_ref = getattr(bpy.data, self.bl_id).get(self.data['name']) + datablock_ref = datablock_root.get(self.data['name']) if datablock_ref: setattr(datablock_ref, 'uuid', self.uuid) - self.pointer = datablock_ref + return datablock_ref - def _dump(self, pointer=None): + def _dump(self, instance=None): dumper = Dumper() data = {} # Dump animation data - if has_action(pointer): + if has_action(instance): dumper = Dumper() dumper.include_filter = ['action'] - data['animation_data'] = dumper.dump(pointer.animation_data) + data['animation_data'] = dumper.dump(instance.animation_data) - if has_driver(pointer): + if has_driver(instance): dumped_drivers = {'animation_data': {'drivers': []}} - for driver in pointer.animation_data.drivers: + for driver in instance.animation_data.drivers: dumped_drivers['animation_data']['drivers'].append( dump_driver(driver)) data.update(dumped_drivers) if self.is_library: - data.update(dumper.dump(pointer)) + data.update(dumper.dump(instance)) else: - data.update(self._dump_implementation(data, pointer=pointer)) + data.update(self._dump_implementation(data, instance=instance)) return data @@ -180,8 +180,8 @@ class BlDatablock(ReplicatedDatablock): def resolve_deps(self): dependencies = [] - if has_action(self.pointer): - dependencies.append(self.pointer.animation_data.action) + if has_action(self.instance): + dependencies.append(self.instance.animation_data.action) if not self.is_library: dependencies.extend(self._resolve_deps_implementation()) diff --git a/multi_user/bl_types/bl_gpencil.py b/multi_user/bl_types/bl_gpencil.py index e3156ed..126873a 100644 --- a/multi_user/bl_types/bl_gpencil.py +++ b/multi_user/bl_types/bl_gpencil.py @@ -95,6 +95,7 @@ def load_stroke(stroke_data, stroke): np_load_collection(stroke_data['points'], stroke.points, STROKE_POINT) + def dump_frame(frame): """ Dump a grease pencil frame to a dict @@ -251,8 +252,8 @@ class BlGpencil(BlDatablock): - def _dump_implementation(self, data, pointer=None): - assert(pointer) + def _dump_implementation(self, data, instance=None): + assert(instance) dumper = Dumper() dumper.depth = 2 dumper.include_filter = [ @@ -263,11 +264,11 @@ class BlGpencil(BlDatablock): 'pixel_factor', 'stroke_depth_order' ] - data = dumper.dump(pointer) + data = dumper.dump(instance) data['layers'] = {} - for layer in pointer.layers: + for layer in instance.layers: data['layers'][layer.info] = dump_layer(layer) return data @@ -275,7 +276,7 @@ class BlGpencil(BlDatablock): def _resolve_deps_implementation(self): deps = [] - for material in self.pointer.materials: + for material in self.instance.materials: deps.append(material) return deps diff --git a/multi_user/bl_types/bl_image.py b/multi_user/bl_types/bl_image.py index 4a9ce9c..df62602 100644 --- a/multi_user/bl_types/bl_image.py +++ b/multi_user/bl_types/bl_image.py @@ -80,10 +80,10 @@ class BlImage(BlDatablock): image.colorspace_settings.name = data["colorspace_settings"]["name"] - def _dump(self, pointer=None): - assert(pointer) + def _dump(self, instance=None): + assert(instance) data = {} - data['pixels'] = dump_image(pointer) + data['pixels'] = dump_image(instance) dumper = Dumper() dumper.depth = 2 dumper.include_filter = [ @@ -95,7 +95,7 @@ class BlImage(BlDatablock): 'filepath', 'source', 'colorspace_settings'] - data.update(dumper.dump(pointer)) + data.update(dumper.dump(instance)) return data diff --git a/multi_user/bl_types/bl_io.py b/multi_user/bl_types/bl_io.py new file mode 100644 index 0000000..65bd139 --- /dev/null +++ b/multi_user/bl_types/bl_io.py @@ -0,0 +1,4 @@ +from . import * + +def dump(datablock): + pass \ No newline at end of file diff --git a/multi_user/bl_types/bl_lattice.py b/multi_user/bl_types/bl_lattice.py index 238a2a9..950cf7e 100644 --- a/multi_user/bl_types/bl_lattice.py +++ b/multi_user/bl_types/bl_lattice.py @@ -42,8 +42,8 @@ class BlLattice(BlDatablock): np_load_collection(data['points'], target.points, POINT) - def _dump_implementation(self, data, pointer=None): - assert(pointer) + def _dump_implementation(self, data, instance=None): + assert(instance) dumper = Dumper() dumper.depth = 1 @@ -58,8 +58,8 @@ class BlLattice(BlDatablock): 'interpolation_type_w', 'use_outside' ] - data = dumper.dump(pointer) + data = dumper.dump(instance) - data['points'] = np_dump_collection(pointer.points, POINT) + data['points'] = np_dump_collection(instance.points, POINT) return data diff --git a/multi_user/bl_types/bl_library.py b/multi_user/bl_types/bl_library.py index f5b1753..e2f1adc 100644 --- a/multi_user/bl_types/bl_library.py +++ b/multi_user/bl_types/bl_library.py @@ -38,9 +38,9 @@ class BlLibrary(BlDatablock): def _load(self, data, target): pass - def dump(self, pointer=None): - assert(pointer) + def _dump(self, instance=None): + assert(instance) dumper = Dumper() - return dumper.dump(pointer) + return dumper.dump(instance) diff --git a/multi_user/bl_types/bl_light.py b/multi_user/bl_types/bl_light.py index 891bb8f..4f8c933 100644 --- a/multi_user/bl_types/bl_light.py +++ b/multi_user/bl_types/bl_light.py @@ -38,8 +38,8 @@ class BlLight(BlDatablock): loader = Loader() loader.load(target, data) - def _dump_implementation(self, data, pointer=None): - assert(pointer) + def _dump_implementation(self, data, instance=None): + assert(instance) dumper = Dumper() dumper.depth = 3 dumper.include_filter = [ @@ -66,7 +66,7 @@ class BlLight(BlDatablock): "size", "angle" ] - data = dumper.dump(pointer) + data = dumper.dump(instance) return data diff --git a/multi_user/bl_types/bl_lightprobe.py b/multi_user/bl_types/bl_lightprobe.py index 7da2b7e..d1ae0b9 100644 --- a/multi_user/bl_types/bl_lightprobe.py +++ b/multi_user/bl_types/bl_lightprobe.py @@ -45,8 +45,8 @@ class BlLightprobe(BlDatablock): loader = Loader() loader.load(target, data) - def _dump_implementation(self, data, pointer=None): - assert(pointer) + def _dump_implementation(self, data, instance=None): + assert(instance) if bpy.app.version[1] < 83: logger.warning("Lightprobe replication only supported since 2.83. See https://developer.blender.org/D6396") @@ -73,7 +73,7 @@ class BlLightprobe(BlDatablock): 'visibility_blur' ] - return dumper.dump(pointer) + return dumper.dump(instance) diff --git a/multi_user/bl_types/bl_material.py b/multi_user/bl_types/bl_material.py index f230ef1..9250371 100644 --- a/multi_user/bl_types/bl_material.py +++ b/multi_user/bl_types/bl_material.py @@ -195,8 +195,8 @@ class BlMaterial(BlDatablock): load_links(data["node_tree"]["links"], target.node_tree) - def _dump_implementation(self, data, pointer=None): - assert(pointer) + def _dump_implementation(self, data, instance=None): + assert(instance) mat_dumper = Dumper() mat_dumper.depth = 2 mat_dumper.exclude_filter = [ @@ -215,17 +215,17 @@ class BlMaterial(BlDatablock): "line_color", "view_center", ] - data = mat_dumper.dump(pointer) + data = mat_dumper.dump(instance) - if pointer.use_nodes: + if instance.use_nodes: nodes = {} - for node in pointer.node_tree.nodes: + for node in instance.node_tree.nodes: nodes[node.name] = dump_node(node) data["node_tree"]['nodes'] = nodes - data["node_tree"]["links"] = dump_links(pointer.node_tree.links) + data["node_tree"]["links"] = dump_links(instance.node_tree.links) - if pointer.is_grease_pencil: + if instance.is_grease_pencil: gp_mat_dumper = Dumper() gp_mat_dumper.depth = 3 @@ -251,19 +251,19 @@ class BlMaterial(BlDatablock): 'mix_color', 'flip' ] - data['grease_pencil'] = gp_mat_dumper.dump(pointer.grease_pencil) + data['grease_pencil'] = gp_mat_dumper.dump(instance.grease_pencil) return data def _resolve_deps_implementation(self): # TODO: resolve node group deps deps = [] - if self.pointer.use_nodes: - for node in self.pointer.node_tree.nodes: + if self.instance.use_nodes: + for node in self.instance.node_tree.nodes: if node.type == 'TEX_IMAGE': deps.append(node.image) if self.is_library: - deps.append(self.pointer.library) + deps.append(self.instance.library) return deps diff --git a/multi_user/bl_types/bl_mesh.py b/multi_user/bl_types/bl_mesh.py index bd8d618..4992655 100644 --- a/multi_user/bl_types/bl_mesh.py +++ b/multi_user/bl_types/bl_mesh.py @@ -109,10 +109,10 @@ class BlMesh(BlDatablock): target.validate() target.update() - def _dump_implementation(self, data, pointer=None): - assert(pointer) + def _dump_implementation(self, data, instance=None): + assert(instance) - mesh = pointer + mesh = instance dumper = Dumper() dumper.depth = 1 @@ -156,7 +156,7 @@ class BlMesh(BlDatablock): # Fix material index m_list = [] - for material in pointer.materials: + for material in instance.materials: if material: m_list.append(material.name) @@ -167,7 +167,7 @@ class BlMesh(BlDatablock): def _resolve_deps_implementation(self): deps = [] - for material in self.pointer.materials: + for material in self.instance.materials: if material: deps.append(material) diff --git a/multi_user/bl_types/bl_metaball.py b/multi_user/bl_types/bl_metaball.py index 22eeea5..32d3f01 100644 --- a/multi_user/bl_types/bl_metaball.py +++ b/multi_user/bl_types/bl_metaball.py @@ -84,8 +84,8 @@ class BlMetaball(BlDatablock): load_metaball_elements(data['elements'], target.elements) - def _dump_implementation(self, data, pointer=None): - assert(pointer) + def _dump_implementation(self, data, instance=None): + assert(instance) dumper = Dumper() dumper.depth = 1 dumper.exclude_filter = [ @@ -96,7 +96,7 @@ class BlMetaball(BlDatablock): "name_full" ] - data = dumper.dump(pointer) - data['elements'] = dump_metaball_elements(pointer.elements) + data = dumper.dump(instance) + data['elements'] = dump_metaball_elements(instance.elements) return data diff --git a/multi_user/bl_types/bl_object.py b/multi_user/bl_types/bl_object.py index 9e45ed7..5cf226b 100644 --- a/multi_user/bl_types/bl_object.py +++ b/multi_user/bl_types/bl_object.py @@ -41,7 +41,7 @@ class BlObject(BlDatablock): bl_icon = 'OBJECT_DATA' def _construct(self, data): - pointer = None + instance = None if self.is_library: with bpy.data.libraries.load(filepath=bpy.data.libraries[self.data['library']].filepath, link=True) as (sourceData, targetData): @@ -56,33 +56,33 @@ class BlObject(BlDatablock): if "data" not in data: pass elif data["data"] in bpy.data.meshes.keys(): - pointer = bpy.data.meshes[data["data"]] + instance = bpy.data.meshes[data["data"]] elif data["data"] in bpy.data.lights.keys(): - pointer = bpy.data.lights[data["data"]] + instance = bpy.data.lights[data["data"]] elif data["data"] in bpy.data.cameras.keys(): - pointer = bpy.data.cameras[data["data"]] + instance = bpy.data.cameras[data["data"]] elif data["data"] in bpy.data.curves.keys(): - pointer = bpy.data.curves[data["data"]] + instance = bpy.data.curves[data["data"]] elif data["data"] in bpy.data.metaballs.keys(): - pointer = bpy.data.metaballs[data["data"]] + instance = bpy.data.metaballs[data["data"]] elif data["data"] in bpy.data.armatures.keys(): - pointer = bpy.data.armatures[data["data"]] + instance = bpy.data.armatures[data["data"]] elif data["data"] in bpy.data.grease_pencils.keys(): - pointer = bpy.data.grease_pencils[data["data"]] + instance = bpy.data.grease_pencils[data["data"]] elif data["data"] in bpy.data.curves.keys(): - pointer = bpy.data.curves[data["data"]] + instance = bpy.data.curves[data["data"]] elif data["data"] in bpy.data.lattices.keys(): - pointer = bpy.data.lattices[data["data"]] + instance = bpy.data.lattices[data["data"]] elif data["data"] in bpy.data.speakers.keys(): - pointer = bpy.data.speakers[data["data"]] + instance = bpy.data.speakers[data["data"]] elif data["data"] in bpy.data.lightprobes.keys(): # Only supported since 2.83 if bpy.app.version[1] >= 83: - pointer = bpy.data.lightprobes[data["data"]] + instance = bpy.data.lightprobes[data["data"]] else: logger.warning( "Lightprobe replication only supported since 2.83. See https://developer.blender.org/D6396") - instance = bpy.data.objects.new(data["name"], pointer) + instance = bpy.data.objects.new(data["name"], instance) instance.uuid = self.uuid return instance @@ -152,8 +152,8 @@ class BlObject(BlDatablock): target.data.shape_keys.key_blocks[key_block].relative_key = target.data.shape_keys.key_blocks[reference] - def _dump_implementation(self, data, pointer=None): - assert(pointer) + def _dump_implementation(self, data, instance=None): + assert(instance) dumper = Dumper() dumper.depth = 1 dumper.include_filter = [ @@ -169,33 +169,33 @@ class BlObject(BlDatablock): "instance_type", "location", "scale", - 'rotation_quaternion' if pointer.rotation_mode == 'QUATERNION' else 'rotation_euler', + 'rotation_quaternion' if instance.rotation_mode == 'QUATERNION' else 'rotation_euler', ] - data = dumper.dump(pointer) + data = dumper.dump(instance) if self.is_library: return data # MODIFIERS - if hasattr(pointer, 'modifiers'): + if hasattr(instance, 'modifiers'): dumper.include_filter = None dumper.depth = 2 data["modifiers"] = {} - for index, modifier in enumerate(pointer.modifiers): + for index, modifier in enumerate(instance.modifiers): data["modifiers"][modifier.name] = dumper.dump(modifier) # CONSTRAINTS # OBJECT - if hasattr(pointer, 'constraints'): + if hasattr(instance, 'constraints'): dumper.depth = 3 - data["constraints"] = dumper.dump(pointer.constraints) + data["constraints"] = dumper.dump(instance.constraints) # POSE - if hasattr(pointer, 'pose') and pointer.pose: + if hasattr(instance, 'pose') and instance.pose: # BONES bones = {} - for bone in pointer.pose.bones: + for bone in instance.pose.bones: bones[bone.name] = {} dumper.depth = 1 rotation = 'rotation_quaternion' if bone.rotation_mode == 'QUATERNION' else 'rotation_euler' @@ -220,7 +220,7 @@ class BlObject(BlDatablock): # GROUPS bone_groups = {} - for group in pointer.pose.bone_groups: + for group in instance.pose.bone_groups: dumper.depth = 3 dumper.include_filter = [ 'name', @@ -230,24 +230,24 @@ class BlObject(BlDatablock): data['pose']['bone_groups'] = bone_groups # CHILDS - if len(pointer.children) > 0: + if len(instance.children) > 0: childs = [] - for child in pointer.children: + for child in instance.children: childs.append(child.name) data["children"] = childs # VERTEx GROUP - if len(pointer.vertex_groups) > 0: + if len(instance.vertex_groups) > 0: vg_data = [] - for vg in pointer.vertex_groups: + for vg in instance.vertex_groups: vg_idx = vg.index dumped_vg = {} dumped_vg['name'] = vg.name vertices = [] - for v in pointer.data.vertices: + for v in instance.data.vertices: for vg in v.groups: if vg.group == vg_idx: vertices.append({ @@ -262,7 +262,7 @@ class BlObject(BlDatablock): data['vertex_groups'] = vg_data # SHAPE KEYS - object_data = pointer.data + object_data = instance.data if hasattr(object_data, 'shape_keys') and object_data.shape_keys: dumper = Dumper() dumper.depth = 2 @@ -295,17 +295,17 @@ class BlObject(BlDatablock): deps = [] # Avoid Empty case - if self.pointer.data: - deps.append(self.pointer.data) - if len(self.pointer.children) > 0: - deps.extend(list(self.pointer.children)) + if self.instance.data: + deps.append(self.instance.data) + if len(self.instance.children) > 0: + deps.extend(list(self.instance.children)) if self.is_library: - deps.append(self.pointer.library) + deps.append(self.instance.library) - if self.pointer.instance_type == 'COLLECTION': + if self.instance.instance_type == 'COLLECTION': # TODO: uuid based - deps.append(self.pointer.instance_collection) + deps.append(self.instance.instance_collection) return deps diff --git a/multi_user/bl_types/bl_scene.py b/multi_user/bl_types/bl_scene.py index 3e4b91e..a563af3 100644 --- a/multi_user/bl_types/bl_scene.py +++ b/multi_user/bl_types/bl_scene.py @@ -37,7 +37,7 @@ class BlScene(BlDatablock): return instance def _load_implementation(self, data, target): - target = self.pointer + target = self.instance # Load other meshes metadata loader = Loader() loader.load(target, data) @@ -83,8 +83,8 @@ class BlScene(BlDatablock): target.view_settings.curve_mapping.black_level = data['view_settings']['curve_mapping']['black_level'] target.view_settings.curve_mapping.update() - def _dump_implementation(self, data, pointer=None): - assert(pointer) + def _dump_implementation(self, data, instance=None): + assert(instance) data = {} scene_dumper = Dumper() @@ -96,12 +96,12 @@ class BlScene(BlDatablock): 'camera', 'grease_pencil', ] - data = scene_dumper.dump(pointer) + data = scene_dumper.dump(instance) scene_dumper.depth = 3 scene_dumper.include_filter = ['children','objects','name'] - data['collection'] = scene_dumper.dump(pointer.collection) + data['collection'] = scene_dumper.dump(instance.collection) scene_dumper.depth = 1 scene_dumper.include_filter = None @@ -124,19 +124,19 @@ class BlScene(BlDatablock): 'samples', 'volume_bounces' ] - data['eevee'] = scene_dumper.dump(pointer.eevee) - data['cycles'] = scene_dumper.dump(pointer.cycles) - data['view_settings'] = scene_dumper.dump(pointer.view_settings) - data['view_settings']['curve_mapping'] = scene_dumper.dump(pointer.view_settings.curve_mapping) + data['eevee'] = scene_dumper.dump(instance.eevee) + data['cycles'] = scene_dumper.dump(instance.cycles) + data['view_settings'] = scene_dumper.dump(instance.view_settings) + data['view_settings']['curve_mapping'] = scene_dumper.dump(instance.view_settings.curve_mapping) - if pointer.view_settings.use_curve_mapping: + if instance.view_settings.use_curve_mapping: scene_dumper.depth = 5 scene_dumper.include_filter = [ 'curves', 'points', 'location' ] - data['view_settings']['curve_mapping']['curves'] = scene_dumper.dump(pointer.view_settings.curve_mapping.curves) + data['view_settings']['curve_mapping']['curves'] = scene_dumper.dump(instance.view_settings.curve_mapping.curves) return data @@ -145,19 +145,19 @@ class BlScene(BlDatablock): deps = [] # child collections - for child in self.pointer.collection.children: + for child in self.instance.collection.children: deps.append(child) # childs objects - for object in self.pointer.objects: + for object in self.instance.objects: deps.append(object) # world - if self.pointer.world: - deps.append(self.pointer.world) + if self.instance.world: + deps.append(self.instance.world) # annotations - if self.pointer.grease_pencil: - deps.append(self.pointer.grease_pencil) + if self.instance.grease_pencil: + deps.append(self.instance.grease_pencil) return deps diff --git a/multi_user/bl_types/bl_speaker.py b/multi_user/bl_types/bl_speaker.py index 3d419f9..5276279 100644 --- a/multi_user/bl_types/bl_speaker.py +++ b/multi_user/bl_types/bl_speaker.py @@ -38,8 +38,8 @@ class BlSpeaker(BlDatablock): def _construct(self, data): return bpy.data.speakers.new(data["name"]) - def _dump_implementation(self, data, pointer=None): - assert(pointer) + def _dump_implementation(self, data, instance=None): + assert(instance) dumper = Dumper() dumper.depth = 1 @@ -58,7 +58,7 @@ class BlSpeaker(BlDatablock): 'cone_volume_outer' ] - return dumper.dump(pointer) + return dumper.dump(instance) diff --git a/multi_user/bl_types/bl_world.py b/multi_user/bl_types/bl_world.py index 7fffb53..a9b8feb 100644 --- a/multi_user/bl_types/bl_world.py +++ b/multi_user/bl_types/bl_world.py @@ -51,8 +51,8 @@ class BlWorld(BlDatablock): load_links(data["node_tree"]["links"], target.node_tree) - def _dump_implementation(self, data, pointer=None): - assert(pointer) + def _dump_implementation(self, data, instance=None): + assert(instance) world_dumper = Dumper() world_dumper.depth = 2 @@ -66,27 +66,27 @@ class BlWorld(BlDatablock): "users", "view_center" ] - data = world_dumper.dump(pointer) - if pointer.use_nodes: + data = world_dumper.dump(instance) + if instance.use_nodes: nodes = {} - for node in pointer.node_tree.nodes: + for node in instance.node_tree.nodes: nodes[node.name] = dump_node(node) data["node_tree"]['nodes'] = nodes - data["node_tree"]['links'] = dump_links(pointer.node_tree.links) + data["node_tree"]['links'] = dump_links(instance.node_tree.links) return data def _resolve_deps_implementation(self): deps = [] - if self.pointer.use_nodes: - for node in self.pointer.node_tree.nodes: + if self.instance.use_nodes: + for node in self.instance.node_tree.nodes: if node.type == 'TEX_IMAGE': deps.append(node.image) if self.is_library: - deps.append(self.pointer.library) + deps.append(self.instance.library) return deps diff --git a/multi_user/bl_types/dump_anything.py b/multi_user/bl_types/dump_anything.py index e97fa63..93b3772 100644 --- a/multi_user/bl_types/dump_anything.py +++ b/multi_user/bl_types/dump_anything.py @@ -192,7 +192,7 @@ def np_load_collection_primitives(collection: bpy.types.CollectionProperty, attr :arg sequence: data buffer :type sequence: strr """ - if len(collection) == 0: + if len(collection) == 0 or not sequence: logger.warning(f"Skipping loadin {attribute}") return @@ -503,7 +503,7 @@ class Loader: DESTRUCTOR_REMOVE = "remove" DESTRUCTOR_CLEAR = "clear" - constructors = { + _constructors = { T.ColorRampElement: (CONSTRUCTOR_NEW, ["position"]), T.ParticleSettingsTextureSlot: (CONSTRUCTOR_ADD, []), T.Modifier: (CONSTRUCTOR_NEW, ["name", "type"]), @@ -517,9 +517,9 @@ class Loader: } element_type = element.bl_rna_property.fixed_type - constructor = constructors.get(type(element_type)) + _constructor = _constructors.get(type(element_type)) - if constructor is None: # collection type not supported + if _constructor is None: # collection type not supported return destructor = destructors.get(type(element_type)) @@ -538,14 +538,14 @@ class Loader: new_element = element.read()[0] else: try: - constructor_parameters = [dumped_element[name] - for name in constructor[1]] + _constructor_parameters = [dumped_element[name] + for name in _constructor[1]] except KeyError: logger.debug("Collection load error, missing parameters.") continue # TODO handle error - new_element = getattr(element.read(), constructor[0])( - *constructor_parameters) + new_element = getattr(element.read(), _constructor[0])( + *_constructor_parameters) self._load_any( BlenderAPIElement( new_element, occlude_read_only=self.occlude_read_only), @@ -576,24 +576,24 @@ class Loader: else: dst_curve.points.new(pos[0], pos[1]) - def _load_pointer(self, pointer, dump): - rna_property_type = pointer.bl_rna_property.fixed_type + def _load_pointer(self, instance, dump): + rna_property_type = instance.bl_rna_property.fixed_type if not rna_property_type: return if isinstance(rna_property_type, T.Image): - pointer.write(bpy.data.images.get(dump)) + instance.write(bpy.data.images.get(dump)) elif isinstance(rna_property_type, T.Texture): - pointer.write(bpy.data.textures.get(dump)) + instance.write(bpy.data.textures.get(dump)) elif isinstance(rna_property_type, T.ColorRamp): - self._load_default(pointer, dump) + self._load_default(instance, dump) elif isinstance(rna_property_type, T.Object): - pointer.write(bpy.data.objects.get(dump)) + instance.write(bpy.data.objects.get(dump)) elif isinstance(rna_property_type, T.Mesh): - pointer.write(bpy.data.meshes.get(dump)) + instance.write(bpy.data.meshes.get(dump)) elif isinstance(rna_property_type, T.Material): - pointer.write(bpy.data.materials.get(dump)) + instance.write(bpy.data.materials.get(dump)) elif isinstance(rna_property_type, T.Collection): - pointer.write(bpy.data.collections.get(dump)) + instance.write(bpy.data.collections.get(dump)) def _load_matrix(self, matrix, dump): matrix.write(mathutils.Matrix(dump)) diff --git a/multi_user/libs/replication b/multi_user/libs/replication index cc66d1d..c5a3997 160000 --- a/multi_user/libs/replication +++ b/multi_user/libs/replication @@ -1 +1 @@ -Subproject commit cc66d1d8e4b4a0351faeb6deeacf69693dcafcab +Subproject commit c5a39975590c99b9728e6364d9b16b72bb6765ca diff --git a/multi_user/operators.py b/multi_user/operators.py index 4c7560c..2b69b86 100644 --- a/multi_user/operators.py +++ b/multi_user/operators.py @@ -507,19 +507,7 @@ def load_pre_handler(dummy): bpy.ops.session.stop() -@persistent -def sanitize_deps_graph(dummy): - """sanitize deps graph - Temporary solution to resolve each node pointers after a Undo. - A future solution should be to avoid storing dataclock reference... - - """ - global client - - if client and client.state['STATE'] in [STATE_ACTIVE]: - for node_key in client.list(): - client.get(node_key)._resolve() @persistent @@ -571,8 +559,6 @@ def register(): bpy.app.handlers.load_pre.append(load_pre_handler) - bpy.app.handlers.undo_post.append(sanitize_deps_graph) - bpy.app.handlers.redo_post.append(sanitize_deps_graph) bpy.app.handlers.frame_change_pre.append(update_client_frame) @@ -592,8 +578,6 @@ def unregister(): bpy.app.handlers.load_pre.remove(load_pre_handler) - bpy.app.handlers.undo_post.remove(sanitize_deps_graph) - bpy.app.handlers.redo_post.remove(sanitize_deps_graph) bpy.app.handlers.frame_change_pre.remove(update_client_frame) diff --git a/scripts/test_addon.py b/scripts/test_addon.py new file mode 100644 index 0000000..6008406 --- /dev/null +++ b/scripts/test_addon.py @@ -0,0 +1,25 @@ +import sys +try: + import blender_addon_tester as BAT +except Exception as e: + print(e) + sys.exit(1) + +def main(): + if len(sys.argv) > 1: + addon = sys.argv[1] + else: + addon = "multi_user" + if len(sys.argv) > 2: + blender_rev = sys.argv[2] + else: + blender_rev = "2.82" + + try: + exit_val = BAT.test_blender_addon(addon_path=addon, blender_revision=blender_rev) + except Exception as e: + print(e) + exit_val = 1 + sys.exit(exit_val) + +main() \ No newline at end of file diff --git a/tests/test_bl_types/light.blend b/tests/test_bl_types/light.blend new file mode 100644 index 0000000..479bfe4 Binary files /dev/null and b/tests/test_bl_types/light.blend differ diff --git a/tests/test_bl_types/test_lights.py b/tests/test_bl_types/test_lights.py new file mode 100644 index 0000000..c47ffe8 --- /dev/null +++ b/tests/test_bl_types/test_lights.py @@ -0,0 +1,24 @@ +import pytest +import os +# from deepdiff import DeepDiff + +from multi_user.bl_types.bl_light import BlLight +import bpy + +@pytest.fixture +def load_test_file(): + dir_path = os.path.dirname(os.path.realpath(__file__)) + bpy.ops.wm.open_mainfile(filepath=os.path.join(dir_path,"light.blend")) + + +def test_light(load_test_file): + from jsondiff import diff + blender_light = bpy.data.lights['point'] + light_dumper = BlLight(owner='None') + sample_data = light_dumper._dump(blender_light) + bpy.data.lights.remove(blender_light) + + test = light_dumper._construct(sample_data) + light_dumper._load(sample_data, test) + sample_2 = light_dumper._dump(test) + assert diff(sample_data,test), False