Files
IfcOpenShell/src
Gorgious56 ed7b2fc233 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.
2026-06-02 15:35:31 +02:00
..