diff --git a/multi_user/presence.py b/multi_user/presence.py index 0a5957f..8112de1 100644 --- a/multi_user/presence.py +++ b/multi_user/presence.py @@ -94,18 +94,21 @@ def project_to_viewport(region: bpy.types.Region, rv3d: bpy.types.RegionView3D, return [target.x, target.y, target.z] -def bbox_from_obj(obj: bpy.types.Object) -> list: +def bbox_from_obj(obj: bpy.types.Object, index: int = 1) -> list: """ Generate a bounding box for a given object by using its world matrix :param obj: target object :type obj: bpy.types.Object + :param index: indice offset + :type index: int :return: list of 8 points [(x,y,z),...], list of 12 link between these points [(1,2),...] """ radius = 1.0 # Radius of the bounding box + index = 8*index vertex_indices = ( - (0, 1), (0, 2), (1, 3), (2, 3), - (4, 5), (4, 6), (5, 7), (6, 7), - (0, 4), (1, 5), (2, 6), (3, 7)) + (0+index, 1+index), (0+index, 2+index), (1+index, 3+index), (2+index, 3+index), + (4+index, 5+index), (4+index, 6+index), (5+index, 7+index), (6+index, 7+index), + (0+index, 4+index), (1+index, 5+index), (2+index, 6+index), (3+index, 7+index)) if obj.type == 'EMPTY': radius = obj.empty_display_size @@ -117,9 +120,12 @@ def bbox_from_obj(obj: bpy.types.Object) -> list: radius = obj.data.display_size elif hasattr(obj, 'bound_box'): vertex_indices = ( - (0, 1), (1, 2), (2, 3), (0, 3), - (4, 5), (5, 6), (6, 7), (4, 7), - (0, 4), (1, 5), (2, 6), (3, 7)) + (0+index, 1+index), (1+index, 2+index), + (2+index, 3+index), (0+index, 3+index), + (4+index, 5+index), (5+index, 6+index), + (6+index, 7+index), (4+index, 7+index), + (0+index, 4+index), (1+index, 5+index), + (2+index, 6+index), (3+index, 7+index)) vertex_pos = get_bb_coords_from_obj(obj) return vertex_pos, vertex_indices @@ -136,26 +142,21 @@ def bbox_from_obj(obj: bpy.types.Object) -> list: return vertex_pos, vertex_indices -def bbox_from_instance_collection(ic: bpy.types.Object) -> list: +def bbox_from_instance_collection(ic: bpy.types.Object, index: int = 0) -> list: """ Generate a bounding box for a given instance collection by using its objects :param ic: target instance collection :type ic: bpy.types.Object - :param radius: bounding box radius - :type radius: float + :param index: indice offset + :type index: int :return: list of 8*objs points [(x,y,z),...], tuple of 12*objs link between these points [(1,2),...] """ vertex_pos = [] vertex_indices = () for obj_index, obj in enumerate(ic.instance_collection.objects): - vertex_pos_temp, vertex_indices_temp = bbox_from_obj(obj) + vertex_pos_temp, vertex_indices_temp = bbox_from_obj(obj, index=index+obj_index) vertex_pos += vertex_pos_temp - vertex_indices_list_temp = list(list(indice) for indice in vertex_indices_temp) - for indice in vertex_indices_list_temp: - indice[0] += 8*obj_index - indice[1] += 8*obj_index - vertex_indices_temp = tuple(tuple(indice) for indice in vertex_indices_list_temp) vertex_indices += vertex_indices_temp bbox_corners = [ic.matrix_world @ mathutils.Vector(vertex) for vertex in vertex_pos] @@ -223,7 +224,7 @@ def get_bb_coords_from_obj(object: bpy.types.Object, instance: bpy.types.Object bbox_corners = [base @ mathutils.Vector( corner) for corner in object.bound_box] - + return [(point.x, point.y, point.z) for point in bbox_corners] @@ -322,6 +323,8 @@ class UserSelectionWidget(Widget): username): self.username = username self.settings = bpy.context.window_manager.session + self.current_selection_ids = [] + self.current_selected_objects = [] @property def data(self): @@ -331,6 +334,15 @@ class UserSelectionWidget(Widget): else: return None + @property + def selected_objects(self): + user_selection = self.data.get('selected_objects') + if user_selection != self.current_selection_ids: + self.current_selection_ids = user_selection + self.current_selected_objects = [find_from_attr("uuid", uid, bpy.data.objects) for uid in user_selection] + + return self.current_selected_objects + def poll(self): if self.data is None: return False @@ -344,27 +356,31 @@ class UserSelectionWidget(Widget): self.settings.presence_show_selected and \ self.settings.enable_presence - 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) - if not obj: - return - if obj.instance_collection: - vertex_pos, vertex_indices = bbox_from_instance_collection(obj) + def draw(self): + vertex_pos = [] + vertex_ind = [] + collection_offset = 0 + for obj_index, obj in enumerate(self.selected_objects): + obj_index+=collection_offset + logging.info(collection_offset) + if hasattr(obj, 'instance_collection') and obj.instance_collection: + bbox_pos, bbox_ind = bbox_from_instance_collection(obj, index=obj_index) + collection_offset+=len(obj.instance_collection.objects) else : - vertex_pos, vertex_indices = bbox_from_obj(obj) + bbox_pos, bbox_ind = bbox_from_obj(obj, index=obj_index) + vertex_pos += bbox_pos + vertex_ind += bbox_ind - shader = gpu.shader.from_builtin('3D_UNIFORM_COLOR') - batch = batch_for_shader( - shader, - 'LINES', - {"pos": vertex_pos}, - indices=vertex_indices) + shader = gpu.shader.from_builtin('3D_UNIFORM_COLOR') + batch = batch_for_shader( + shader, + 'LINES', + {"pos": vertex_pos}, + indices=vertex_ind) - shader.bind() - shader.uniform_float("color", self.data.get('color')) - batch.draw(shader) + shader.bind() + shader.uniform_float("color", self.data.get('color')) + batch.draw(shader) class UserNameWidget(Widget): draw_type = 'POST_PIXEL'