mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-23 17:56:33 +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
|
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):
|
class GizmoColor(Enum):
|
||||||
"""Color identifiers for dimension gizmos.
|
"""Color identifiers for dimension gizmos.
|
||||||
|
|
||||||
@@ -5075,8 +5089,7 @@ class BillboardingGizmoGroupMixin:
|
|||||||
self.position_gizmos(context)
|
self.position_gizmos(context)
|
||||||
|
|
||||||
def draw_prepare(self, context: bpy.types.Context) -> None:
|
def draw_prepare(self, context: bpy.types.Context) -> None:
|
||||||
if _is_transform_modal_active(context):
|
if apply_transform_modal_draw_gate(self, context):
|
||||||
_hide_all_non_modal_gizmos(self)
|
|
||||||
return
|
return
|
||||||
self.position_gizmos(context)
|
self.position_gizmos(context)
|
||||||
|
|
||||||
@@ -6498,8 +6511,7 @@ class BaseParametricGizmoGroup:
|
|||||||
"""
|
"""
|
||||||
if not self.is_setup_complete():
|
if not self.is_setup_complete():
|
||||||
return
|
return
|
||||||
if _is_transform_modal_active(context):
|
if apply_transform_modal_draw_gate(self, context):
|
||||||
_hide_all_non_modal_gizmos(self)
|
|
||||||
return
|
return
|
||||||
obj = context.active_object
|
obj = context.active_object
|
||||||
if not obj:
|
if not obj:
|
||||||
@@ -6707,8 +6719,7 @@ class BaseSchematicGizmoGroup(BaseParametricGizmoGroup):
|
|||||||
def draw_prepare(self, context: bpy.types.Context) -> None:
|
def draw_prepare(self, context: bpy.types.Context) -> None:
|
||||||
if not self.is_setup_complete():
|
if not self.is_setup_complete():
|
||||||
return
|
return
|
||||||
if _is_transform_modal_active(context):
|
if apply_transform_modal_draw_gate(self, context):
|
||||||
_hide_all_non_modal_gizmos(self)
|
|
||||||
return
|
return
|
||||||
obj = context.active_object
|
obj = context.active_object
|
||||||
if not obj:
|
if not obj:
|
||||||
|
|||||||
@@ -2032,42 +2032,6 @@ class BoundingBoxDecorator:
|
|||||||
co2.y -= y_overlap / 2 + min_spacing
|
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(
|
def _fill_quads_alpha(
|
||||||
context: bpy.types.Context,
|
context: bpy.types.Context,
|
||||||
quads: list[
|
quads: list[
|
||||||
@@ -2082,8 +2046,7 @@ def _fill_quads_alpha(
|
|||||||
alpha: float,
|
alpha: float,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Render ``quads`` (each a 4-tuple of world-space corner verts in CCW
|
"""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
|
order) as one TRIS batch with two triangles per quad."""
|
||||||
``_stroke_lines_alpha`` for filled previews."""
|
|
||||||
if not quads:
|
if not quads:
|
||||||
return
|
return
|
||||||
verts: list[tuple[float, float, float]] = []
|
verts: list[tuple[float, float, float]] = []
|
||||||
@@ -2179,12 +2142,12 @@ class MEPSegmentExtendPreviewDecorator(tool.Blender.ViewportDecorator):
|
|||||||
return
|
return
|
||||||
start_world, end_world = line
|
start_world, end_world = line
|
||||||
color = tuple(prefs.decorator_color_selected[:3])
|
color = tuple(prefs.decorator_color_selected[:3])
|
||||||
_stroke_lines_alpha(
|
draw_polyline_segments(
|
||||||
context,
|
context,
|
||||||
[(tuple(start_world), tuple(end_world))],
|
[(tuple(start_world), tuple(end_world))],
|
||||||
color,
|
color,
|
||||||
self.LINE_WIDTH,
|
|
||||||
self.LINE_ALPHA,
|
self.LINE_ALPHA,
|
||||||
|
self.LINE_WIDTH,
|
||||||
)
|
)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@@ -2250,9 +2213,11 @@ class BendPreviewDecorator(tool.Blender.ViewportDecorator):
|
|||||||
# Late import: decorator.py loads at addon enable but mep.py imports
|
# Late import: decorator.py loads at addon enable but mep.py imports
|
||||||
# this module for the extend preview, so a module-level import would
|
# this module for the extend preview, so a module-level import would
|
||||||
# cycle.
|
# 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()
|
prefs = tool.Blender.get_addon_preferences()
|
||||||
|
|
||||||
if not preview["valid"]:
|
if not preview["valid"]:
|
||||||
@@ -2260,7 +2225,7 @@ class BendPreviewDecorator(tool.Blender.ViewportDecorator):
|
|||||||
axes = preview.get("invalid_axes") or []
|
axes = preview.get("invalid_axes") or []
|
||||||
if axes:
|
if axes:
|
||||||
segments = [(tuple(a), tuple(b)) for a, b in 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
|
return
|
||||||
|
|
||||||
leg_color = tuple(prefs.decorations_colour[:3])
|
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_a_far, leg_a_end = preview["leg_a"]
|
||||||
leg_b_far, leg_b_end = preview["leg_b"]
|
leg_b_far, leg_b_end = preview["leg_b"]
|
||||||
_stroke_lines_alpha(
|
draw_polyline_segments(
|
||||||
context,
|
context,
|
||||||
[(tuple(leg_a_far), tuple(leg_a_end)), (tuple(leg_b_far), tuple(leg_b_end))],
|
[(tuple(leg_a_far), tuple(leg_a_end)), (tuple(leg_b_far), tuple(leg_b_end))],
|
||||||
leg_color,
|
leg_color,
|
||||||
self.LINE_WIDTH_LEG,
|
|
||||||
self.LINE_ALPHA,
|
self.LINE_ALPHA,
|
||||||
|
self.LINE_WIDTH_LEG,
|
||||||
)
|
)
|
||||||
|
|
||||||
arc = preview["arc"]
|
arc = preview["arc"]
|
||||||
if len(arc) >= 2:
|
if len(arc) >= 2:
|
||||||
arc_segments = [(tuple(arc[i]), tuple(arc[i + 1])) for i in range(len(arc) - 1)]
|
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):
|
class WallFilletPreviewDecorator(tool.Blender.ViewportDecorator):
|
||||||
@@ -2343,15 +2308,15 @@ class WallFilletPreviewDecorator(tool.Blender.ViewportDecorator):
|
|||||||
(tuple(far_a), tuple(tangent_a)),
|
(tuple(far_a), tuple(tangent_a)),
|
||||||
(tuple(far_b), tuple(tangent_b)),
|
(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 []
|
arc = geom.get("arc") or []
|
||||||
if len(arc) >= 2:
|
if len(arc) >= 2:
|
||||||
arc_segments = [(tuple(arc[i]), tuple(arc[i + 1])) for i in range(len(arc) - 1)]
|
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"):
|
elif geom.get("invalid_axes"):
|
||||||
axes = geom["invalid_axes"]
|
axes = geom["invalid_axes"]
|
||||||
segments = [(tuple(a), tuple(b)) for a, b in 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
|
return
|
||||||
|
|
||||||
leg_color = tuple(prefs.decorations_colour[:3])
|
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_a), tuple(geom["tangent_a"])),
|
||||||
(tuple(far_b), tuple(geom["tangent_b"])),
|
(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"]
|
arc = geom["arc"]
|
||||||
if len(arc) >= 2:
|
if len(arc) >= 2:
|
||||||
arc_segments = [(tuple(arc[i]), tuple(arc[i + 1])) for i in range(len(arc) - 1)]
|
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
|
# Dim construction lines from arc_center to each tangent point so
|
||||||
# the radius reads as concrete during drag.
|
# 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_a"])),
|
||||||
(tuple(arc_center), tuple(geom["tangent_b"])),
|
(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
|
@staticmethod
|
||||||
def _far_endpoint(reference_line, intersection):
|
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]
|
pts = [world_main @ p for p in _DOOR_SWING_ARC_UNIT_POINTS]
|
||||||
for i in range(len(pts) - 1):
|
for i in range(len(pts) - 1):
|
||||||
segments.append((tuple(pts[i]), tuple(pts[i + 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 = (
|
_BBOX_EDGES = (
|
||||||
|
|||||||
@@ -219,6 +219,10 @@ _DASH_WIDTH_METERS: float = 0.10
|
|||||||
# overlay biases the depth buffer at outline pixels.
|
# overlay biases the depth buffer at outline pixels.
|
||||||
_DASH_LINE_WIDTH: float = 1.5
|
_DASH_LINE_WIDTH: float = 1.5
|
||||||
_SOLID_LINE_WIDTH: float = 2.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":
|
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
|
# Restore the per-iteration default set at the top of __call__ so
|
||||||
# subsequent draws (the HalfSpaceSolid arrow, future call-sites) are
|
# subsequent draws (the HalfSpaceSolid arrow, future call-sites) are
|
||||||
# not silently affected by the front-pass width override.
|
# 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)
|
gpu.state.depth_test_set(original_depth_test)
|
||||||
|
|
||||||
def __call__(self, context):
|
def __call__(self, context):
|
||||||
@@ -1286,7 +1290,7 @@ class DecorationsHandler:
|
|||||||
self.line_shader.bind() # required to be able to change uniforms of the shader
|
self.line_shader.bind() # required to be able to change uniforms of the shader
|
||||||
# POLYLINE_UNIFORM_COLOR specific uniforms
|
# POLYLINE_UNIFORM_COLOR specific uniforms
|
||||||
self.line_shader.uniform_float("viewportSize", (context.region.width, context.region.height))
|
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
|
# general shader
|
||||||
self.shader = gpu.shader.from_builtin("UNIFORM_COLOR")
|
self.shader = gpu.shader.from_builtin("UNIFORM_COLOR")
|
||||||
|
|||||||
@@ -1588,8 +1588,7 @@ class Model(bonsai.core.tool.Model):
|
|||||||
element = tool.Ifc.get_entity(object)
|
element = tool.Ifc.get_entity(object)
|
||||||
if not element:
|
if not element:
|
||||||
return
|
return
|
||||||
psets = ifcopenshell.util.element.get_psets(element)
|
pset_data = ifcopenshell.util.element.get_pset(element, pset_name)
|
||||||
pset_data = psets.get(pset_name, None)
|
|
||||||
if not pset_data:
|
if not pset_data:
|
||||||
return
|
return
|
||||||
pset_data["data_dict"] = json.loads(pset_data.get("Data", "[]") or "[]")
|
pset_data["data_dict"] = json.loads(pset_data.get("Data", "[]") or "[]")
|
||||||
|
|||||||
Reference in New Issue
Block a user