From e253ccd52d562a222c2724edc121d73c7964815b Mon Sep 17 00:00:00 2001 From: Swann Martinez Date: Wed, 22 Jan 2020 14:33:34 +0100 Subject: [PATCH] refactor: use client metadata --- multi_user/__init__.py | 13 +++---- multi_user/bl_types/__init__.py | 1 - multi_user/bl_types/bl_user.py | 64 ------------------------------- multi_user/delayable.py | 68 ++++++++++++++++++++------------- multi_user/libs/replication | 2 +- multi_user/operators.py | 18 ++------- multi_user/presence.py | 47 +++++------------------ multi_user/ui.py | 7 ++-- multi_user/utils.py | 4 +- 9 files changed, 66 insertions(+), 158 deletions(-) delete mode 100644 multi_user/bl_types/bl_user.py diff --git a/multi_user/__init__.py b/multi_user/__init__.py index 09071c1..41abf8e 100644 --- a/multi_user/__init__.py +++ b/multi_user/__init__.py @@ -57,22 +57,19 @@ def generate_supported_types(): def client_list_callback(scene, context): from . import operators - from .bl_types.bl_user import BlUser items = [(RP_COMMON, RP_COMMON, "")] username = bpy.context.window_manager.session.username cli = operators.client if cli: - client_keys = cli.list(filter=BlUser) - for k in client_keys: - name = cli.get(uuid=k).data["name"] - - name_desc = name - if name == username: + client_ids = cli.online_users.keys() + for id in client_ids: + name_desc = id + if id == username: name_desc += " (self)" - items.append((name, name_desc, "")) + items.append((id, name_desc, "")) return items diff --git a/multi_user/bl_types/__init__.py b/multi_user/bl_types/__init__.py index 7f0991a..c3e9605 100644 --- a/multi_user/bl_types/__init__.py +++ b/multi_user/bl_types/__init__.py @@ -1,5 +1,4 @@ __all__ = [ - 'bl_user', 'bl_object', 'bl_mesh', 'bl_camera', diff --git a/multi_user/bl_types/bl_user.py b/multi_user/bl_types/bl_user.py deleted file mode 100644 index 1d0611d..0000000 --- a/multi_user/bl_types/bl_user.py +++ /dev/null @@ -1,64 +0,0 @@ -import bpy -import mathutils -import jsondiff - -from .. import utils -from .. import presence -from .bl_datablock import BlDatablock -from ..libs.replication.replication.constants import UP - - -class BlUser(BlDatablock): - bl_id = "users" - bl_class = presence.User - bl_delay_refresh = .1 - bl_delay_apply = .1 - bl_automatic_push = True - bl_icon = 'CON_ARMATURE' - - def construct(self, data): - user = bpy.data.window_managers['WinMan'].online_users.add() - user.name = data['name'] - user.username = data['name'] - user.current_frame = data['current_frame'] - - def apply(self): - if self.pointer is None: - self.set_pointer() - - self.load(self.data,self.pointer) - - for obj in bpy.data.objects: - if obj.hide_select and obj.uuid not in self.data['selected_objects']: - obj.hide_select = False - elif not obj.hide_select and obj.uuid in self.data['selected_objects']: - obj.hide_select = True - - presence.refresh_3d_view() - - self.state = UP - - def load(self, data, target): - target.current_frame = data['current_frame'] - - def dump(self, pointer=None): - data = utils.dump_anything.dump(pointer) - data['location'] = pointer.location - data['color'] = pointer.color - data['selected_objects'] = pointer.selected_objects - data['view_matrix'] = pointer.view_matrix - data['current_frame'] = bpy.context.scene.frame_current - - return data - - def update(self): - self.pointer.is_dirty = True - - def resolve(self): - self.pointer = bpy.data.window_managers['WinMan'].online_users.get(self.data['name']) - - def is_valid(self): - return True - - - diff --git a/multi_user/delayable.py b/multi_user/delayable.py index f50c981..cd790ad 100644 --- a/multi_user/delayable.py +++ b/multi_user/delayable.py @@ -3,10 +3,10 @@ import logging import bpy from . import operators, presence, utils -from .bl_types.bl_user import BlUser from .libs.replication.replication.constants import FETCHED, RP_COMMON logger = logging.getLogger(__name__) +logger.setLevel(logging.INFO) class Delayable(): @@ -83,7 +83,6 @@ class DynamicRightSelectTimer(Timer): super().__init__(timout) self._last_selection = [] self._user = None - self._user_metadata = None self._right_strategy = RP_COMMON def execute(self): @@ -94,7 +93,6 @@ class DynamicRightSelectTimer(Timer): # Find user if self._user is None: self._user = session.online_users.get(settings.username) - self._user_metadata = self._user.get('metadata') if self._right_strategy is None: self._right_strategy = session.get_config()[ @@ -140,21 +138,25 @@ class DynamicRightSelectTimer(Timer): return self._last_selection = current_selection - self._user_metadata['selected_objects'] = current_selection - session.update_user_metadata(self._user_metadata) + user_metadata = { + 'selected_objects': current_selection + } + + session.update_user_metadata(user_metadata) logger.info("Update selection") + # Fix deselection until right managment refactoring (with Roles concepts) if len(current_selection) == 0 and self._right_strategy == RP_COMMON: owned_keys = session.list( filter_owner=settings.username) for key in owned_keys: node = session.get(uuid=key) - if not isinstance(node, BlUser): - session.change_owner( - key, - RP_COMMON, - recursive=recursive) + + session.change_owner( + key, + RP_COMMON, + recursive=recursive) for user, user_info in session.online_users.items(): if user != settings.username: @@ -190,8 +192,9 @@ class Draw(Delayable): class DrawClient(Draw): def execute(self): - session = operators.client - if session and presence.renderer: + session = getattr(operators, 'client') + renderer = getattr(presence, 'renderer') + if session and renderer: settings = bpy.context.window_manager.session users = session.online_users @@ -199,10 +202,10 @@ class DrawClient(Draw): metadata = user.get('metadata') if settings.presence_show_selected and 'selected_objects' in metadata.keys(): - presence.renderer.draw_client_selection( + renderer.draw_client_selection( user['id'], metadata['color'], metadata['selected_objects']) if settings.presence_show_user and 'view_corners' in metadata: - presence.renderer.draw_client_camera( + renderer.draw_client_camera( user['id'], metadata['view_corners'], metadata['color']) @@ -213,23 +216,31 @@ class ClientUpdate(Timer): def execute(self): settings = bpy.context.window_manager.session session_info = bpy.context.window_manager.session - session = operators.client + session = getattr(operators, 'client') if session: local_user = operators.client.online_users.get( session_info.username) + if not local_user: + return - metadata = { - 'view_corners': presence.get_view_corners(), - 'view_matrix': presence.get_view_matrix(), - 'color': (settings.client_color.r, - settings.client_color.g, - settings.client_color.b, - 1), - } + local_user_metadata = local_user.get('metadata') + current_view_corners = presence.get_view_corners() - session.update_user_metadata(metadata) - - logger.info("{}".format(local_user)) + if not local_user_metadata: + logger.info("init user metadata") + metadata = { + 'view_corners': current_view_corners, + 'view_matrix': presence.get_view_matrix(), + 'color': (settings.client_color.r, + settings.client_color.g, + settings.client_color.b, + 1), + } + session.update_user_metadata(metadata) + elif current_view_corners != local_user_metadata['view_corners']: + logger.info('update user metadata') + local_user_metadata['view_corners'] = current_view_corners + session.update_user_metadata(local_user_metadata) # sync online users session_users = operators.client.online_users @@ -240,7 +251,7 @@ class ClientUpdate(Timer): ui_users.remove(index) bpy.context.window_manager.session.presence_show_user = False bpy.context.window_manager.session.presence_show_user = True - presence.refresh_3d_view() + break for user in session_users: @@ -248,3 +259,6 @@ class ClientUpdate(Timer): new_key = ui_users.add() new_key.name = user new_key.username = user + + # TODO: event drivent 3d view refresh + presence.refresh_3d_view() diff --git a/multi_user/libs/replication b/multi_user/libs/replication index 20c122a..d8537c3 160000 --- a/multi_user/libs/replication +++ b/multi_user/libs/replication @@ -1 +1 @@ -Subproject commit 20c122a522dea6c1d4991b30be548c3e1e81857c +Subproject commit d8537c31c06cca5e6033740c3b50864760b60bfb diff --git a/multi_user/operators.py b/multi_user/operators.py index 9f1ae5e..4fb4ea9 100644 --- a/multi_user/operators.py +++ b/multi_user/operators.py @@ -36,7 +36,6 @@ modal_executor_queue = None # OPERATORS - class SessionStartOperator(bpy.types.Operator): bl_idname = "session.start" bl_label = "start" @@ -54,16 +53,15 @@ class SessionStartOperator(bpy.types.Operator): users = bpy.data.window_managers['WinMan'].online_users # TODO: Sync server clients - users.clear() - # save config settings.save(context) bpy_factory = ReplicatedDataFactory() supported_bl_types = [] ui_context = context.copy() + # init the factory with supported types for type in bl_types.types_to_register(): type_module = getattr(bl_types, type) @@ -87,6 +85,8 @@ class SessionStartOperator(bpy.types.Operator): target_type=type_module_class)) client = Session(factory=bpy_factory) + + if self.host: # Scene setup @@ -118,18 +118,6 @@ class SessionStartOperator(bpy.types.Operator): "A session is already hosted on this address") return {"CANCELLED"} - # Init user settings - usr = presence.User( - username=settings.username, - color=(settings.client_color.r, - settings.client_color.g, - settings.client_color.b, - 1), - ) - - settings.user_uuid = client.add(usr, owner=settings.username) - client.commit(settings.user_uuid) - if self.host: for scene in bpy.data.scenes: scene_uuid = client.add(scene) diff --git a/multi_user/presence.py b/multi_user/presence.py index e6145c6..bc4272c 100644 --- a/multi_user/presence.py +++ b/multi_user/presence.py @@ -122,33 +122,6 @@ def get_view_matrix(): return matrix_dumper.dump(rv3d.view_matrix) -class User(): - def __init__(self, username=None, color=(0, 0, 0, 1)): - self.is_dirty = False - self.name = username - self.color = color - self.location = [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]] - self.selected_objects = [] - self.last_select_objects = [] - self.view_matrix = None - - def update_location(self): - current_coords = get_view_corners() - area, region, rv3d = view3d_find() - - if area and region and rv3d: - current_coords = list(get_view_corners()) - if current_coords and self.location != current_coords: - self.location = current_coords - - matrix_dumper = utils.dump_anything.Dumper() - current_vm = matrix_dumper.dump(rv3d.view_matrix) - if self.view_matrix != current_vm: - self.view_matrix = current_vm - - def update_selected_objects(self, context): - self.selected_objects = utils.get_selected_objects(context.scene) - def update_presence(self, context): global renderer @@ -226,14 +199,14 @@ class DrawFactory(object): self.d2d_items.clear() - def draw_client_selection(self, client_uuid, client_color, client_selection): - local_user = bpy.context.window_manager.session.user_uuid + def draw_client_selection(self, client_id, client_color, client_selection): + local_user = bpy.context.window_manager.session.username - if local_user != client_uuid: - self.flush_selection(client_uuid) + if local_user != client_id: + self.flush_selection(client_id) for select_ob in client_selection: - drawable_key = "{}_select_{}".format(client_uuid, select_ob) + drawable_key = "{}_select_{}".format(client_id, select_ob) ob = utils.find_from_attr("uuid", select_ob, bpy.data.objects) if not ob: @@ -282,11 +255,11 @@ class DrawFactory(object): self.d3d_items[key] = (shader, batch, color) - def draw_client_camera(self, client_uuid, client_location, client_color): + def draw_client_camera(self, client_id, client_location, client_color): if client_location: - local_user = bpy.context.window_manager.session.user_uuid + local_user = bpy.context.window_manager.session.username - if local_user != client_uuid: + if local_user != client_id: try: indices = ( (1, 3), (2, 1), (3, 0), @@ -301,8 +274,8 @@ class DrawFactory(object): batch = batch_for_shader( shader, 'LINES', {"pos": position}, indices=indices) - self.d3d_items[client_uuid] = (shader, batch, color) - self.d2d_items[client_uuid] = (position[1], client_uuid, color) + self.d3d_items[client_id] = (shader, batch, color) + self.d2d_items[client_id] = (position[1], client_id, color) except Exception as e: logger.error("Draw client exception {}".format(e)) diff --git a/multi_user/ui.py b/multi_user/ui.py index 3ab637c..d2f809f 100644 --- a/multi_user/ui.py +++ b/multi_user/ui.py @@ -1,7 +1,6 @@ import bpy from . import operators -from .bl_types.bl_user import BlUser from .libs.replication.replication.constants import (ADDED, ERROR, FETCHED, MODIFIED, RP_COMMON, UP) @@ -188,7 +187,7 @@ class SESSION_PT_user(bpy.types.Panel): # Create a simple row. row = layout.row() box = row.box() - split = box.split(factor=0.3) + split = box.split(factor=0.5) split.label(text="user") split.label(text="frame") split.label(text="ping") @@ -219,7 +218,7 @@ class SESSION_UL_users(bpy.types.UIList): ping = str(user_stat['latency']) break - split = layout.split(factor=0.3) + split = layout.split(factor=0.5) split.label(text=item.username) split.label(text=str(item.current_frame)) split.label(text=ping) @@ -256,7 +255,7 @@ def draw_property(context, parent, property_uuid, level=0): settings = context.window_manager.session item = operators.client.get(uuid=property_uuid) - if item.str_type == 'BlUser' or item.state == ERROR: + if item.state == ERROR: return area_msg = parent.row(align=True) diff --git a/multi_user/utils.py b/multi_user/utils.py index 2646597..8cd35fb 100644 --- a/multi_user/utils.py +++ b/multi_user/utils.py @@ -27,6 +27,7 @@ def has_driver(target): and target.animation_data and target.animation_data.drivers) + def find_from_attr(attr_name, attr_value, list): for item in list: if getattr(item, attr_name, None) == attr_value: @@ -56,7 +57,7 @@ def get_datablock_users(datablock): def random_string_digits(stringLength=6): """Generate a random string of letters and digits """ lettersAndDigits = string.ascii_letters + string.digits - return ''.join(random.choice(lettersAndDigits) for i in range(stringLength)) + return ''.join(random.choices(lettersAndDigits, k=stringLength)) def clean_scene(): @@ -151,6 +152,7 @@ def dump_datablock_attibutes(datablock=None, attributes=[], depth=1, dickt=None) return data + def resolve_from_id(id, optionnal_type=None): for category in dir(bpy.data): root = getattr(bpy.data, category)