mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-11 06:18:09 +00:00
Stack wall-join trio along screen-up + L/T glyphs
GizmoWallJoinIntersection used to place its icons at state-specific world points: join at floor Z, extend-to-wall at the active wall's top Z, fillet stacked screen-up above join. Same XY at different Z collapses to a single screen pixel in plan / top view, so two icons became one hit target — invisible from above. * position_gizmos now always-stacks along screen-up at a wall-top anchor in both the joined (unjoin + fillet) and the intersecting (extend + join + fillet) states. Order bottom-up is extend / L / fillet. Collinear-merge keeps its single boundary icon (no stack needed). * New _stack_anchor_z picks the active wall's top Z (or the taller of the two on mid-selection-transition frames). New _stack_at lays a tuple of icons along screen-up at the resolved anchor. * Glyph swap: join_icon -> VIEW3D_GT_wall_corner (L), extend_to_wall_icon -> VIEW3D_GT_wall_tee (T). Both classes already existed in bim/module/drawing/gizmos.py from an earlier commit; only the setup() bl_idname strings changed. The previous arrow-merge / arrow-extend pair read as the same direction once stacked. Forward-compat AST contracts in test_wall_gizmos_forward_compat.py pin the new invariants: the L and T bl_idnames must appear in setup(), and position_gizmos must route through _stack_at so a regression that reintroduces a direct billboarded_at write for any state-specific icon fails CI before it flattens the stack again. Also folds in a one-line typo fix in core/spatial.py: assign_container's per-element can_contain check iterated `e` but predicate-tested `root_element` (the outer for-loop variable), so every element in the comprehension was tested against the same container/element pair. Switch the argument to `e`. Generated with the assistance of an AI coding tool.
This commit is contained in:
committed by
Thomas Krijnen
parent
ebb3b1ed10
commit
497acc3d19
@@ -159,3 +159,54 @@ def test_gizmo_wall_add_opening_accepts_fillet_corner_active():
|
||||
"drops fillet-corner walls. Use is_path_connectable_wall instead, matching "
|
||||
"the host gate every other wall-state gizmo group uses."
|
||||
)
|
||||
|
||||
|
||||
def test_join_intersection_uses_l_and_t_glyphs():
|
||||
"""``GizmoWallJoinIntersection.setup`` must bind the join icon to the L
|
||||
glyph (``VIEW3D_GT_wall_corner``) and the extend-to icon to the T glyph
|
||||
(``VIEW3D_GT_wall_tee``). The L / T pair makes the corner-join vs
|
||||
extend-into-side distinction read at a glance — a regression to the
|
||||
arrow-merge glyph for both icons makes them visually indistinguishable
|
||||
once they're stacked at the same XY."""
|
||||
from bonsai.bim.module.model.wall import GizmoWallJoinIntersection
|
||||
|
||||
source = textwrap.dedent(inspect.getsource(GizmoWallJoinIntersection.setup))
|
||||
assert '"VIEW3D_GT_wall_corner"' in source, (
|
||||
"GizmoWallJoinIntersection.setup must bind join_icon to VIEW3D_GT_wall_corner "
|
||||
"(the L glyph). The arrow-merge glyph (VIEW3D_GT_merge) is the collinear-merge "
|
||||
"case and was visually ambiguous with the extend-to icon when both were stacked."
|
||||
)
|
||||
assert '"VIEW3D_GT_wall_tee"' in source, (
|
||||
"GizmoWallJoinIntersection.setup must bind extend_to_wall_icon to "
|
||||
"VIEW3D_GT_wall_tee (the T glyph). The arrow-extend glyph was visually "
|
||||
"ambiguous with the join icon when both were stacked."
|
||||
)
|
||||
|
||||
|
||||
def test_join_intersection_stacks_along_screen_up_in_both_states():
|
||||
"""``GizmoWallJoinIntersection.position_gizmos`` must route both the
|
||||
joined (unjoin + fillet) and the intersecting (join + extend + fillet)
|
||||
states through ``_stack_at`` so the icons stay individually clickable
|
||||
in any view, including top / plan view where world-Z separation
|
||||
collapses to zero on screen. A regression that re-introduces a
|
||||
per-state ``billboarded_at(corner, ...)`` write outside ``_stack_at``
|
||||
silently flattens the stack back onto one screen pixel."""
|
||||
from bonsai.bim.module.model.wall import GizmoWallJoinIntersection
|
||||
|
||||
source = textwrap.dedent(inspect.getsource(GizmoWallJoinIntersection.position_gizmos))
|
||||
tree = ast.parse(source)
|
||||
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 "_stack_at" in call_names, (
|
||||
"GizmoWallJoinIntersection.position_gizmos must call self._stack_at to "
|
||||
"lay icons along screen-up at the wall-top anchor. Direct "
|
||||
"billboarded_at writes for the join/unjoin/extend/fillet icons bypass "
|
||||
"the stacking contract and re-introduce the top-view collapse bug."
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user