From 664f7635ccdb02caf2b4e5421a16f71d40e246f5 Mon Sep 17 00:00:00 2001 From: Swann Date: Tue, 3 Nov 2020 16:15:34 +0100 Subject: [PATCH 1/4] feat: support empty id_root in actions --- multi_user/__init__.py | 2 +- multi_user/bl_types/bl_action.py | 13 +++++++++---- multi_user/bl_types/bl_mesh.py | 7 +------ 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/multi_user/__init__.py b/multi_user/__init__.py index 0b76f90..d7a1248 100644 --- a/multi_user/__init__.py +++ b/multi_user/__init__.py @@ -44,7 +44,7 @@ from . import environment DEPENDENCIES = { - ("replication", '0.1.6'), + ("replication", '0.1.7'), } diff --git a/multi_user/bl_types/bl_action.py b/multi_user/bl_types/bl_action.py index 15d3622..253a13e 100644 --- a/multi_user/bl_types/bl_action.py +++ b/multi_user/bl_types/bl_action.py @@ -42,7 +42,7 @@ KEYFRAME = [ ] -def dump_fcurve(fcurve: bpy.types.FCurve, use_numpy:bool =True) -> dict: +def dump_fcurve(fcurve: bpy.types.FCurve, use_numpy: bool = True) -> dict: """ Dump a sigle curve to a dict :arg fcurve: fcurve to dump @@ -59,7 +59,7 @@ def dump_fcurve(fcurve: bpy.types.FCurve, use_numpy:bool =True) -> dict: if use_numpy: points = fcurve.keyframe_points - fcurve_data['keyframes_count'] = len(fcurve.keyframe_points) + fcurve_data['keyframes_count'] = len(fcurve.keyframe_points) fcurve_data['keyframe_points'] = np_dump_collection(points, KEYFRAME) else: # Legacy method @@ -92,7 +92,8 @@ def load_fcurve(fcurve_data, fcurve): if use_numpy: keyframe_points.add(fcurve_data['keyframes_count']) - np_load_collection(fcurve_data["keyframe_points"], keyframe_points, KEYFRAME) + np_load_collection( + fcurve_data["keyframe_points"], keyframe_points, KEYFRAME) else: # paste dumped keyframes @@ -153,7 +154,11 @@ class BlAction(BlDatablock): dumped_data_path, index=dumped_array_index) load_fcurve(dumped_fcurve, fcurve) - target.id_root = data['id_root'] + + id_root = data.get('id_root') + + if id_root: + target.id_root = id_root def _dump_implementation(self, data, instance=None): dumper = Dumper() diff --git a/multi_user/bl_types/bl_mesh.py b/multi_user/bl_types/bl_mesh.py index cf6982c..70546b7 100644 --- a/multi_user/bl_types/bl_mesh.py +++ b/multi_user/bl_types/bl_mesh.py @@ -172,12 +172,7 @@ class BlMesh(BlDatablock): data['vertex_colors'][color_map.name]['data'] = np_dump_collection_primitive(color_map.data, 'color') # Fix material index - m_list = [] - for material in instance.materials: - if material: - m_list.append((material.uuid,material.name)) - - data['material_list'] = m_list + data['material_list'] = [(m.uuid, m.name) for m in instance.materials if m] return data From c710111887e3825cf80dbe37ec3f0b48b90f31a4 Mon Sep 17 00:00:00 2001 From: Swann Date: Tue, 3 Nov 2020 16:44:42 +0100 Subject: [PATCH 2/4] feat: test to hot reload newly installed module --- multi_user/environment.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/multi_user/environment.py b/multi_user/environment.py index 8796a4c..5fc47a3 100644 --- a/multi_user/environment.py +++ b/multi_user/environment.py @@ -62,6 +62,9 @@ def install_package(name, version): del env["PIP_REQUIRE_VIRTUALENV"] subprocess.run([str(PYTHON_PATH), "-m", "pip", "install", f"{name}=={version}"], env=env) + if name in sys.modules: + del sys.modules[name] + def check_package_version(name, required_version): logging.info(f"Checking {name} version...") out = subprocess.run([str(PYTHON_PATH), "-m", "pip", "show", name], capture_output=True) From 371d793a134e6fdefa0dad1ad1631e3a33348cd8 Mon Sep 17 00:00:00 2001 From: Swann Date: Tue, 3 Nov 2020 23:17:08 +0100 Subject: [PATCH 3/4] fix: materials Math and Vector node sync Related to #137 --- multi_user/bl_types/bl_material.py | 44 ++++++++++++++---------------- 1 file changed, 20 insertions(+), 24 deletions(-) diff --git a/multi_user/bl_types/bl_material.py b/multi_user/bl_types/bl_material.py index 376a077..f096749 100644 --- a/multi_user/bl_types/bl_material.py +++ b/multi_user/bl_types/bl_material.py @@ -37,28 +37,28 @@ def load_node(node_data, node_tree): """ loader = Loader() target_node = node_tree.nodes.new(type=node_data["bl_idname"]) - + target_node.select = False loader.load(target_node, node_data) image_uuid = node_data.get('image_uuid', None) if image_uuid and not target_node.image: target_node.image = get_datablock_from_uuid(image_uuid, None) - for input in node_data["inputs"]: - if hasattr(target_node.inputs[input], "default_value"): + for idx, inpt in enumerate(node_data["inputs"]): + if hasattr(target_node.inputs[idx], "default_value"): try: - target_node.inputs[input].default_value = node_data["inputs"][input]["default_value"] + target_node.inputs[idx].default_value = inpt["default_value"] except: logging.error( - f"Material {input} parameter not supported, skipping") + f"Material {inpt.keys()} parameter not supported, skipping") - for output in node_data["outputs"]: - if hasattr(target_node.outputs[output], "default_value"): + for idx, output in enumerate(node_data["outputs"]): + if hasattr(target_node.outputs[idx], "default_value"): try: - target_node.outputs[output].default_value = node_data["outputs"][output]["default_value"] + target_node.outputs[idx].default_value = output["default_value"] except: logging.error( - f"Material {output} parameter not supported, skipping") + f"Material {output.keys()} parameter not supported, skipping") def load_links(links_data, node_tree): @@ -142,24 +142,20 @@ def dump_node(node): dumped_node = node_dumper.dump(node) if hasattr(node, 'inputs'): - dumped_node['inputs'] = {} + dumped_node['inputs'] = [] - for i in node.inputs: - input_dumper = Dumper() - input_dumper.depth = 2 - input_dumper.include_filter = ["default_value"] + io_dumper = Dumper() + io_dumper.depth = 2 + io_dumper.include_filter = ["default_value"] - if hasattr(i, 'default_value'): - dumped_node['inputs'][i.name] = input_dumper.dump(i) + for idx, inpt in enumerate(node.inputs): + if hasattr(inpt, 'default_value'): + dumped_node['inputs'].append(io_dumper.dump(inpt)) - dumped_node['outputs'] = {} - for i in node.outputs: - output_dumper = Dumper() - output_dumper.depth = 2 - output_dumper.include_filter = ["default_value"] - - if hasattr(i, 'default_value'): - dumped_node['outputs'][i.name] = output_dumper.dump(i) + dumped_node['outputs'] = [] + for idx, output in enumerate(node.outputs): + if hasattr(output, 'default_value'): + dumped_node['outputs'].append(io_dumper.dump(output)) if hasattr(node, 'color_ramp'): ramp_dumper = Dumper() From 17949003f74af4791d8b85a193162cb315fa9b51 Mon Sep 17 00:00:00 2001 From: Swann Date: Tue, 3 Nov 2020 23:44:25 +0100 Subject: [PATCH 4/4] refactor: remove reparent mecanism fix: empty camera background image fix: object data reassignation --- multi_user/__init__.py | 2 +- multi_user/bl_types/bl_camera.py | 11 +++++++---- multi_user/bl_types/bl_object.py | 9 +++------ multi_user/delayable.py | 12 +----------- 4 files changed, 12 insertions(+), 22 deletions(-) diff --git a/multi_user/__init__.py b/multi_user/__init__.py index d7a1248..98c4103 100644 --- a/multi_user/__init__.py +++ b/multi_user/__init__.py @@ -44,7 +44,7 @@ from . import environment DEPENDENCIES = { - ("replication", '0.1.7'), + ("replication", '0.1.8'), } diff --git a/multi_user/bl_types/bl_camera.py b/multi_user/bl_types/bl_camera.py index e65b85a..22f58ae 100644 --- a/multi_user/bl_types/bl_camera.py +++ b/multi_user/bl_types/bl_camera.py @@ -48,12 +48,15 @@ class BlCamera(BlDatablock): background_images = data.get('background_images') + target.background_images.clear() + if background_images: - target.background_images.clear() for img_name, img_data in background_images.items(): - target_img = target.background_images.new() - target_img.image = bpy.data.images[img_name] - loader.load(target_img, img_data) + img_id = img_data.get('image') + if img_id: + target_img = target.background_images.new() + target_img.image = bpy.data.images[img_id] + loader.load(target_img, img_data) def _dump_implementation(self, data, instance=None): assert(instance) diff --git a/multi_user/bl_types/bl_object.py b/multi_user/bl_types/bl_object.py index 021fb35..4d0bc79 100644 --- a/multi_user/bl_types/bl_object.py +++ b/multi_user/bl_types/bl_object.py @@ -24,7 +24,6 @@ from replication.exception import ContextError from .bl_datablock import BlDatablock, get_datablock_from_uuid from .dump_anything import Dumper, Loader -from replication.exception import ReparentException def load_pose(target_bone, data): @@ -120,9 +119,7 @@ class BlObject(BlDatablock): data_uuid = data.get("data_uuid") data_id = data.get("data") - if target.type != data['type']: - raise ReparentException() - elif target.data and (target.data.name != data_id): + if target.data and (target.data.name != data_id): target.data = get_datablock_from_uuid(data_uuid, find_data_from_name(data_id), ignore=['images']) # vertex groups @@ -191,10 +188,10 @@ class BlObject(BlDatablock): target_bone.bone_group = target.pose.bone_group[bone_data['bone_group_index']] # TODO: find another way... - if target.type == 'EMPTY': + if target.empty_display_type == "IMAGE": img_uuid = data.get('data_uuid') if target.data is None and img_uuid: - target.data = get_datablock_from_uuid(img_uuid, None)#bpy.data.images.get(img_key, None) + target.data = get_datablock_from_uuid(img_uuid, None) def _dump_implementation(self, data, instance=None): assert(instance) diff --git a/multi_user/delayable.py b/multi_user/delayable.py index df75973..70ecfe6 100644 --- a/multi_user/delayable.py +++ b/multi_user/delayable.py @@ -36,8 +36,7 @@ from replication.constants import (FETCHED, STATE_ACTIVE, STATE_SYNCING, STATE_LOBBY, - STATE_SRV_SYNC, - REPARENT) + STATE_SRV_SYNC) from replication.interface import session from replication.exception import NonAuthorizedOperationError @@ -122,15 +121,6 @@ class ApplyTimer(Timer): session.apply(node) except Exception as e: logging.error(f"Fail to apply {node_ref.uuid}: {e}") - elif node_ref.state == REPARENT: - # Reload the node - node_ref.remove_instance() - node_ref.resolve() - session.apply(node) - for parent in session._graph.find_parents(node): - logging.info(f"Applying parent {parent}") - session.apply(parent, force=True) - node_ref.state = UP class DynamicRightSelectTimer(Timer):