diff --git a/multi_user/bl_types/bl_datablock.py b/multi_user/bl_types/bl_datablock.py index 88485a9..25ffd41 100644 --- a/multi_user/bl_types/bl_datablock.py +++ b/multi_user/bl_types/bl_datablock.py @@ -100,6 +100,8 @@ class BlDatablock(ReplicatedDatablock): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) instance = kwargs.get('instance', None) + + self.preferences = utils.get_preferences() # TODO: use is_library_indirect self.is_library = (instance and hasattr(instance, 'library') and diff --git a/multi_user/bl_types/bl_mesh.py b/multi_user/bl_types/bl_mesh.py index 9bfb356..1e3c04c 100644 --- a/multi_user/bl_types/bl_mesh.py +++ b/multi_user/bl_types/bl_mesh.py @@ -27,7 +27,6 @@ from replication.constants import DIFF_BINARY from replication.exception import ContextError from .bl_datablock import BlDatablock - VERTICE = ['co'] EDGE = [ @@ -113,8 +112,8 @@ class BlMesh(BlDatablock): def _dump_implementation(self, data, instance=None): assert(instance) - - if instance.is_editmode: + + if instance.is_editmode and not self.preferences.enable_editmode_updates: raise ContextError("Mesh is in edit mode") mesh = instance diff --git a/multi_user/bl_types/bl_object.py b/multi_user/bl_types/bl_object.py index 77bed03..9c5a233 100644 --- a/multi_user/bl_types/bl_object.py +++ b/multi_user/bl_types/bl_object.py @@ -16,14 +16,15 @@ # ##### END GPL LICENSE BLOCK ##### -import bpy -import mathutils import logging -from .dump_anything import Loader, Dumper -from .bl_datablock import BlDatablock +import bpy +import mathutils from replication.exception import ContextError +from .bl_datablock import BlDatablock +from .dump_anything import Dumper, Loader + def load_pose(target_bone, data): target_bone.rotation_mode = data['rotation_mode'] @@ -31,6 +32,13 @@ def load_pose(target_bone, data): loader.load(target_bone, data) +def _is_editmode(object: bpy.types.Object) -> bool: + child_data = getattr(object, 'data', None) + return (child_data and + hasattr(child_data, 'is_editmode') and + child_data.is_editmode) + + class BlObject(BlDatablock): bl_id = "objects" bl_class = bpy.types.Object @@ -88,13 +96,13 @@ class BlObject(BlDatablock): def _load_implementation(self, data, target): loader = Loader() - + # vertex groups if 'vertex_groups' in data: target.vertex_groups.clear() for vg in data['vertex_groups']: vertex_group = target.vertex_groups.new(name=vg['name']) - point_attr = 'vertices' if 'vertices' in vg else 'points' + point_attr = 'vertices' if 'vertices' in vg else 'points' for vert in vg[point_attr]: vertex_group.add( [vert['index']], vert['weight'], 'REPLACE') @@ -147,7 +155,6 @@ class BlObject(BlDatablock): if 'constraints' in bone_data.keys(): loader.load(target_bone, bone_data['constraints']) - load_pose(target_bone, bone_data) if 'bone_index' in bone_data.keys(): @@ -162,11 +169,12 @@ class BlObject(BlDatablock): def _dump_implementation(self, data, instance=None): assert(instance) - - child_data = getattr(instance, 'data', None) - - if child_data and hasattr(child_data, 'is_editmode') and child_data.is_editmode: - raise ContextError("Object is in edit-mode.") + + if _is_editmode(instance): + if self.preferences.enable_editmode_updates: + instance.update_from_editmode() + else: + raise ContextError("Object is in edit-mode.") dumper = Dumper() dumper.depth = 1 @@ -211,7 +219,6 @@ class BlObject(BlDatablock): data["modifiers"][modifier.name] = dumper.dump(modifier) # CONSTRAINTS - # OBJECT if hasattr(instance, 'constraints'): dumper.depth = 3 data["constraints"] = dumper.dump(instance.constraints) @@ -264,7 +271,8 @@ class BlObject(BlDatablock): # VERTEx GROUP if len(instance.vertex_groups) > 0: - points_attr = 'vertices' if isinstance(instance.data, bpy.types.Mesh) else 'points' + points_attr = 'vertices' if isinstance( + instance.data, bpy.types.Mesh) else 'points' vg_data = [] for vg in instance.vertex_groups: vg_idx = vg.index @@ -319,7 +327,7 @@ class BlObject(BlDatablock): def _resolve_deps_implementation(self): deps = [] - + # Avoid Empty case if self.instance.data: deps.append(self.instance.data) @@ -334,4 +342,3 @@ class BlObject(BlDatablock): deps.append(self.instance.instance_collection) return deps - diff --git a/multi_user/operators.py b/multi_user/operators.py index 8245f41..428fe94 100644 --- a/multi_user/operators.py +++ b/multi_user/operators.py @@ -631,7 +631,7 @@ def depsgraph_evaluation(scene): context = bpy.context blender_depsgraph = bpy.context.view_layer.depsgraph dependency_updates = [u for u in blender_depsgraph.updates] - session_infos = utils.get_preferences() + settings = utils.get_preferences() # NOTE: maybe we don't need to check each update but only the first @@ -647,7 +647,8 @@ def depsgraph_evaluation(scene): # - if its to someone else, ignore the update (go deeper ?) if node and node.owner in [client.id, RP_COMMON] and node.state == UP: # Avoid slow geometry update - if 'EDIT' in context.mode: + if 'EDIT' in context.mode and \ + not settings.enable_editmode_updates: break client.stash(node.uuid) diff --git a/multi_user/preferences.py b/multi_user/preferences.py index ead8082..0c9aa68 100644 --- a/multi_user/preferences.py +++ b/multi_user/preferences.py @@ -137,11 +137,17 @@ class SessionPrefs(bpy.types.AddonPreferences): ('DEPSGRAPH', "Depsgraph", "Experimental: Use the blender dependency graph to trigger updates"), ], ) + # Replication update settings depsgraph_update_rate: bpy.props.IntProperty( name='depsgraph update rate', description='Dependency graph uppdate rate (milliseconds)', default=100 ) + enable_editmode_updates: bpy.props.BoolProperty( + name="Edit mode updates", + description="Enable objects update in edit mode (! Impact performances !)", + default=False + ) # for UI category: bpy.props.EnumProperty( name="Category", diff --git a/multi_user/ui.py b/multi_user/ui.py index 39b9427..94fcca2 100644 --- a/multi_user/ui.py +++ b/multi_user/ui.py @@ -299,15 +299,19 @@ class SESSION_PT_advanced_settings(bpy.types.Panel): replication_section = layout.row().box() replication_section.label(text="Replication ", icon='TRIA_DOWN') replication_section_row = replication_section.row() - if runtime_settings.session_mode == 'HOST': - replication_section_row.prop(settings.sync_flags, "sync_render_settings") - + replication_section_row.label(text="Sync flags:") + replication_section_row = replication_section.row() + replication_section_row.prop(settings.sync_flags, "sync_render_settings") + replication_section_row = replication_section.row() + # replication_section_row.label(text=":", icon='EDITMODE_HLT') + replication_section_row.prop(settings, "enable_editmode_updates") replication_section_row = replication_section.row() replication_section_row.label(text="Update method:") - replication_section_row.prop(settings, "update_method", text="") + replication_section_row = replication_section.row() + replication_section_row.prop(settings, "update_method", expand=True) replication_section_row = replication_section.row() replication_timers = replication_section_row.box() - replication_timers.label(text="Per data type timers", icon='TIME') + replication_timers.label(text="Replication timers", icon='TIME') if settings.update_method == "DEFAULT": replication_timers = replication_timers.row() # Replication frequencies