diff --git a/src/bonsai/bonsai/bim/module/drawing/gizmos.py b/src/bonsai/bonsai/bim/module/drawing/gizmos.py index 3f794d5804..3c03e9db49 100644 --- a/src/bonsai/bonsai/bim/module/drawing/gizmos.py +++ b/src/bonsai/bonsai/bim/module/drawing/gizmos.py @@ -204,6 +204,20 @@ def _hide_all_non_modal_gizmos(group) -> None: gz.hide = True +def apply_transform_modal_draw_gate(group, context) -> bool: + """Combined gate for ``draw_prepare`` overrides: hide non-modal gizmos and + return ``True`` when a Blender transform modal is dragging matrix_world. + + Returns ``False`` when no transform modal is active so callers can fall + through to their normal positioning logic. ``True`` means the caller must + early-return without touching matrix_basis — the hidden gizmos will be + re-shown on the next idle frame once the modal exits.""" + if not _is_transform_modal_active(context): + return False + _hide_all_non_modal_gizmos(group) + return True + + class GizmoColor(Enum): """Color identifiers for dimension gizmos. @@ -5075,8 +5089,7 @@ class BillboardingGizmoGroupMixin: self.position_gizmos(context) def draw_prepare(self, context: bpy.types.Context) -> None: - if _is_transform_modal_active(context): - _hide_all_non_modal_gizmos(self) + if apply_transform_modal_draw_gate(self, context): return self.position_gizmos(context) @@ -6498,8 +6511,7 @@ class BaseParametricGizmoGroup: """ if not self.is_setup_complete(): return - if _is_transform_modal_active(context): - _hide_all_non_modal_gizmos(self) + if apply_transform_modal_draw_gate(self, context): return obj = context.active_object if not obj: @@ -6707,8 +6719,7 @@ class BaseSchematicGizmoGroup(BaseParametricGizmoGroup): def draw_prepare(self, context: bpy.types.Context) -> None: if not self.is_setup_complete(): return - if _is_transform_modal_active(context): - _hide_all_non_modal_gizmos(self) + if apply_transform_modal_draw_gate(self, context): return obj = context.active_object if not obj: diff --git a/src/bonsai/bonsai/bim/module/model/decorator.py b/src/bonsai/bonsai/bim/module/model/decorator.py index c2f4e8f139..2d4b72c7a0 100644 --- a/src/bonsai/bonsai/bim/module/model/decorator.py +++ b/src/bonsai/bonsai/bim/module/model/decorator.py @@ -2032,42 +2032,6 @@ class BoundingBoxDecorator: co2.y -= y_overlap / 2 + min_spacing -def _stroke_lines_alpha( - context: bpy.types.Context, - segments: list[tuple[tuple[float, float, float], tuple[float, float, float]]], - color_rgb: tuple[float, float, float], - line_width: float, - line_alpha: float, -) -> None: - """Render ``segments`` (a list of ``(start, end)`` tuples) as one - anti-aliased LINES batch in world space. Early-returns when - ``context.region`` is unavailable (e.g. when called from a - ``_RestrictContext``).""" - if not segments: - return - verts: list[tuple[float, float, float]] = [] - indices: list[tuple[int, int]] = [] - for start, end in segments: - base = len(verts) - verts.append(tuple(start)) - verts.append(tuple(end)) - indices.append((base, base + 1)) - if not tool.Blender.validate_shader_batch_data(verts, indices): - return - region = getattr(context, "region", None) - if region is None: - return - shader = gpu.shader.from_builtin("POLYLINE_UNIFORM_COLOR") - shader.bind() - shader.uniform_float("viewportSize", (region.width, region.height)) - shader.uniform_float("lineWidth", line_width) - shader.uniform_float("color", (*color_rgb, line_alpha)) - batch = batch_for_shader(shader, "LINES", {"pos": verts}, indices=indices) - gpu.state.blend_set("ALPHA") - batch.draw(shader) - gpu.state.blend_set("NONE") - - def _fill_quads_alpha( context: bpy.types.Context, quads: list[ @@ -2082,8 +2046,7 @@ def _fill_quads_alpha( alpha: float, ) -> None: """Render ``quads`` (each a 4-tuple of world-space corner verts in CCW - order) as one TRIS batch with two triangles per quad. Companion to - ``_stroke_lines_alpha`` for filled previews.""" + order) as one TRIS batch with two triangles per quad.""" if not quads: return verts: list[tuple[float, float, float]] = [] @@ -2179,12 +2142,12 @@ class MEPSegmentExtendPreviewDecorator(tool.Blender.ViewportDecorator): return start_world, end_world = line color = tuple(prefs.decorator_color_selected[:3]) - _stroke_lines_alpha( + draw_polyline_segments( context, [(tuple(start_world), tuple(end_world))], color, - self.LINE_WIDTH, self.LINE_ALPHA, + self.LINE_WIDTH, ) @staticmethod @@ -2250,9 +2213,11 @@ class BendPreviewDecorator(tool.Blender.ViewportDecorator): # Late import: decorator.py loads at addon enable but mep.py imports # this module for the extend preview, so a module-level import would # cycle. - from bonsai.bim.module.model.mep import compute_bend_preview_polylines + from bonsai.bim.module.model.mep import cached_compute_bend_preview_polylines - preview = compute_bend_preview_polylines(start_obj, end_obj, props.start_length, props.end_length, props.radius) + preview = cached_compute_bend_preview_polylines( + start_obj, end_obj, props.start_length, props.end_length, props.radius + ) prefs = tool.Blender.get_addon_preferences() if not preview["valid"]: @@ -2260,7 +2225,7 @@ class BendPreviewDecorator(tool.Blender.ViewportDecorator): axes = preview.get("invalid_axes") or [] if axes: segments = [(tuple(a), tuple(b)) for a, b in axes] - _stroke_lines_alpha(context, segments, warning_color, self.LINE_WIDTH_ARC, self.LINE_ALPHA) + draw_polyline_segments(context, segments, warning_color, self.LINE_ALPHA, self.LINE_WIDTH_ARC) return leg_color = tuple(prefs.decorations_colour[:3]) @@ -2268,18 +2233,18 @@ class BendPreviewDecorator(tool.Blender.ViewportDecorator): leg_a_far, leg_a_end = preview["leg_a"] leg_b_far, leg_b_end = preview["leg_b"] - _stroke_lines_alpha( + draw_polyline_segments( context, [(tuple(leg_a_far), tuple(leg_a_end)), (tuple(leg_b_far), tuple(leg_b_end))], leg_color, - self.LINE_WIDTH_LEG, self.LINE_ALPHA, + self.LINE_WIDTH_LEG, ) arc = preview["arc"] if len(arc) >= 2: arc_segments = [(tuple(arc[i]), tuple(arc[i + 1])) for i in range(len(arc) - 1)] - _stroke_lines_alpha(context, arc_segments, arc_color, self.LINE_WIDTH_ARC, self.LINE_ALPHA) + draw_polyline_segments(context, arc_segments, arc_color, self.LINE_ALPHA, self.LINE_WIDTH_ARC) class WallFilletPreviewDecorator(tool.Blender.ViewportDecorator): @@ -2343,15 +2308,15 @@ class WallFilletPreviewDecorator(tool.Blender.ViewportDecorator): (tuple(far_a), tuple(tangent_a)), (tuple(far_b), tuple(tangent_b)), ] - _stroke_lines_alpha(context, legs, warning_color, self.LINE_WIDTH_LEG, self.LINE_ALPHA) + draw_polyline_segments(context, legs, warning_color, self.LINE_ALPHA, self.LINE_WIDTH_LEG) arc = geom.get("arc") or [] if len(arc) >= 2: arc_segments = [(tuple(arc[i]), tuple(arc[i + 1])) for i in range(len(arc) - 1)] - _stroke_lines_alpha(context, arc_segments, warning_color, self.LINE_WIDTH_ARC, self.LINE_ALPHA) + draw_polyline_segments(context, arc_segments, warning_color, self.LINE_ALPHA, self.LINE_WIDTH_ARC) elif geom.get("invalid_axes"): axes = geom["invalid_axes"] segments = [(tuple(a), tuple(b)) for a, b in axes] - _stroke_lines_alpha(context, segments, warning_color, self.LINE_WIDTH_ARC, self.LINE_ALPHA) + draw_polyline_segments(context, segments, warning_color, self.LINE_ALPHA, self.LINE_WIDTH_ARC) return leg_color = tuple(prefs.decorations_colour[:3]) @@ -2368,12 +2333,12 @@ class WallFilletPreviewDecorator(tool.Blender.ViewportDecorator): (tuple(far_a), tuple(geom["tangent_a"])), (tuple(far_b), tuple(geom["tangent_b"])), ] - _stroke_lines_alpha(context, legs, leg_color, self.LINE_WIDTH_LEG, self.LINE_ALPHA) + draw_polyline_segments(context, legs, leg_color, self.LINE_ALPHA, self.LINE_WIDTH_LEG) arc = geom["arc"] if len(arc) >= 2: arc_segments = [(tuple(arc[i]), tuple(arc[i + 1])) for i in range(len(arc) - 1)] - _stroke_lines_alpha(context, arc_segments, arc_color, self.LINE_WIDTH_ARC, self.LINE_ALPHA) + draw_polyline_segments(context, arc_segments, arc_color, self.LINE_ALPHA, self.LINE_WIDTH_ARC) # Dim construction lines from arc_center to each tangent point so # the radius reads as concrete during drag. @@ -2383,7 +2348,9 @@ class WallFilletPreviewDecorator(tool.Blender.ViewportDecorator): (tuple(arc_center), tuple(geom["tangent_a"])), (tuple(arc_center), tuple(geom["tangent_b"])), ] - _stroke_lines_alpha(context, construction, arc_color, self.LINE_WIDTH_CONSTRUCTION, self.CONSTRUCTION_ALPHA) + draw_polyline_segments( + context, construction, arc_color, self.CONSTRUCTION_ALPHA, self.LINE_WIDTH_CONSTRUCTION + ) @staticmethod def _far_endpoint(reference_line, intersection): @@ -2505,7 +2472,7 @@ class DoorSwingReadonlyDecorator(tool.Blender.ViewportDecorator): pts = [world_main @ p for p in _DOOR_SWING_ARC_UNIT_POINTS] for i in range(len(pts) - 1): segments.append((tuple(pts[i]), tuple(pts[i + 1]))) - _stroke_lines_alpha(context, segments, main_color, self.LINE_WIDTH, self.LINE_ALPHA) + draw_polyline_segments(context, segments, main_color, self.LINE_ALPHA, self.LINE_WIDTH) _BBOX_EDGES = ( diff --git a/src/bonsai/bonsai/bim/module/model/opening.py b/src/bonsai/bonsai/bim/module/model/opening.py index c457b3144f..4a16bee5af 100644 --- a/src/bonsai/bonsai/bim/module/model/opening.py +++ b/src/bonsai/bonsai/bim/module/model/opening.py @@ -219,6 +219,10 @@ _DASH_WIDTH_METERS: float = 0.10 # overlay biases the depth buffer at outline pixels. _DASH_LINE_WIDTH: float = 1.5 _SOLID_LINE_WIDTH: float = 2.5 +# Per-iteration default line width used by every non-occlusion draw call in +# this decorator's ``__call__``. Restored after each occlusion pair so the +# next draw isn't silently inheriting the wider solid-pass override. +_DEFAULT_LINE_WIDTH: float = 2.0 def _get_cached_batch_or_none(cache_key: tuple[int, str]) -> "gpu.types.GPUBatch | None": @@ -1250,7 +1254,7 @@ class DecorationsHandler: # Restore the per-iteration default set at the top of __call__ so # subsequent draws (the HalfSpaceSolid arrow, future call-sites) are # not silently affected by the front-pass width override. - self.line_shader.uniform_float("lineWidth", 2.0) + self.line_shader.uniform_float("lineWidth", _DEFAULT_LINE_WIDTH) gpu.state.depth_test_set(original_depth_test) def __call__(self, context): @@ -1286,7 +1290,7 @@ class DecorationsHandler: self.line_shader.bind() # required to be able to change uniforms of the shader # POLYLINE_UNIFORM_COLOR specific uniforms self.line_shader.uniform_float("viewportSize", (context.region.width, context.region.height)) - self.line_shader.uniform_float("lineWidth", 2.0) + self.line_shader.uniform_float("lineWidth", _DEFAULT_LINE_WIDTH) # general shader self.shader = gpu.shader.from_builtin("UNIFORM_COLOR") diff --git a/src/bonsai/bonsai/tool/model.py b/src/bonsai/bonsai/tool/model.py index d59f653036..2ea1678479 100644 --- a/src/bonsai/bonsai/tool/model.py +++ b/src/bonsai/bonsai/tool/model.py @@ -1588,8 +1588,7 @@ class Model(bonsai.core.tool.Model): element = tool.Ifc.get_entity(object) if not element: return - psets = ifcopenshell.util.element.get_psets(element) - pset_data = psets.get(pset_name, None) + pset_data = ifcopenshell.util.element.get_pset(element, pset_name) if not pset_data: return pset_data["data_dict"] = json.loads(pset_data.get("Data", "[]") or "[]")