diff --git a/multi_user/preferences.py b/multi_user/preferences.py index b1d993c..de4fba2 100644 --- a/multi_user/preferences.py +++ b/multi_user/preferences.py @@ -273,6 +273,13 @@ class SessionPrefs(bpy.types.AddonPreferences): step=1, subtype='PERCENTAGE', ) + presence_mode_distance: bpy.props.FloatProperty( + name="Distance mode visibilty", + description="Adjust the distance visibilty of user's mode", + min=0.1, + max=1000, + default=100, + ) conf_session_identity_expanded: bpy.props.BoolProperty( name="Identity", description="Identity", @@ -446,10 +453,11 @@ class SessionPrefs(bpy.types.AddonPreferences): col = box.column(align=True) col.prop(self, "presence_hud_scale", expand=True) - col.prop(self, "presence_hud_hpos", expand=True) col.prop(self, "presence_hud_vpos", expand=True) + col.prop(self, "presence_mode_distance", expand=True) + if self.category == 'UPDATE': from . import addon_updater_ops addon_updater_ops.update_settings_ui(self, context) @@ -538,6 +546,11 @@ class SessionProps(bpy.types.PropertyGroup): description='Enable user overlay ', default=True, ) + presence_show_mode: bpy.props.BoolProperty( + name="Show users current mode", + description='Enable user mode overlay ', + default=False, + ) presence_show_far_user: bpy.props.BoolProperty( name="Show users on different scenes", description="Show user on different scenes", diff --git a/multi_user/presence.py b/multi_user/presence.py index 23921dc..0a5957f 100644 --- a/multi_user/presence.py +++ b/multi_user/presence.py @@ -251,6 +251,13 @@ class Widget(object): """ return True + def configure_bgl(self): + bgl.glLineWidth(2.) + bgl.glEnable(bgl.GL_DEPTH_TEST) + bgl.glEnable(bgl.GL_BLEND) + bgl.glEnable(bgl.GL_LINE_SMOOTH) + + def draw(self): """How to draw the widget """ @@ -304,11 +311,6 @@ class UserFrustumWidget(Widget): {"pos": positions}, indices=self.indices) - bgl.glLineWidth(2.) - bgl.glEnable(bgl.GL_DEPTH_TEST) - bgl.glEnable(bgl.GL_BLEND) - bgl.glEnable(bgl.GL_LINE_SMOOTH) - shader.bind() shader.uniform_float("color", self.data.get('color')) batch.draw(shader) @@ -342,7 +344,7 @@ class UserSelectionWidget(Widget): self.settings.presence_show_selected and \ self.settings.enable_presence - def draw(self): + def draw(self): user_selection = self.data.get('selected_objects') for select_obj in user_selection: obj = find_from_attr("uuid", select_obj, bpy.data.objects) @@ -406,6 +408,62 @@ class UserNameWidget(Widget): blf.color(0, color[0], color[1], color[2], color[3]) blf.draw(0, self.username) +class UserModeWidget(Widget): + draw_type = 'POST_PIXEL' + + def __init__( + self, + username): + self.username = username + self.settings = bpy.context.window_manager.session + self.preferences = get_preferences() + + @property + def data(self): + user = session.online_users.get(self.username) + if user: + return user.get('metadata') + else: + return None + + def poll(self): + if self.data is None: + return False + + scene_current = self.data.get('scene_current') + mode_current = self.data.get('mode_current') + user_selection = self.data.get('selected_objects') + + return (scene_current == bpy.context.scene.name or + mode_current == bpy.context.mode or + self.settings.presence_show_far_user) and \ + user_selection and \ + self.settings.presence_show_mode and \ + self.settings.enable_presence + + def draw(self): + user_selection = self.data.get('selected_objects') + area, region, rv3d = view3d_find() + viewport_coord = project_to_viewport(region, rv3d, (0, 0)) + + obj = find_from_attr("uuid", user_selection[0], bpy.data.objects) + if not obj: + return + mode_current = self.data.get('mode_current') + color = self.data.get('color') + origin_coord = project_to_screen(obj.location) + + distance_viewport_object = math.sqrt((viewport_coord[0]-obj.location[0])**2+(viewport_coord[1]-obj.location[1])**2+(viewport_coord[2]-obj.location[2])**2) + + if distance_viewport_object > self.preferences.presence_mode_distance : + return + + if origin_coord : + blf.position(0, origin_coord[0]+8, origin_coord[1]-15, 0) + blf.size(0, 16, 72) + blf.color(0, color[0], color[1], color[2], color[3]) + blf.draw(0, mode_current) + class SessionStatusWidget(Widget): draw_type = 'POST_PIXEL' @@ -488,6 +546,7 @@ class DrawFactory(object): try: for widget in self.widgets.values(): if widget.draw_type == 'POST_VIEW' and widget.poll(): + widget.configure_bgl() widget.draw() except Exception as e: logging.error( @@ -497,6 +556,7 @@ class DrawFactory(object): try: for widget in self.widgets.values(): if widget.draw_type == 'POST_PIXEL' and widget.poll(): + widget.configure_bgl() widget.draw() except Exception as e: logging.error( @@ -509,6 +569,7 @@ this.renderer = DrawFactory() def register(): this.renderer.register_handlers() + this.renderer.add_widget("session_status", SessionStatusWidget()) diff --git a/multi_user/timers.py b/multi_user/timers.py index a4502e4..62d8a6d 100644 --- a/multi_user/timers.py +++ b/multi_user/timers.py @@ -27,7 +27,7 @@ from replication.interface import session from replication import porcelain from . import operators, utils -from .presence import (UserFrustumWidget, UserNameWidget, UserSelectionWidget, +from .presence import (UserFrustumWidget, UserNameWidget, UserModeWidget, UserSelectionWidget, generate_user_camera, get_view_matrix, refresh_3d_view, refresh_sidebar_view, renderer) @@ -309,7 +309,8 @@ class ClientUpdate(Timer): settings.client_color.b, 1), 'frame_current': bpy.context.scene.frame_current, - 'scene_current': scene_current + 'scene_current': scene_current, + 'mode_current': bpy.context.mode } porcelain.update_user_metadata(session.repository, metadata) @@ -323,6 +324,9 @@ class ClientUpdate(Timer): local_user_metadata['view_matrix'] = get_view_matrix( ) porcelain.update_user_metadata(session.repository, local_user_metadata) + elif bpy.context.mode != local_user_metadata['mode_current']: + local_user_metadata['mode_current'] = bpy.context.mode + porcelain.update_user_metadata(session.repository, local_user_metadata) class SessionStatusUpdate(Timer): @@ -350,6 +354,7 @@ class SessionUserSync(Timer): renderer.remove_widget(f"{user.username}_cam") renderer.remove_widget(f"{user.username}_select") renderer.remove_widget(f"{user.username}_name") + renderer.remove_widget(f"{user.username}_mode") ui_users.remove(index) break @@ -365,6 +370,8 @@ class SessionUserSync(Timer): f"{user}_select", UserSelectionWidget(user)) renderer.add_widget( f"{user}_name", UserNameWidget(user)) + renderer.add_widget( + f"{user}_mode", UserModeWidget(user)) class MainThreadExecutor(Timer): diff --git a/multi_user/ui.py b/multi_user/ui.py index 1523f2d..50f809b 100644 --- a/multi_user/ui.py +++ b/multi_user/ui.py @@ -107,7 +107,7 @@ class SESSION_PT_settings(bpy.types.Panel): row = row.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=True) row.prop(settings.sync_flags, "sync_render_settings",text="",icon_only=True, icon='SCENE') row.prop(settings.sync_flags, "sync_during_editmode", text="",icon_only=True, icon='EDITMODE_HLT') - row.prop(settings.sync_flags, "sync_active_camera", text="",icon_only=True, icon='OBJECT_DATAMODE') + row.prop(settings.sync_flags, "sync_active_camera", text="",icon_only=True, icon='VIEW_CAMERA') row= layout.row() @@ -343,9 +343,10 @@ class SESSION_PT_user(bpy.types.Panel): box = row.box() split = box.split(factor=0.35) split.label(text="user") - split = split.split(factor=0.5) - split.label(text="location") + split = split.split(factor=0.3) + split.label(text="mode") split.label(text="frame") + split.label(text="location") split.label(text="ping") row = layout.row() @@ -383,6 +384,8 @@ class SESSION_UL_users(bpy.types.UIList): ping = '-' frame_current = '-' scene_current = '-' + mode_current = '-' + mode_icon = 'BLANK1' status_icon = 'BLANK1' if session: user = session.online_users.get(item.username) @@ -392,13 +395,45 @@ class SESSION_UL_users(bpy.types.UIList): if metadata and 'frame_current' in metadata: frame_current = str(metadata.get('frame_current','-')) scene_current = metadata.get('scene_current','-') + mode_current = metadata.get('mode_current','-') + if mode_current == "OBJECT" : + mode_icon = "OBJECT_DATAMODE" + elif mode_current == "EDIT_MESH" : + mode_icon = "EDITMODE_HLT" + elif mode_current == 'EDIT_CURVE': + mode_icon = "CURVE_DATA" + elif mode_current == 'EDIT_SURFACE': + mode_icon = "SURFACE_DATA" + elif mode_current == 'EDIT_TEXT': + mode_icon = "FILE_FONT" + elif mode_current == 'EDIT_ARMATURE': + mode_icon = "ARMATURE_DATA" + elif mode_current == 'EDIT_METABALL': + mode_icon = "META_BALL" + elif mode_current == 'EDIT_LATTICE': + mode_icon = "LATTICE_DATA" + elif mode_current == 'POSE': + mode_icon = "POSE_HLT" + elif mode_current == 'SCULPT': + mode_icon = "SCULPTMODE_HLT" + elif mode_current == 'PAINT_WEIGHT': + mode_icon = "WPAINT_HLT" + elif mode_current == 'PAINT_VERTEX': + mode_icon = "VPAINT_HLT" + elif mode_current == 'PAINT_TEXTURE': + mode_icon = "TPAINT_HLT" + elif mode_current == 'PARTICLE': + mode_icon = "PARTICLES" + elif mode_current == 'PAINT_GPENCIL' or mode_current =='EDIT_GPENCIL' or mode_current =='SCULPT_GPENCIL' or mode_current =='WEIGHT_GPENCIL' or mode_current =='VERTEX_GPENCIL': + mode_icon = "GREASEPENCIL" if user['admin']: status_icon = 'FAKE_USER_ON' split = layout.split(factor=0.35) split.label(text=item.username, icon=status_icon) - split = split.split(factor=0.5) - split.label(text=scene_current) + split = split.split(factor=0.3) + split.label(icon=mode_icon) split.label(text=frame_current) + split.label(text=scene_current) split.label(text=ping) @@ -425,20 +460,29 @@ class SESSION_PT_presence(bpy.types.Panel): settings = context.window_manager.session pref = get_preferences() layout.active = settings.enable_presence + + row = layout.row() + row = row.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=True) + row.prop(settings, "presence_show_selected",text="",icon_only=True, icon='CUBE') + row.prop(settings, "presence_show_user", text="",icon_only=True, icon='CAMERA_DATA') + row.prop(settings, "presence_show_mode", text="",icon_only=True, icon='OBJECT_DATAMODE') + row.prop(settings, "presence_show_far_user", text="",icon_only=True, icon='SCENE_DATA') + col = layout.column() + if settings.presence_show_mode : + row = col.column() + row.prop(pref, "presence_mode_distance", expand=True) + col.prop(settings, "presence_show_session_status") - row = col.column() - row.active = settings.presence_show_session_status - row.prop(pref, "presence_hud_scale", expand=True) - row = col.column(align=True) - row.active = settings.presence_show_session_status - row.prop(pref, "presence_hud_hpos", expand=True) - row.prop(pref, "presence_hud_vpos", expand=True) - col.prop(settings, "presence_show_selected") - col.prop(settings, "presence_show_user") - row = layout.column() - row.active = settings.presence_show_user - row.prop(settings, "presence_show_far_user") + if settings.presence_show_session_status : + row = col.column() + row.active = settings.presence_show_session_status + row.prop(pref, "presence_hud_scale", expand=True) + row = col.column(align=True) + row.active = settings.presence_show_session_status + row.prop(pref, "presence_hud_hpos", expand=True) + row.prop(pref, "presence_hud_vpos", expand=True) + def draw_property(context, parent, property_uuid, level=0): settings = get_preferences() @@ -585,23 +629,32 @@ class VIEW3D_PT_overlay_session(bpy.types.Panel): def draw(self, context): layout = self.layout - view = context.space_data - overlay = view.overlay - display_all = overlay.show_overlays - - col = layout.column() - - row = col.row(align=True) settings = context.window_manager.session + pref = get_preferences() layout.active = settings.enable_presence + + row = layout.row() + row = row.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=True) + row.prop(settings, "presence_show_selected",text="",icon_only=True, icon='CUBE') + row.prop(settings, "presence_show_user", text="",icon_only=True, icon='CAMERA_DATA') + row.prop(settings, "presence_show_mode", text="",icon_only=True, icon='OBJECT_DATAMODE') + row.prop(settings, "presence_show_far_user", text="",icon_only=True, icon='SCENE_DATA') + col = layout.column() + if settings.presence_show_mode : + row = col.column() + row.prop(pref, "presence_mode_distance", expand=True) + col.prop(settings, "presence_show_session_status") - col.prop(settings, "presence_show_selected") - col.prop(settings, "presence_show_user") - - row = layout.column() - row.active = settings.presence_show_user - row.prop(settings, "presence_show_far_user") + if settings.presence_show_session_status : + row = col.column() + row.active = settings.presence_show_session_status + row.prop(pref, "presence_hud_scale", expand=True) + row = col.column(align=True) + row.active = settings.presence_show_session_status + row.prop(pref, "presence_hud_hpos", expand=True) + row.prop(pref, "presence_hud_vpos", expand=True) + classes = ( SESSION_UL_users,