mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-11 22:31:55 +00:00
Highlight partner wall on link-toggle hover
Hovering a wall-junction link-toggle icon today only swaps the icon shape — the user doesn't see which wall the click will disconnect from until after they click. ATPATH (T-junction) configurations especially make the partner ambiguous when multiple connections sit close together. On hover, paint a wireframe bbox around the partner wall using the same shader, constants and color the array module already established for its layer-children highlight (POLYLINE_UNIFORM_COLOR, decorator_color_special, line width 1.8, alpha 0.8). The line-width / alpha constants in decorator.py are renamed from _ARRAY_LAYER_BBOX_LINE_* to _BBOX_HIGHLIGHT_LINE_* and shared between draw_array_layer_children_bbox and the new draw_wall_partner_bbox so the two highlights stay in lockstep. The trigger lives in a new GizmoWallLinkToggle subclass in wall.py which keeps the base gizmos.GizmoLinkToggle generic (per the generic-naming convention for shared widgets). The subclass's draw() calls super().draw(context) then on self.is_highlight outlines its partner_obj via the shared decorator helper. Same trigger pattern as GizmoArrayLayerIndicator. Blender's Gizmo API exposes target_set_operator but no symmetric getter, so the partner reference can't be read back from the bound operator handle. Instead GizmoWallUnjoinSingle.position_gizmos mirrors the resolved partner_obj onto each visible icon every frame next to the existing other_wall_guid write — the icon's draw() reads from its own __slots__-declared attribute. A forward-compat AST test pins the contract: GizmoWallLinkToggle.draw must reference is_highlight and call draw_wall_partner_bbox. Catches the regression where someone tidies the draw() override into super() or replaces the shared helper with an ad-hoc draw call. Generated with the assistance of an AI coding tool.
This commit is contained in:
committed by
Thomas Krijnen
parent
f2868c2631
commit
782f25bd31
@@ -28,6 +28,7 @@ rule is."""
|
||||
|
||||
import ast
|
||||
import inspect
|
||||
import textwrap
|
||||
|
||||
import pytest
|
||||
|
||||
@@ -59,3 +60,33 @@ def test_iter_path_connections_uses_path_connectable_predicate():
|
||||
"that strict predicate drops fillet-corner walls. Use "
|
||||
"is_path_connectable_wall instead."
|
||||
)
|
||||
|
||||
|
||||
def test_gizmo_wall_link_toggle_invokes_partner_bbox_helper():
|
||||
"""The wall subclass must call draw_wall_partner_bbox when its hover
|
||||
state is active. Without this contract the partner-wall highlight
|
||||
silently regresses if someone "tidies" the draw() override away."""
|
||||
from bonsai.bim.module.model import wall as wall_module
|
||||
|
||||
source = textwrap.dedent(inspect.getsource(wall_module.GizmoWallLinkToggle.draw))
|
||||
tree = ast.parse(source)
|
||||
attr_names = {node.attr for node in ast.walk(tree) if isinstance(node, ast.Attribute)}
|
||||
call_names: set[str] = set()
|
||||
for node in ast.walk(tree):
|
||||
if not isinstance(node, ast.Call):
|
||||
continue
|
||||
if isinstance(node.func, ast.Attribute):
|
||||
call_names.add(node.func.attr)
|
||||
elif isinstance(node.func, ast.Name):
|
||||
call_names.add(node.func.id)
|
||||
|
||||
assert "is_highlight" in attr_names, (
|
||||
"GizmoWallLinkToggle.draw must gate its highlight call on self.is_highlight — "
|
||||
"without it the partner outline would draw every frame, not just on hover."
|
||||
)
|
||||
assert "draw_wall_partner_bbox" in call_names, (
|
||||
"GizmoWallLinkToggle.draw must call draw_wall_partner_bbox to render the "
|
||||
"partner outline. The shared composite in decorator.py is the canonical "
|
||||
"trigger for this feature; replacing it with an ad-hoc draw call would "
|
||||
"drift from the array-children bbox styling."
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user