Commit Graph

20641 Commits

Author SHA1 Message Date
Gorgious56 230cbe1fd8 Add core/model.py constants + core/product.py helpers
core/model.py gains:

* Three calibrated dot-product / distance thresholds — PARALLEL_DOT_THRESHOLD
  (~2° from parallel, cos(2°) ≈ 0.9994), COLLINEAR_LINE_TOLERANCE (50mm
  perpendicular distance for two parallel wall axes to share a line),
  BASELINE_OFFSET_TOLERANCE — replacing inline magic numbers that the
  wall-join classifier, fillet-state machine, and gizmo preview decorator
  all read from.
* Pure wall-join geometry helpers (project_axis_intersection,
  are_axes_collinear, classify_wall_join_state, wall_join_preview_lines,
  resolve_extend_walls_target, extrusion_depth_from_vertical_height,
  length_and_height_from_extrusion). They take primitive tuples + floats,
  no bpy, no ifcopenshell — testable in the core lane.

core/product.py is new — pure-Python aggregate-walk helpers (resolve_host_
of_product, collect_decomposed_products) that downstream tool/spatial and
tool/aggregate consumers can call without importing ifcopenshell at module
load.

Generated with the assistance of an AI coding tool.
2026-05-26 23:28:19 +02:00
Richard Brice 45ea5eb07a Updates alignment api. Fixes bugs authoring semantic-only alignment bonsai-0.8.6-alpha2605251753 2026-05-25 10:34:29 -07:00
Richard Brice 42ed398169 Simplifies line and circle parent curves and parent curve normalization 2026-05-25 10:34:29 -07:00
Richard Brice f70044d373 Fixes bug computing cross slope 2026-05-25 10:34:29 -07:00
Ryan Schultz 719309571e Improve active tool panel hotkey button display
Use add_layout_hotkey_operator for draw_regen_operations so the Regen
button shows text and shortcut icons in the sidebar like all other
panel buttons. Add a separator between modifier and key icons for
readability.
bonsai-0.8.6-alpha2605251435
2026-05-25 09:35:12 -05:00
Bruno Postle d3f0ad03fb Quote {id} placeholders in examples (issue #8101)
Shell {} expressions require quoting
2026-05-24 20:25:36 +01:00
Gorgious56 7e96692764 Merge pull request #8089 from Gorgious56/gizmos
Parametric gizmos : Support wall and wall operations
bonsai-0.8.6-alpha2605210959
2026-05-21 11:58:54 +02:00
Gorgious56 3e0978062f Add lifecycle-mixin tests + predicate-total registry guard
test_parametric_lifecycle.py covers the door/window/railing/roof
state-transition contracts (enable/finish/cancel; no-op on
non-matching elements; draft preserved on finish-time failure)
that the registry smoke test never exercised.

test_parametric_registry.py gains a check that every is_<name>
predicate stays total (never raises on a non-matching IFC entity)
— a raising predicate would break the save path for unrelated
types. Also rewrites the gizmo-prefs check to read __annotations__
instead of hasattr, which depended on Blender registration timing.

Generated with the assistance of an AI coding tool.
2026-05-21 11:40:38 +02:00
Gorgious56 b3f482e0fa Defer mathutils imports in stair gizmo tests
Aligns with the test/bim/ convention: heavy imports go inside test
functions so the autouse _require_real_bpy fixture skips cleanly
when bpy is mocked, rather than module-level imports failing at
collection time and erroring out the whole file.

Generated with the assistance of an AI coding tool.
2026-05-21 11:18:00 +02:00
Gorgious56 4943c77c5e Add BONSAI_TEST_ARGS env-var fallback to runpytest.py
PowerShell and some wrapper scripts on Windows occasionally strip
or reorder the `--` separator before Blender sees it, dropping the
pytest args into Blender's positional file-load slot ("File format
is not supported"). The env var carries the same args via a
shell-evaluation-free channel. Default `--` path is byte-identical
to the pre-change behaviour.

Generated with the assistance of an AI coding tool.
2026-05-21 11:17:31 +02:00
Gorgious56 6caf94f1d3 Sweep docstrings for rot-prone references
Docstrings naming sibling methods, private helpers, test files, or
historical symbols silently go wrong on rename. Strip Sphinx :meth:
/ :class: / :func: / :attr: markup that mostly added noise (no
Sphinx in this project), and rewrite five docstrings that cited
specific test paths or private hooks to describe the behaviour
instead.

Generated with the assistance of an AI coding tool.
2026-05-21 11:09:29 +02:00
Gorgious56 1e36cc318e Drop save-time parametric-edit confirm dialog
The dialog's only outcomes were "Apply & Save" (same as silent save)
or "Cancel" (same as not saving) — net friction with no actual choice.
Auto-commit stays as the safety net; the count now suffixes the
existing save-success report so it isn't immediately overwritten.

Generated with the assistance of an AI coding tool.
2026-05-21 11:00:19 +02:00
Gorgious56 46381ec08b Prioritize smaller distance gizmos in selection
When two GizmoDimension hit regions overlap (a short dimension
nested inside a longer one along the same axis), the larger one
used to win because hit boxes are scaled by world-space length —
the long box fully contains the short one, leaving the short
gizmo unreachable. The larger gizmo stays clickable at its
exposed ends, so smaller-wins is the right UX default.

Sets self.select_bias = -self._dimension_length inside
GizmoDimension.set_dimension_length. The smaller gizmo writes a
less-negative depth value in the GPU select buffer and wins the
tie-break. select_bias is unused elsewhere in the codebase, so
icon and arrow gizmos keep bias=0 and are unaffected (icons
correctly still win against dimensions, since 0 > -length).

Adds test/bim/module/drawing/test_dimension_gizmo_priority.py
with 5 cases: direct ordering, monotonicity across length ranges,
abs() handling for signed dimensions, and NaN/Inf safety.

Generated with the assistance of an AI coding tool.
2026-05-21 10:30:32 +02:00
Gorgious56 47af955dd1 Simplify pending edit popup text 2026-05-21 09:48:00 +02:00
Gorgious56 f582d0230c Fix set_icon_gizmo_position so billboard ignores object rotation
set_icon_gizmo_position computed
``mw @ (Translation @ billboard_rot @ Scale)`` — the object's world
matrix was applied AFTER the billboard rotation, so any non-trivial
object rotation (e.g. a wall rotated in plan, a stair rotated to
match a corridor) carried over into the icon's transform and tilted
it edge-on to the camera instead of facing it.

Switch to ``billboarded_at(world_pos, billboard_rot, scale)`` where
``world_pos = mw @ local_pos``: translate to world space first, then
apply the billboard rotation independently of the object's rotation.
This matches the manual pattern the base class's
``update_editing_gizmos`` already uses for validate/cancel/cycle for
exactly this reason.

Drops the now-stale workaround docstring on
``GizmoWallEdition._update_icon_row_extras`` that documented why it
bypassed ``set_icon_gizmo_position`` — the helper does the right
thing now.

Adds ``test/bim/module/model/test_stair_gizmos.py`` as the regression
guard: parametrised over six rotation angles, asserts that the rotation
part of the resulting matrix equals ``billboard_rot`` (no contribution
from ``mw``'s rotation) and that the translation lands at
``world_pos``. Also exercises ``set_icon_gizmo_position`` end-to-end via
a stub gizmo to catch the exact shape of the previously-broken call
site.

Generated with the assistance of an AI coding tool.
2026-05-20 17:28:18 +02:00
Gorgious56 26eef20eb5 Add wall parametric editing and gizmos
Walls gain in-viewport parametric editing matching the door/window/stair
UX: drag handles for length, height, slope (x-angle), layer baseline
cycle, plus cursor-anchored quality-of-life operators (split at cursor,
extend to cursor, extend height, rotate 90, toggle openings) and
two-object state-machine gizmos (unjoin / merge / join-corner /
extend-to-wall / extend-vertically / add-opening).

Wall enters tool.Parametric.EDIT_TYPES, so save-time auto-commit,
GizmoPreferencesWall registration, and the in-progress-edit predicates
all light up automatically through the registry plumbing landed two
commits back.

The three-layer commit model (drag -> BIMWallProperties -> bmesh
preview -> Finish -> single ifc.run) means dragging a handle through
hundreds of intermediate values produces zero extra IFC entities. A
no-op enable->finish round-trip is byte-identical. The snapshot diff
in FinishEditingWall skips unchanged params.
_commit_active_wall_edit_if_any ensures cursor-anchored operators see
committed geometry, not the draft preview box.

Also lands the `prompt_auto_commit_parametric_edits` BoolProperty on
BIM_ADDON_preferences (consumed by the auto-commit dialog landed in
the framework commit) and refactors
`draw_{door,window,stair}_gizmo_parameters` into a shared
`_draw_parametric_gizmo_parameters` helper that the new
`draw_wall_gizmo_parameters` reuses. This commit and the framework
commit are stacked - the framework commit references the BoolProperty
defined here, so they must land together.

Tests cover pure math (core/test_model.py), DimensionGizmoConfig text
formatter, GizmoWallExtendVertically.poll() preconditions, and the
refresh_post_commit cache-invalidation regression. BDD scenarios in
model.feature cover the edit triad, auto-commit on save, and the
two-object gizmos. Documentation added to creating_walls.rst.

Generated with the assistance of an AI coding tool.
2026-05-20 16:58:39 +02:00
Gorgious56 2143262883 Fix dead duplicates and misleading import comments
Three small post-landing cleanups against the parametric framework commit:

* core/model.py had `are_axes_collinear` and `closest_endpoint_midpoint`
  each defined twice — Python silently kept the second copy, the first
  was dead code. Removed the dead copies; runtime behavior unchanged
  (the live versions were already the kept ones).
* bim/__init__.py's `_parametric_gizmo_preference_classes` docstring
  named the wrong link in the import chain (`tool.blender → bim.ifc`).
  The real chain is `tool/ifc.py` (and ~6 other tool/* modules) which
  import `from bonsai.bim.ifc import IfcStore` at module load. Updated
  docstring to cite that root cause and the architectural fix (move
  `IfcStore` out of `bim/`).
* tool/blender.py's `from bonsai.bim.ifc import IFC_CONNECTED_TYPE`
  carried a 5-line comment claiming it was "lazy" to avoid a circular
  load. The import sits inside an `if TYPE_CHECKING:` block with
  `from __future__ import annotations` — it never runs at runtime
  regardless. Comment removed; the TYPE_CHECKING guard is
  self-explanatory.

Generated with the assistance of an AI coding tool.
2026-05-20 16:25:49 +02:00
Gorgious56 233cc344fa Add tool.Parametric registry and lifecycle mixins
Establish a single source of truth for parametric element types (door,
window, stair, railing, roof). tool.Parametric.EDIT_TYPES drives:
- BIM<Name>Properties PointerProperty attachment via the registry
- GizmoPreferences<Name> class registration in bim/__init__.py
- save-time auto-commit of pending draft edits
- the refresh_post_commit epilogue called from IfcStore after every IFC
  mutation, which fixes the stale-header bug where in-place hotkey
  mutations (S_E / C_E) left BIMModelProperties and the gizmo cache
  pointing at obsolete values.

Refactors door/window/railing/roof onto shared mixins from
bim/parametric_lifecycle.py (FeatureModifierEditMixin and
PathPreservingEditMixin); stair gets the lock-gizmo refactor and
frame-cache integration. Behavior preserved.

Adds BaseParametricGizmoGroup._prime_frame_caches so the parametric
gizmos stop re-deriving preferences, view direction, and billboard
rotation per frame; reorders poll() to short-circuit on the cheapest
predicate first. Adds the icon library + BillboardingGizmoGroupMixin
that the wall feature in the next commit will consume.

Generated with the assistance of an AI coding tool.
2026-05-20 15:18:44 +02:00
Gorgious56 a64e737d9c Merge pull request #8078 from Gorgious56/v0.8.0
Fix 8077 : Fix SHIFT + D with non-ifc object selection
bonsai-0.8.6-alpha2605191103
2026-05-19 13:03:21 +02:00
Gorgious56 1b2507e143 Fix 8077 : Fix SHIFT + D with non-ifc object selection
When a project has a ifc file associated, selecting non-ifc objects and duplicating them with SHIFT + D now correctly both duplicate them, keep the new objects selected and starts the transform modal. IFC objects behaviour is unaffected.
2026-05-19 12:29:18 +02:00
Geert Hesselink 508b99cb73 Fix lint failures and add missing pyparsing dependency (#8048)
* unblock voxel schema loading, add test for express

* Apply black formatting

* Fix lint failures and add missing pyparsing dependency

* align ty -> 0.0.34
bonsai-0.8.6-alpha2605182017
2026-05-18 22:17:45 +02:00
Thomas Krijnen 4e406ab1ce Change default value of assume_asset_uniqueness_by_name #8045 bonsai-0.8.6-alpha2605181129 2026-05-18 13:29:39 +02:00
Thomas Krijnen 227d85d81f arrange polygons: limit width ratio when merging boxes 2026-05-15 21:12:43 +02:00
Thomas Krijnen a24cdf4958 Merge branch 'v0.8.0' of https://github.com/IfcOpenShell/IfcOpenShell into v0.8.0 2026-05-15 21:12:01 +02:00
Ryan Schultz e78ef865b8 Fix #8056 - Dimensions with CustomUnit" = "Inches - Fractional" should not show 0. bonsai-0.8.6-alpha2605151228 2026-05-15 07:28:29 -05:00
Thomas Krijnen 9345b9ce3f arrange polies: don't allow snapped point paths to cross non-containing other rect axes 2026-05-14 21:45:59 +02:00
Thomas Krijnen 0b5dded3b3 Fix temporary solution storage in arrange polygons 2026-05-14 14:37:44 +02:00
Thomas Krijnen 97218b1fdb Calculate box-width as orthogonal distance; aabb code for segment intersection (disabled) 2026-05-14 14:17:10 +02:00
Thomas Krijnen 1b637c6499 Arrange polies: reorder segment to exterior insertion based on length 2026-05-12 20:52:30 +02:00
Thomas Krijnen 47312e1fbb Reduce log noise on materials without styles #7947 2026-05-08 15:00:30 +02:00
Thomas Krijnen 7aa2bb366e arrange polies, fuse boxes only when obb also overlaps 2026-05-07 20:35:54 +02:00
Ghesselink c197a45247 Apply black formatting bonsai-0.8.6-alpha2605061132 2026-05-06 13:32:05 +02:00
Ghesselink ab73550059 unblock voxel schema loading, add test for express 2026-05-06 13:32:05 +02:00
Thomas Krijnen 53c2ddbb47 arrange polies: try connect to closest point when extension and projection both do not work 2026-05-03 21:46:11 +02:00
Thomas Krijnen 7c6f6a4176 arrange polies performance: retain input poly provenance while subdividing; insert into arrangement_2 in batches 2026-05-02 13:21:20 +02:00
Thomas Krijnen 261037fb82 arrange polies: only subdivide segments that correspond to input poly segments 2026-05-02 13:21:20 +02:00
Thomas Krijnen eacbb55810 arrange polies: apply triangle elimination in both algo 1 and 2 2026-05-02 13:21:20 +02:00
Thomas Krijnen 3d05a5e9d1 arrange polies: lower iou to 45% 2026-05-02 13:21:20 +02:00
Richard Brice cb3253b57c Removes unnecessary operations when combining horizontal and vertical placement matrices for alignment 2026-05-01 14:13:00 -07:00
Thomas Krijnen a23cb3744f arrange polygons: debug output point and annotate self intersecting polies; fix snapping distance check and fallback; tweak max snap to exterior distance; accept non-simple polies - likely touching without edge overlap; write representative points to debug output; properly apply algo 1 fallback; correct order for halfedge elimination; 2026-05-01 16:24:20 +02:00
dependabot[bot] 57ef96a909 Bump actions/checkout from 4 to 6
Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 6.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v4...v6)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
bonsai-0.8.6-alpha2604302255
2026-05-01 08:58:38 +10:00
dependabot[bot] 674d98dbb3 Bump astral-sh/setup-uv from 3 to 7
Bumps [astral-sh/setup-uv](https://github.com/astral-sh/setup-uv) from 3 to 7.
- [Release notes](https://github.com/astral-sh/setup-uv/releases)
- [Commits](https://github.com/astral-sh/setup-uv/compare/v3...v7)

---
updated-dependencies:
- dependency-name: astral-sh/setup-uv
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-05-01 08:58:31 +10:00
dependabot[bot] c58711a8f7 Bump hendrikmuhs/ccache-action from 1.2.22 to 1.2.23
Bumps [hendrikmuhs/ccache-action](https://github.com/hendrikmuhs/ccache-action) from 1.2.22 to 1.2.23.
- [Release notes](https://github.com/hendrikmuhs/ccache-action/releases)
- [Commits](https://github.com/hendrikmuhs/ccache-action/compare/v1.2.22...v1.2.23)

---
updated-dependencies:
- dependency-name: hendrikmuhs/ccache-action
  dependency-version: 1.2.23
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
bonsai-0.8.6-alpha2604302253
2026-05-01 08:56:20 +10:00
dependabot[bot] e1a7214a29 Bump ruff from 0.15.10 to 0.15.12
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.15.10 to 0.15.12.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/ruff/compare/0.15.10...0.15.12)

---
updated-dependencies:
- dependency-name: ruff
  dependency-version: 0.15.12
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-05-01 08:56:13 +10:00
dependabot[bot] 852d620dc6 Bump ty from 0.0.29 to 0.0.32
Bumps [ty](https://github.com/astral-sh/ty) from 0.0.29 to 0.0.32.
- [Release notes](https://github.com/astral-sh/ty/releases)
- [Changelog](https://github.com/astral-sh/ty/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/ty/compare/0.0.29...0.0.32)

---
updated-dependencies:
- dependency-name: ty
  dependency-version: 0.0.32
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-05-01 08:56:05 +10:00
Ryan Schultz 856631092b Fix #7885: LAYER3 crash on IfcCompositeProfileDef
The x-angle transformation for LAYER3 slabs assumed SweptArea
is always IfcArbitraryClosedProfileDef (which has OuterCurve),
but composite profiles use IfcCompositeProfileDef instead.
Apply the coord scaling to each sub-profile individually.

Generated with the assistance of an AI coding tool.
bonsai-0.8.6-alpha2604302251
2026-05-01 08:54:02 +10:00
Ryan Schultz 7a61cf20a4 Fix #7927: Fix SECTION annotation for MODEL_VIEW drawings
generate_section_reference_points had no handler for
MODEL_VIEW target view, causing it to silently return
None. Add MODEL_VIEW branch that clips the section line
to XY camera bounds while preserving the Z coordinate
for correct 3D placement.

Generated with the assistance of an AI coding tool.
2026-05-01 08:52:55 +10:00
Ryan Schultz c999a92aa7 Fix #8024 - Fix TypeError when CardinalPoint is None
Guard the int() cast on CardinalPoint in
BIM_OT_edit_assigned_material so a None value (no cardinal
point set) no longer raises a TypeError.

Generated with the assistance of an AI coding tool.
bonsai-0.8.6-alpha2604302247
2026-05-01 08:51:00 +10:00
E Shattow 434b179ed9 docs: project_overview: project_info blender tip to change display units after project creation
Link to Blender Manual for tip to change display units
2026-05-01 08:47:42 +10:00
Thomas Krijnen 8b5b4006aa Try with manual paths bonsai-0.8.6-alpha2604261928 2026-04-26 21:29:16 +02:00