From 2eec228c3e18bb23db8175c4e036a7fbad9b0ae7 Mon Sep 17 00:00:00 2001 From: Swann Martinez Date: Tue, 14 Jan 2020 11:49:36 +0100 Subject: [PATCH] feat: undo/redo handler The solution for now is to resolve datablock references when undo appen. Related to #32. --- multi_user/bl_types/bl_datablock.py | 20 +++++++++++++------- multi_user/bl_types/bl_user.py | 3 +++ multi_user/operators.py | 20 +++++++++++++++++++- 3 files changed, 35 insertions(+), 8 deletions(-) diff --git a/multi_user/bl_types/bl_datablock.py b/multi_user/bl_types/bl_datablock.py index f1d7ae8..2fdd203 100644 --- a/multi_user/bl_types/bl_datablock.py +++ b/multi_user/bl_types/bl_datablock.py @@ -107,14 +107,20 @@ class BlDatablock(ReplicatedDatablock): return [self.pointer.library] def resolve(self): - self.pointer = utils.find_from_attr('uuid', self.uuid, bpy.data.scenes) + datablock_ref = None + datablock_root = getattr(bpy.data, self.bl_id) + datablock_ref = utils.find_from_attr('uuid', self.uuid, datablock_root) - if not self.pointer: - self.pointer = getattr(bpy.data,self.bl_id).get(self.data['name']) - print(self.data['name']) - if self.pointer: - setattr(self.pointer, 'uuid', self.uuid) - + # 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']) + + if datablock_ref: + setattr(datablock_ref, 'uuid', self.uuid) + + self.pointer = datablock_ref def dump(self, pointer=None): data = {} diff --git a/multi_user/bl_types/bl_user.py b/multi_user/bl_types/bl_user.py index 6e2aaa5..8f0a2b2 100644 --- a/multi_user/bl_types/bl_user.py +++ b/multi_user/bl_types/bl_user.py @@ -41,6 +41,9 @@ class BlUser(BlDatablock): def update(self): self.pointer.is_dirty = True + + def resolve(self): + pass def is_valid(self): return True diff --git a/multi_user/operators.py b/multi_user/operators.py index 8464e1e..3608156 100644 --- a/multi_user/operators.py +++ b/multi_user/operators.py @@ -41,7 +41,6 @@ class SessionStartOperator(bpy.types.Operator): bl_idname = "session.start" bl_label = "start" bl_description = "connect to a net server" - bl_options = {"REGISTER"} host: bpy.props.BoolProperty(default=False) @@ -382,6 +381,7 @@ classes = ( SessionCommit, ApplyArmatureOperator, ) + @persistent def load_pre_handler(dummy): global client @@ -389,6 +389,19 @@ def load_pre_handler(dummy): if client and client.state in [STATE_ACTIVE, STATE_SYNCING]: 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 in [STATE_ACTIVE]: + for node_key in client.list(): + client.get(node_key).resolve() def register(): from bpy.utils import register_class @@ -397,6 +410,9 @@ 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) + def unregister(): global client @@ -410,6 +426,8 @@ 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) if __name__ == "__main__": register()