From 226ea10de88f2fea28f73a9a4d2a581db9afb669 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bruno=20Perdig=C3=A3o?= Date: Mon, 25 Nov 2024 17:46:48 -0300 Subject: [PATCH] Add aggregate mode decorator. --- .../bonsai/bim/module/aggregate/decorator.py | 119 +++++++++++++++--- .../bonsai/bim/module/aggregate/operator.py | 5 +- 2 files changed, 102 insertions(+), 22 deletions(-) diff --git a/src/bonsai/bonsai/bim/module/aggregate/decorator.py b/src/bonsai/bonsai/bim/module/aggregate/decorator.py index 05687fc49d..557060317e 100644 --- a/src/bonsai/bonsai/bim/module/aggregate/decorator.py +++ b/src/bonsai/bonsai/bim/module/aggregate/decorator.py @@ -16,15 +16,22 @@ # You should have received a copy of the GNU General Public License # along with Bonsai. If not, see . +import blf import bpy import gpu import ifcopenshell import bonsai.tool as tool from bpy.types import SpaceView3D +from bpy_extras import view3d_utils from gpu_extras.batch import batch_for_shader from mathutils import Vector +def transparent_color(color, alpha=0.1): + color = [i for i in color] + color[3] = alpha + return color + class AggregateDecorator: is_installed = False handlers = [] @@ -47,23 +54,19 @@ class AggregateDecorator: pass cls.is_installed = False - def transparent_color(self, color, alpha=0.1): - color = [i for i in color] - color[3] = alpha - return color def dotted_line_shader(self): vert_out = gpu.types.GPUStageInterfaceInfo("my_interface") - vert_out.smooth('FLOAT', "v_ArcLength") + vert_out.smooth("FLOAT", "v_ArcLength") shader_info = gpu.types.GPUShaderCreateInfo() - shader_info.push_constant('MAT4', "u_ViewProjectionMatrix") - shader_info.push_constant('FLOAT', "u_Scale") - shader_info.vertex_in(0, 'VEC3', "position") - shader_info.vertex_in(1, 'FLOAT', "arcLength") + shader_info.push_constant("MAT4", "u_ViewProjectionMatrix") + shader_info.push_constant("FLOAT", "u_Scale") + shader_info.vertex_in(0, "VEC3", "position") + shader_info.vertex_in(1, "FLOAT", "arcLength") shader_info.vertex_out(vert_out) - shader_info.fragment_out(0, 'VEC4', "FragColor") - shader_info.push_constant('VEC4', "color") + shader_info.fragment_out(0, "VEC4", "FragColor") + shader_info.push_constant("VEC4", "color") shader_info.vertex_source( "void main()" @@ -74,11 +77,7 @@ class AggregateDecorator: ) shader_info.fragment_source( - "void main()" - "{" - " if (step(sin(v_ArcLength * u_Scale), 0.4) == 1) discard;" - " FragColor = color;" - "}" + "void main()" "{" " if (step(sin(v_ArcLength * u_Scale), 0.4) == 1) discard;" " FragColor = color;" "}" ) shader = gpu.shader.create_from_info(shader_info) @@ -86,7 +85,6 @@ class AggregateDecorator: del shader_info return shader - def draw_custom_batch(self, coords, color): shader = self.dotted_line_shader() @@ -95,7 +93,8 @@ class AggregateDecorator: arc_lengths.append(arc_lengths[-1] + (a - b).length) batch = batch_for_shader( - shader, 'LINE_STRIP', + shader, + "LINE_STRIP", {"position": coords, "arcLength": arc_lengths}, ) @@ -105,7 +104,6 @@ class AggregateDecorator: shader.uniform_float("u_Scale", 25) batch.draw(shader) - def draw_batch(self, shader_type, content_pos, color, indices=None): shader = self.line_shader if shader_type == "LINES" else self.shader batch = batch_for_shader(shader, shader_type, {"pos": content_pos}, indices=indices) @@ -156,10 +154,91 @@ class AggregateDecorator: self.draw_batch("LINES", line_y, color, [(0, 1)]) line_z = (location - Vector((0.0, 0.0, size)), location + Vector((0.0, 0.0, size))) self.draw_batch("LINES", line_z, color, [(0, 1)]) - if context.scene.BIMAggregateProperties.in_edit_mode: + if context.scene.BIMAggregateProperties.in_aggregate_mode: return parts = ifcopenshell.util.element.get_parts(tool.Ifc.get_entity(aggregate)) for part in parts: part_obj = tool.Ifc.get_object(part) line = (part_obj.matrix_world.translation, location) self.draw_custom_batch(line, decorator_color_unselected) + +class AggregateModeDecorator: + is_installed = False + handlers = [] + + @classmethod + def install(cls, context): + if cls.is_installed: + cls.uninstall() + handler = cls() + cls.handlers.append( + SpaceView3D.draw_handler_add(handler.draw_aggregate_name, (context,), "WINDOW", "POST_PIXEL") + ) + cls.handlers.append( + SpaceView3D.draw_handler_add(handler.draw_aggregate_empty, (context,), "WINDOW", "POST_VIEW") + ) + cls.is_installed = True + + @classmethod + def uninstall(cls): + for handler in cls.handlers: + try: + SpaceView3D.draw_handler_remove(handler, "WINDOW") + except ValueError: + pass + cls.is_installed = False + + def draw_batch(self, shader_type, content_pos, color, indices=None): + shader = self.line_shader if shader_type == "LINES" else self.shader + batch = batch_for_shader(shader, shader_type, {"pos": content_pos}, indices=indices) + shader.uniform_float("color", color) + batch.draw(shader) + + + def draw_aggregate_name(self, context): + region = context.region + rv3d = region.data + props = context.scene.BIMAggregateProperties + aggregate_obj = props.editing_aggregate + self.addon_prefs = tool.Blender.get_addon_preferences() + self.font_id = 0 + font_size = tool.Blender.scale_font_size(12) + blf.size(self.font_id, font_size) + blf.enable(self.font_id, blf.SHADOW) + blf.shadow(self.font_id, 6, 0, 0, 0, 1) + color = self.addon_prefs.decorator_color_special + if aggregate_obj in context.selected_objects: + color = self.addon_prefs.decorator_color_selected + blf.color(self.font_id, *color) + text = aggregate_obj.name + text_coords = view3d_utils.location_3d_to_region_2d(region, rv3d, aggregate_obj.location) + text_length = blf.dimensions(self.font_id, text) + text_coords[0] -= (text_length[0] / 2) + text_coords[1] -= 20 + blf.position(self.font_id, text_coords[0], text_coords[1], 0) + + self.shader = gpu.shader.from_builtin("UNIFORM_COLOR") + + blf.draw(self.font_id, text) + + def draw_aggregate_empty(self, context): + props = context.scene.BIMAggregateProperties + aggregate_obj = props.editing_aggregate + self.addon_prefs = tool.Blender.get_addon_preferences() + self.line_shader = gpu.shader.from_builtin("POLYLINE_UNIFORM_COLOR") + self.line_shader.bind() + self.line_shader.uniform_float("viewportSize", (context.region.width, context.region.height)) + self.line_shader.uniform_float("lineWidth", 1.0) + color = self.addon_prefs.decorator_color_special + if aggregate_obj in context.selected_objects: + self.line_shader.uniform_float("lineWidth", 2.0) + color = self.addon_prefs.decorator_color_selected + size = aggregate_obj.empty_display_size + location = aggregate_obj.location + line_x = (location - Vector((size, 0.0, 0.0)), location + Vector((size, 0.0, 0.0))) + self.draw_batch("LINES", line_x, color, [(0, 1)]) + line_y = (location - Vector((0.0, size, 0.0)), location + Vector((0.0, size, 0.0))) + self.draw_batch("LINES", line_y, color, [(0, 1)]) + line_z = (location - Vector((0.0, 0.0, size)), location + Vector((0.0, 0.0, size))) + self.draw_batch("LINES", line_z, color, [(0, 1)]) + diff --git a/src/bonsai/bonsai/bim/module/aggregate/operator.py b/src/bonsai/bonsai/bim/module/aggregate/operator.py index 0817c5a67d..ec595f11d5 100644 --- a/src/bonsai/bonsai/bim/module/aggregate/operator.py +++ b/src/bonsai/bonsai/bim/module/aggregate/operator.py @@ -24,6 +24,7 @@ import bonsai.tool as tool import bonsai.core.aggregate as core import bonsai.core.spatial from bonsai.bim.ifc import IfcStore +from bonsai.bim.module.aggregate.decorator import AggregateModeDecorator class BIM_OT_aggregate_assign_object(bpy.types.Operator, tool.Ifc.Operator): @@ -388,10 +389,10 @@ class BIM_OT_toggle_mode_set_aggregate(bpy.types.Operator, tool.Ifc.Operator): def _execute(self, context): props = context.scene.BIMAggregateProperties if props.in_aggregate_mode: - #AggregateModeDecorator.uninstall() + AggregateModeDecorator.uninstall() BIM_OT_disable_mode_set_aggregate._execute(self, context) else: - #AggregateModeDecorator.install(context) + AggregateModeDecorator.install(context) BIM_OT_mode_set_aggregate._execute(self, context)