mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-09 09:21:46 +00:00
DRY transform-modal draw gate + polyline helper
Two small refactors: - apply_transform_modal_draw_gate(group, context) replaces the three-line _is_transform_modal_active + _hide_all_non_modal_gizmos pair that BillboardingGizmoGroupMixin, BaseParametricGizmoGroup and BaseSchematicGizmoGroup all repeat in draw_prepare. - decorator.py renames _stroke_lines_alpha to a public-scope draw_polyline_segments and drops the no-longer-private companion docstring reference; the function is now usable by sibling decorators that draw polyline overlays. Plus a few one-liner tweaks in tool/model.py and opening.py following the helper rename. Generated with the assistance of an AI coding tool.
This commit is contained in:
@@ -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:
|
||||
|
||||
@@ -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 = (
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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 "[]")
|
||||
|
||||
Reference in New Issue
Block a user