From 931dc61d5329d3e399a2fed52d515f3f7aa1cc8e Mon Sep 17 00:00:00 2001 From: Swann Martinez Date: Fri, 19 Apr 2019 15:46:54 +0200 Subject: [PATCH] feat(rcf): uuid test --- client.py | 43 +++++++++++++++++++++++++++++++++-- draw.py | 9 +++++++- helpers.py | 63 +++++++++++++++++++++++++++++++--------------------- operators.py | 56 ++++++++++++++++++++++++++++++++-------------- 4 files changed, 126 insertions(+), 45 deletions(-) diff --git a/client.py b/client.py index d76966c..e52ac3a 100644 --- a/client.py +++ b/client.py @@ -187,10 +187,10 @@ class RCFClientAgent(object): if value == 'None': value = helpers.dump(key) - + if value: rcfmsg = message.RCFMessage( - key=key, id=self.id, mtype="", body=value) + key=key, id=self.id,uuid=value['uuid'], mtype="", body=value) rcfmsg.store(self.property_map) rcfmsg.send(self.publisher) @@ -345,3 +345,42 @@ def serialization_agent(ctx, pipe): if agent.pipe in items: agent.control_message() + + +class SyncAgent(object): + ctx = None + pipe = None + + def __init__(self, ctx, pipe): + self.ctx = ctx + self.pipe = pipe + logger.info("serialisation service launched") + + def control_message(self): + msg = self.pipe.recv_multipart() + command = msg.pop(0) + + pass + +def sync_agent(ctx, pipe): + agent = SyncAgent(ctx, pipe) + + global stop + while True: + if stop: + break + + poller = zmq.Poller() + poller.register(agent.pipe, zmq.POLLIN) + + try: + items = dict(poller.poll(1)) + except: + raise + break + + if agent.pipe in items: + agent.control_message() + + # Synchronisation + \ No newline at end of file diff --git a/draw.py b/draw.py index 5ae9e9a..3af4f1c 100644 --- a/draw.py +++ b/draw.py @@ -137,7 +137,14 @@ class HUD(object): self.d3d_items["{}/{}".format(client[0], select_ob)] = (shader, batch, color) else: - self.d3d_items.clear() + key_to_remove = [] + for k in self.d3d_items.keys(): + if "{}/".format(client[0]) in k: + key_to_remove.append(k) + + for k in key_to_remove: + del self.d3d_items[k] + def draw_clients(self): clients = self.client.get("Client") diff --git a/helpers.py b/helpers.py index aef6c0e..161dc13 100644 --- a/helpers.py +++ b/helpers.py @@ -1,10 +1,13 @@ import bpy import mathutils from .libs import dump_anything +from uuid import uuid4 +import logging CORRESPONDANCE = {'Collection': 'collections', 'Mesh': 'meshes', 'Object': 'objects', 'Material': 'materials', 'Texture': 'textures', 'Scene': 'scenes', 'Light': 'lights', 'Camera': 'cameras', 'Action': 'actions', 'Armature': 'armatures', 'Grease Pencil': 'grease_pencils'} +logger = logging.getLogger(__name__) # UTILITY FUNCTIONS def refresh_window(): @@ -27,6 +30,10 @@ def load(key, value): target = resolve_bpy_path(key) target_type = key.split('/')[0] + try: + target.uuid = value['uuid'] + except: + pass if target_type == 'Object': load_object(target=target, data=value, create=True) @@ -92,35 +99,38 @@ def load_client(client=None, data=None): def load_mesh(target=None, data=None, create=False): import bmesh - # TODO: handle error - mesh_buffer = bmesh.new() + if not target or not target.is_editmode: + # TODO: handle error + mesh_buffer = bmesh.new() - for i in data["vertices"]: - mesh_buffer.verts.new(data["vertices"][i]["co"]) + for i in data["vertices"]: + mesh_buffer.verts.new(data["vertices"][i]["co"]) - mesh_buffer.verts.ensure_lookup_table() + mesh_buffer.verts.ensure_lookup_table() - for i in data["edges"]: - verts = mesh_buffer.verts - v1 = data["edges"][i]["vertices"][0] - v2 = data["edges"][i]["vertices"][1] - mesh_buffer.edges.new([verts[v1], verts[v2]]) + for i in data["edges"]: + verts = mesh_buffer.verts + v1 = data["edges"][i]["vertices"][0] + v2 = data["edges"][i]["vertices"][1] + mesh_buffer.edges.new([verts[v1], verts[v2]]) - for p in data["polygons"]: - verts = [] - for v in data["polygons"][p]["vertices"]: - verts.append(mesh_buffer.verts[v]) + for p in data["polygons"]: + verts = [] + for v in data["polygons"][p]["vertices"]: + verts.append(mesh_buffer.verts[v]) - if len(verts) > 0: - mesh_buffer.faces.new(verts) + if len(verts) > 0: + mesh_buffer.faces.new(verts) - if target is None and create: - target = bpy.data.meshes.new(data["name"]) + if target is None and create: + target = bpy.data.meshes.new(data["name"]) - mesh_buffer.to_mesh(target) + mesh_buffer.to_mesh(target) - # Load other meshes metadata - dump_anything.load(target, data) + # Load other meshes metadata + dump_anything.load(target, data) + else: + logger.info("Mesh can't be loaded") def load_object(target=None, data=None, create=False): @@ -320,18 +330,21 @@ def dump(key): target_type = key.split('/')[0] data = None + + target.uuid = str(uuid4) + if target_type == 'Material': - data = dump_datablock_attibute(target, ['name', 'node_tree'], 7) + data = dump_datablock_attibute(target, ['name', 'node_tree','uuid'], 7) elif target_type == 'Grease Pencil': data = dump_datablock_attibute( - target, ['name', 'layers', 'materials'], 9) + target, ['name', 'layers', 'materials','uuid'], 9) elif target_type == 'Camera': data = dump_datablock(target, 1) elif target_type == 'Light': data = dump_datablock(target, 1) elif target_type == 'Mesh': data = dump_datablock_attibute( - target, ['name', 'polygons', 'edges', 'vertices'], 6) + target, ['name', 'polygons', 'edges', 'vertices','uuid'], 6) elif target_type == 'Object': data = dump_datablock(target, 1) elif target_type == 'Collection': @@ -379,7 +392,7 @@ def init_client(key=None): C = bpy.context Net = C.scene.session_settings - + client_dict['uuid'] = str(uuid4()) client_dict['location'] = [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]] client_dict['color'] = [Net.client_color.r, Net.client_color.g, Net.client_color.b, 1] diff --git a/operators.py b/operators.py index ca442ab..d5ac8c5 100644 --- a/operators.py +++ b/operators.py @@ -15,6 +15,7 @@ import gpu import mathutils from bpy_extras import view3d_utils from gpu_extras.batch import batch_for_shader +from uuid import uuid4 from . import client, ui, draw, helpers from .libs import umsgpack @@ -86,21 +87,28 @@ def update_selected_object(context): username = bpy.context.scene.session_settings.username client_key = "Client/{}".format(username) - client_data = client_instance.get(client_key) + client_data = client_instance.get(client_key) + selected_objects = helpers.get_selected_objects(context.scene) - # Active object bounding box + if len(selected_objects) > 0: + for obj in context.selected_objects: if obj.name not in client_data[0][1]['active_objects']: client_data[0][1]['active_objects'] = selected_objects client_instance.set(client_key,client_data[0][1]) break + elif client_data[0][1]['active_objects']: client_data[0][1]['active_objects'] = [] client_instance.set(client_key,client_data[0][1]) - + + + # for update in local_updates: + + # client_instance.get('') # if session.active_object is not context.selected_objects[0] or session.active_object.is_evaluated: # session.active_object = context.selected_objects[0] # key = "net/objects/{}".format(client_instance.id.decode()) @@ -131,6 +139,7 @@ def init_datablocks(): for datatype in SUPPORTED_TYPES: for item in getattr(bpy.data, helpers.CORRESPONDANCE[datatype]): + item.uuid = str(uuid4()) key = "{}/{}".format(datatype, item.name) print(key) client_instance.set(key) @@ -461,24 +470,36 @@ def depsgraph_update(scene): if client_instance and client_instance.agent.is_alive(): updates = bpy.context.depsgraph.updates - + username = bpy.context.scene.session_settings.username update_selected_object(bpy.context) - if is_dirty(updates): - for update in ordered(updates): - if update[2] == "Master Collection": - pass - elif update[1] in SUPPORTED_TYPES: - client_instance.set("{}/{}".format(update[1], update[2])) - - # if hasattr(bpy.context, 'selected_objects'): selected_objects = helpers.get_selected_objects(scene) if len(selected_objects) > 0: - for updated_data in updates: - if updated_data.id.name in selected_objects: - if updated_data.is_updated_transform or updated_data.is_updated_geometry: - client_instance.set( - "{}/{}".format(updated_data.id.bl_rna.name, updated_data.id.name)) + for update in updates: + update_key = "{}/{}".format(update.id.bl_rna.name, update.id.name) + remote_update = client_instance.get(update_key) + + if remote_update and remote_update[0][1]["uuid"] == update.id.uuid: + print("{} sending update".format(username)) + client_instance.set( + "{}/{}".format(update.id.bl_rna.name, update.id.name)) + else: + print("{} applying update".format(username)) + # if is_dirty(updates): + # for update in ordered(updates): + # if update[2] == "Master Collection": + # pass + # elif update[1] in SUPPORTED_TYPES: + # client_instance.set("{}/{}".format(update[1], update[2])) + + # if hasattr(bpy.context, 'selected_objects'): + # selected_objects = helpers.get_selected_objects(scene) + # if len(selected_objects) > 0: + # for updated_data in updates: + # if updated_data.id.name in selected_objects: + # if updated_data.is_updated_transform or updated_data.is_updated_geometry: + # client_instance.set( + # "{}/{}".format(updated_data.id.bl_rna.name, updated_data.id.name)) def register(): @@ -486,6 +507,7 @@ def register(): for cls in classes: register_class(cls) bpy.types.ID.is_dirty = bpy.props.BoolProperty(default=False) + bpy.types.ID.uuid = bpy.props.StringProperty(default="None") bpy.types.Scene.session_settings = bpy.props.PointerProperty( type=session_settings) bpy.app.handlers.depsgraph_update_post.append(depsgraph_update)