Compare commits

..

185 Commits

Author SHA1 Message Date
Ryan Schultz 7c738c15d9 Fix slab layer geometry for rotated and angled slabs
Three bugs fixed:

1. EditAssignedMaterial was sweeping all slabs that share a layer set
   when changing material properties, instead of updating only the
   selected element's assigned material.

2. slice_layerset_mesh (loader.py): layer bisect positions were scaled
   incorrectly due to a stale unit_scale and a reversed/missing
   DirectionSense guard. Now always recalculates unit_scale fresh and
   correctly applies sense_factor.

3. change_thickness (slab.py): extrusion depth was computed as
   `thickness / cos(obj.rotation_euler.x)`, which incorrectly scaled
   ObjectPlacement-rotated slabs (where the extrusion direction is
   local Z and no scaling is needed). The correct formula is
   `thickness / extrusion_vec.z`, which handles both ObjectPlacement
   rotation (extrusion_vec.z ≈ 1.0 → no scale) and ExtrudedDirection
   tilts (extrusion_vec.z < 1.0 → scale up) uniformly. The resulting
   slab was 1.414× too thick for 45°-rotated slabs, making both
   material layers appear fatter than specified.

   slice_layerset_mesh retains a depth_scale safety factor
   (extrusion_vec.z × ifc_depth / total_layer_thickness) as a
   robustness guard for IFC files from other authoring tools where
   extrusion depth may not match the sum of LayerThicknesses.
2026-03-14 12:21:54 -05:00
Ryan Schultz 036ee098a6 Fix slab layer geometry: custom offset isolation, unit scale, and layer ordering
Three related bugs fixed in the slab material layer set workflow:

1. EditAssignedMaterial (operator.py): Applying a custom offset to one slab
   instance incorrectly regenerated geometry for ALL slabs sharing the same
   IfcMaterialLayerSet. Replaced regenerate_from_layer_set (sweeps all users)
   with per-element regenerate_from_occurence for AXIS3 slabs and targeted
   recalculate_walls for AXIS2 walls. Each element's IfcMaterialLayerSetUsage
   attributes are now updated individually before regeneration.

2. slice_layerset_mesh (loader.py): Loader.unit_scale is a class variable only
   set during full file import, so it was stale (= 1) during live geometry
   updates on foot-based IFC files. Layer bisect planes were being computed in
   IFC feet while the mesh was in Blender metres, placing all cuts completely
   outside the mesh. Fixed by computing unit_scale fresh from the IFC file on
   each call via ifcopenshell.util.unit.calculate_unit_scale.

3. OffsetFromReferenceLine stale / layer order reversed (slab.py, loader.py):
   A guard (and custom_offset is None) in change_thickness prevented writing
   the correct OffsetFromReferenceLine (position.z) to the usage when a custom
   offset was active. This left the value at 0.0 instead of the actual slab
   bottom (e.g. -1.0 IFC units for a TOP-reference slab), so the bisect
   starting point co was at the reference plane rather than the slab bottom,
   reversing layer assignments or missing layers entirely. Removed the guard —
   safe because each element has its own IfcMaterialLayerSetUsage instance.
   Reverted the AXIS3 bisect normal back to (0,0,1) (upward from co at slab
   bottom) which is correct once OffsetFromReferenceLine is properly set.
2026-03-14 12:21:35 -05:00
Thomas Krijnen cf9df33aa5 Change checkout reference to build branch 2026-03-14 14:51:24 +01:00
Thomas Krijnen 1a6fd2530f Remove dependency on Standard_failure #7788 2026-03-14 14:44:47 +01:00
Dion Moult ea64f1b6b9 Fix #7770, #7747, #7572, #7522, #7416, #7086: Bug when first point in poly tool clicked twice
Previous logic always skipped the first point. Instead, it should only
skip when actually closing a loop (i.e. >= 3 points).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-14 20:35:59 +11:00
Dion Moult 473d689cf2 Fix #7794: Only slice layerset mesh when material layer set usage exists
Without a usage, orientation is undefined so slicing should be skipped.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-14 13:25:14 +11:00
Richard Brice cf1552e79e Simplifies IfxAxis2PlacementLinear, assumes default Axis = (0,0,1) 2026-03-13 11:16:10 -07:00
Andrej730 90db564b4b ifcclash - add advanced package type that supports smart group clashes 2026-03-13 20:26:23 +05:00
Andrej730 e9fb6b3c1d Bonsai Makefile - upstream bpypolyskel wheel recipe
Sent PR - https://github.com/prochitecture/bpypolyskel/pull/22
2026-03-13 20:26:23 +05:00
Andrej730 a5e0b3f0e5 Bonsai Makefile - upstream ifcjson wheel recipe
Sent PR - https://github.com/IFCJSON-Team/IFC2JSON_python/pull/8
2026-03-13 20:26:23 +05:00
Andrej730 60519e8fed ifcopenshell dev_environment - include all packages 2026-03-13 20:26:23 +05:00
Andrej730 8fb454bb27 Partially disable old Windows workaround for Bonsai uninstallation 2026-03-13 20:26:23 +05:00
Andrej730 9ed8f3e244 Bonsai - fix missing Bonsai Fatal Error UI
Since we added more data to debug info in fcf5614 Fatal Error itself started to fail and was never displayed due some props being inaccessible during load, should be fixed now.

Possible error that were fixed:
```
  File "\Blender\5.1\extensions\raw_githubusercontent_com\bonsai\__init__.py", line 328, in <module>
    print(format_debug_info(get_debug_info()))
                            ~~~~~~~~~~~~~~^^
  File "\Blender\5.1\extensions\raw_githubusercontent_com\bonsai\__init__.py", line 117, in get_debug_info
    if bpy.data.is_saved:
       ^^^^^^^^^^^^^^^^^
AttributeError: '_RestrictData' object has no attribute 'is_saved'

Traceback (most recent call last):
  File "\Blender\5.1\extensions\raw_githubusercontent_com\bonsai\__init__.py", line 366, in draw
    info = get_debug_info()
  File "\Blender\5.1\extensions\raw_githubusercontent_com\bonsai\__init__.py", line 152, in get_debug_info
    bim_props = tool.Blender.get_bim_props()
                ^^^^
NameError: name 'tool' is not defined. Did you mean: 'bool'?

Traceback (most recent call last):
  File "\Blender\5.1\extensions\raw_githubusercontent_com\bonsai\__init__.py", line 366, in draw
    info = get_debug_info()
  File "\Blender\5.1\extensions\raw_githubusercontent_com\bonsai\__init__.py", line 141, in get_debug_info
    import bonsai.tool as tool
  File "\Blender\5.1\extensions\.local\lib\python3.13\site-packages\bonsai\__init__.py", line 355, in <module>
    print(format_debug_info(get_debug_info()))
                            ~~~~~~~~~~~~~~^^
  File "\Blender\5.1\extensions\.local\lib\python3.13\site-packages\bonsai\__init__.py", line 141, in get_debug_info
    import bonsai.tool as tool
  File "\Blender\5.1\extensions\.local\lib\python3.13\site-packages\bonsai\tool\__init__.py", line 23, in <module>
    from bonsai.tool.attribute import Attribute
  File "\Blender\5.1\extensions\.local\lib\python3.13\site-packages\bonsai\tool\attribute.py", line 31, in <module>
    import bonsai.bim.helper as helper
  File "\Blender\5.1\extensions\.local\lib\python3.13\site-packages\bonsai\bim\__init__.py", line 28, in <module>
    from . import handler, operator, prop, ui
  File "\Blender\5.1\extensions\.local\lib\python3.13\site-packages\bonsai\bim\handler.py", line 36, in <module>
    from bonsai.bim.module.aggregate.decorator import AggregateDecorator
  File "\Blender\5.1\extensions\.local\lib\python3.13\site-packages\bonsai\bim\module\aggregate\__init__.py", line 21, in <module>
    from . import operator, prop, ui
  File "\Blender\5.1\extensions\.local\lib\python3.13\site-packages\bonsai\bim\module\aggregate\operator.py", line 32, in <module>
    class BIM_OT_aggregate_assign_object(bpy.types.Operator, tool.Ifc.Operator):
                                                             ^^^^^^^^
AttributeError: partially initialized module 'bonsai.tool' from '\Blender\5.1\extensions\.local\lib\python3.13\site-packages\bonsai\tool\__init__.py' has no attribute 'Ifc' (most likely due to a circular import)
```
2026-03-13 20:26:23 +05:00
Andrej730 298beacef6 Bonsai - remove pyperclip use 2026-03-13 20:26:22 +05:00
Andrej730 eba798c544 typing 2026-03-13 20:26:22 +05:00
dependabot[bot] 1576302caf Bump devalue from 5.6.3 to 5.6.4 in /src/ifctester/webapp
Bumps [devalue](https://github.com/sveltejs/devalue) from 5.6.3 to 5.6.4.
- [Release notes](https://github.com/sveltejs/devalue/releases)
- [Changelog](https://github.com/sveltejs/devalue/blob/main/CHANGELOG.md)
- [Commits](https://github.com/sveltejs/devalue/compare/v5.6.3...v5.6.4)

---
updated-dependencies:
- dependency-name: devalue
  dependency-version: 5.6.4
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-13 07:58:26 +01:00
dependabot[bot] d7f29c4494 Bump tar from 7.5.10 to 7.5.11 in /src/ifctester/webapp
Bumps [tar](https://github.com/isaacs/node-tar) from 7.5.10 to 7.5.11.
- [Release notes](https://github.com/isaacs/node-tar/releases)
- [Changelog](https://github.com/isaacs/node-tar/blob/main/CHANGELOG.md)
- [Commits](https://github.com/isaacs/node-tar/compare/v7.5.10...v7.5.11)

---
updated-dependencies:
- dependency-name: tar
  dependency-version: 7.5.11
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-13 07:58:22 +01:00
dependabot[bot] 4ff6f7c78b Bump black from 26.3.0 to 26.3.1
Bumps [black](https://github.com/psf/black) from 26.3.0 to 26.3.1.
- [Release notes](https://github.com/psf/black/releases)
- [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
- [Commits](https://github.com/psf/black/compare/26.3.0...26.3.1)

---
updated-dependencies:
- dependency-name: black
  dependency-version: 26.3.1
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-13 07:58:06 +01:00
Andrej730 0b44e146bd Fix error starting Bonsai (77697aeef) 2026-03-13 11:57:17 +05:00
tsomanna_QCOM cf42f986c4 Add Support for IfcOpenShell on Win ARM64 2026-03-12 20:29:10 +01:00
tsomanna_QCOM e84142894e Add Support for IfcOpenShell on Win ARM64 2026-03-12 20:29:10 +01:00
tsomanna_QCOM b38a0dce1f Add Support for IfcOpenShell on Win ARM64 2026-03-12 20:29:10 +01:00
tsomanna_QCOM ae253f5e2a Add Support for IfcOpenShell on Win ARM64 2026-03-12 20:29:10 +01:00
tsomanna_QCOM b25c24a007 Add Support for IfcOpenShell on Win ARM64 2026-03-12 20:29:10 +01:00
Andrej730 8bd3fab608 Linked Models - option to isolate selected object
Quick demo - https://files.catbox.moe/6chdx7.mp4
2026-03-12 20:21:10 +05:00
Andrej730 82951fe702 Pylance - ignore _deps folder
In my case it was adding 3115 Python files and VS Code kept indexing them.
2026-03-12 20:21:10 +05:00
Andrej730 77697aeefc typing 2026-03-12 20:21:10 +05:00
Thomas Krijnen 71442bd4d4 Submodule 2026-03-12 12:34:05 +01:00
Andrej730 f7bee258c6 Linked models - add description for georeferencing indicator
Example - https://files.catbox.moe/bkn9pn.png
2026-03-11 18:38:25 +05:00
Andrej730 0585f8716a Quick Favorites Manager - support enum items 2026-03-11 18:38:25 +05:00
Andrej730 f3fe1a7bf0 ci.yml - BUILD_EXAMPLES=ON to keep testing examples build 2026-03-11 18:38:25 +05:00
Andrej730 61ba6a7989 Add operator to run search generic search queries
So it will be easy to add queries to quick favorites.
2026-03-11 18:38:25 +05:00
Andrej730 97f900e62f Quick Favorites Manager - show operators suggestions 2026-03-11 18:38:25 +05:00
Andrej730 594d72d7e1 Quick Favorites Manager
Blender doesn't have it's own quick favorites manager and working with them can be not very flexible - you can add them in context menu and remove them from Quick Favorites menu. But you can't reorder them, you can't rename them and you can't even add a new button to favorites if it's not added by some addon in the UI.

Have been stumbling upon this for awhile and decided to create an experimental manager UI for this. Things it can do:
- help user create a button with any operator in Blender and properties they prefer to then save it Quick Favorites. Which seems can be very useful in Bonsai, since you can create separate buttons for all kinds of selectors expressions, class assignment or other operators.

- it can import quick favorites from user's actual current quick favorites, so they can just modify them a bit, reorder, rename and then add them again.

- Since quick favorites are not exposed to Python API in Blender, we're using a very hacky way to retrieve them from Blender and don't provide our own buttons for adding and removing quick favorites, as it may be dangerous and even more hacky in implementation. So the workflow for user is to either generate some buttons and add them to quick favorites using Manager or to import it's own quick favorites, then change them how they like, then remove quick favorites using usual quick favorites menu and then add new button one by one.

Small demo - https://files.catbox.moe/vyffp6.mp4
2026-03-11 18:38:24 +05:00
Andrej730 578caaf2cd tool.Blender.update_all_viewports 2026-03-11 18:38:24 +05:00
Andrej730 15ea092ac4 typing 2026-03-11 18:38:23 +05:00
Andrej730 4b12b6dacd bim.hide_queried_linked_element - note known UNDO limitation 2026-03-11 18:38:23 +05:00
Andrej730 584bbe3b83 tool/test_project - remove redundant __init__ 2026-03-11 18:38:22 +05:00
Andrej730 e47b7bca4b ci-black-formatting.yml - note on Python versions used 2026-03-11 18:38:22 +05:00
Andrej730 62b108766b ci-black-formatting.yml - note on Python versions used 2026-03-11 18:38:22 +05:00
HugoBallee 972a1fd309 Update getting_started.rst
IFC_SCHEMA_NAME matching includes
2026-03-10 09:41:09 +01:00
Bruno Postle 6f0bb21a43 Disable building example applications by default, closes #7763
Enable with -DBUILD_EXAMPLES=ON
2026-03-09 22:59:34 +00:00
dependabot[bot] 72f279381f Bump immutable from 5.1.2 to 5.1.5 in /src/ifctester/webapp
Bumps [immutable](https://github.com/immutable-js/immutable-js) from 5.1.2 to 5.1.5.
- [Release notes](https://github.com/immutable-js/immutable-js/releases)
- [Changelog](https://github.com/immutable-js/immutable-js/blob/main/CHANGELOG.md)
- [Commits](https://github.com/immutable-js/immutable-js/compare/v5.1.2...v5.1.5)

---
updated-dependencies:
- dependency-name: immutable
  dependency-version: 5.1.5
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-09 14:33:44 +01:00
dependabot[bot] 9873e403bc Bump tar from 7.5.9 to 7.5.10 in /src/ifctester/webapp
Bumps [tar](https://github.com/isaacs/node-tar) from 7.5.9 to 7.5.10.
- [Release notes](https://github.com/isaacs/node-tar/releases)
- [Changelog](https://github.com/isaacs/node-tar/blob/main/CHANGELOG.md)
- [Commits](https://github.com/isaacs/node-tar/compare/v7.5.9...v7.5.10)

---
updated-dependencies:
- dependency-name: tar
  dependency-version: 7.5.10
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-09 14:33:38 +01:00
dependabot[bot] a48449bc9c Bump docker/setup-buildx-action from 3 to 4
Bumps [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) from 3 to 4.
- [Release notes](https://github.com/docker/setup-buildx-action/releases)
- [Commits](https://github.com/docker/setup-buildx-action/compare/v3...v4)

---
updated-dependencies:
- dependency-name: docker/setup-buildx-action
  dependency-version: '4'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-09 14:33:31 +01:00
dependabot[bot] 8cc50b7399 Bump docker/build-push-action from 6 to 7
Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 6 to 7.
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](https://github.com/docker/build-push-action/compare/v6...v7)

---
updated-dependencies:
- dependency-name: docker/build-push-action
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-09 14:33:25 +01:00
dependabot[bot] da027b912e Bump black from 26.1.0 to 26.3.0
Bumps [black](https://github.com/psf/black) from 26.1.0 to 26.3.0.
- [Release notes](https://github.com/psf/black/releases)
- [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
- [Commits](https://github.com/psf/black/compare/26.1.0...26.3.0)

---
updated-dependencies:
- dependency-name: black
  dependency-version: 26.3.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-09 14:33:18 +01:00
dependabot[bot] b65a69b9ca Bump docker/login-action from 3 to 4
Bumps [docker/login-action](https://github.com/docker/login-action) from 3 to 4.
- [Release notes](https://github.com/docker/login-action/releases)
- [Commits](https://github.com/docker/login-action/compare/v3...v4)

---
updated-dependencies:
- dependency-name: docker/login-action
  dependency-version: '4'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-09 14:25:36 +01:00
dependabot[bot] 3b3b1f1eab Bump ruff from 0.15.4 to 0.15.5
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.15.4 to 0.15.5.
- [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.4...0.15.5)

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

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-09 14:25:11 +01:00
dependabot[bot] ff1b74ef10 Bump docker/setup-qemu-action from 3 to 4
Bumps [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) from 3 to 4.
- [Release notes](https://github.com/docker/setup-qemu-action/releases)
- [Commits](https://github.com/docker/setup-qemu-action/compare/v3...v4)

---
updated-dependencies:
- dependency-name: docker/setup-qemu-action
  dependency-version: '4'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-09 14:22:05 +01:00
Richard Brice 610d639c21 Fixes rotation lerp test in make_loft 2026-03-08 10:37:05 -07:00
Richard Brice e282a18474 Fixes crash in taxonomy::loft::print_impl when axis == nullptr 2026-03-08 09:55:47 -07:00
Thomas Krijnen 0469a9528b use basic casts to prevent needless item upgrades #7738 2026-03-06 16:34:12 +01:00
Andrej730 f9486be172 get_linked_element_geom_slice - add tests 2026-03-06 19:07:34 +05:00
Andrej730 3a59425a64 Linked IFC models - hotkey to hide selected geometry
Demo - https://files.catbox.moe/aok74w.mp4
2026-03-06 19:07:34 +05:00
Andrej730 9d0c172a53 bim.select_linked_model_element
Refactored methods for accessing objects in linked models and added a simple operator to select object in linked model by providing guid.

A quick demo - https://files.catbox.moe/sjjw37.mp4
2026-03-06 19:07:34 +05:00
Andrej730 ecc82a52f5 ExtractPropertiesToSQLite - add typing for created columns 2026-03-06 19:07:34 +05:00
Andrej730 adaf33b74f project.operator - reuse ray_cast method 2026-03-06 19:07:33 +05:00
Andrej730 a52a329197 Update note on Blender upstream issue
Fix was included in 4.5.7 (see 141496 bug in https://projects.blender.org/blender/blender/issues/141871)
2026-03-06 19:07:33 +05:00
Andrej730 3a54e808f6 dev_environment python - create user site packages folder if missing
E.g. it might be missing if Python was just installed. Also print paths first before symlinking, making it easier to debug.
2026-03-06 19:07:33 +05:00
Andrej730 f102c7c1b4 ifcopenshell-python makefile - add note about PYNUMBER 2026-03-06 19:07:33 +05:00
Andrej730 9005333f53 ifcpatch MergeProjects - make logger arg optional 2026-03-06 19:07:33 +05:00
Andrej730 a26dbe252a bim.append_inspected_linked_element - fix missing UNDO 2026-03-06 19:07:33 +05:00
Andrej730 8743d5643e typing 2026-03-06 19:07:33 +05:00
Andrej730 619848823c Sort out imports 2026-03-06 19:07:32 +05:00
Richard Brice 951ade4b57 Fix bug introduced in 65d5df78 2026-03-05 14:50:33 -08:00
Richard Brice 1378919709 Fixes IfcLinearPlacement fallback position warning 2026-03-03 13:16:55 -08:00
Ryan Schultz 61cfa48c2c docs: add BonsaiPR bleeding edge installation section (#7721)
* Fix #7718: Fix FallDecorator label calculation for all slope annotation types

- Fix wrong dict key type in decoration.py: DecoratorData.data["fall"] is
  keyed by obj.name (str) but was looked up with obj (Object), causing
  object_type to always be None
- Apply obj.matrix_world transform to spline points before computing rise/run
  in both decoration.py and svgwriter.py; local coordinates have Z=0 for flat
  annotations, world coordinates correctly reflect elevation change
- Use hypotenuse (segment_length) instead of run as the denominator for
  SLOPE_FRACTION label display

Generated with the assistance of an AI coding tool.

* docs: add BonsaiPR bleeding edge installation section

Add new section to installation.rst documenting the BonsaiPR
community build, including why it exists, how the automated
PR-merging system works, installation steps with automated
updates, manual installation, and the PR workflow for
contributors.

Generated with the assistance of an AI coding tool.

* whoops
2026-03-03 18:48:03 +11:00
falken10vdl d6c782aba5 Add newline handling with add_newline_between_words n SvgWriter for text literals 2026-03-03 18:46:14 +11:00
dependabot[bot] d4150e0558 Bump svelte from 5.53.0 to 5.53.6 in /src/ifctester/webapp
Bumps [svelte](https://github.com/sveltejs/svelte/tree/HEAD/packages/svelte) from 5.53.0 to 5.53.6.
- [Release notes](https://github.com/sveltejs/svelte/releases)
- [Changelog](https://github.com/sveltejs/svelte/blob/main/packages/svelte/CHANGELOG.md)
- [Commits](https://github.com/sveltejs/svelte/commits/svelte@5.53.6/packages/svelte)

---
updated-dependencies:
- dependency-name: svelte
  dependency-version: 5.53.6
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-03 18:44:47 +11:00
dependabot[bot] 4f6051cb0a Bump ruff from 0.15.2 to 0.15.4
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.15.2 to 0.15.4.
- [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.2...0.15.4)

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

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-03 18:44:40 +11:00
dependabot[bot] 5a27ec9814 Bump actions/upload-artifact from 6 to 7
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 6 to 7.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v6...v7)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-03 18:44:32 +11:00
dependabot[bot] 0ce60f5061 Bump actions/download-artifact from 7.0.0 to 8.0.0
Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 7.0.0 to 8.0.0.
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](https://github.com/actions/download-artifact/compare/v7.0.0...v8.0.0)

---
updated-dependencies:
- dependency-name: actions/download-artifact
  dependency-version: 8.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-03 18:44:25 +11:00
Thomas Krijnen 43146530b0 arrange polygons: Alternative (unused) perimiter approach; simpler topology handling; projection-based clean-up 2026-03-02 21:49:05 +01:00
Andrej730 db377e2178 Also bump binary version 2026-02-27 15:20:18 +05:00
Thomas Krijnen 5b0511379b IfcAxis1Placement.Axis is optional #7728 2026-02-27 11:06:45 +01:00
Andrej730 f8663b5e2b Bump ifcopenshell build
Just because it didn't happened for a while now and we need to test it.
2026-02-27 14:52:56 +05:00
Andrej730 92c979fbbf black . 2026-02-27 14:52:55 +05:00
Andrej730 8834a51122 format cmake files 2026-02-27 14:52:55 +05:00
Andrej730 1c5b825d8e build-all-win - fix missing compression for Python zip archives
Same as 5ebd425, should resolve https://github.com/ifcopenshell/ifcopenshell/issues/7404
2026-02-27 12:09:34 +05:00
dependabot[bot] 58c69f9d35 Bump ruff from 0.15.1 to 0.15.2
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.15.1 to 0.15.2.
- [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.1...0.15.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-26 13:15:49 +01:00
dependabot[bot] 198e111a92 Bump gersemi from 0.25.4 to 0.26.0
Bumps [gersemi](https://github.com/BlankSpruce/gersemi) from 0.25.4 to 0.26.0.
- [Release notes](https://github.com/BlankSpruce/gersemi/releases)
- [Changelog](https://github.com/BlankSpruce/gersemi/blob/master/CHANGELOG.md)
- [Commits](https://github.com/BlankSpruce/gersemi/compare/0.25.4...0.26.0)

---
updated-dependencies:
- dependency-name: gersemi
  dependency-version: 0.26.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-26 13:15:39 +01:00
dependabot[bot] 35886c9f72 Bump svelte from 5.33.10 to 5.53.0 in /src/ifctester/webapp
Bumps [svelte](https://github.com/sveltejs/svelte/tree/HEAD/packages/svelte) from 5.33.10 to 5.53.0.
- [Release notes](https://github.com/sveltejs/svelte/releases)
- [Changelog](https://github.com/sveltejs/svelte/blob/main/packages/svelte/CHANGELOG.md)
- [Commits](https://github.com/sveltejs/svelte/commits/svelte@5.53.0/packages/svelte)

---
updated-dependencies:
- dependency-name: svelte
  dependency-version: 5.53.0
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-26 13:14:38 +01:00
dependabot[bot] 097c8af7c7 Bump rollup from 4.41.1 to 4.59.0 in /src/ifctester/webapp
Bumps [rollup](https://github.com/rollup/rollup) from 4.41.1 to 4.59.0.
- [Release notes](https://github.com/rollup/rollup/releases)
- [Changelog](https://github.com/rollup/rollup/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rollup/rollup/compare/v4.41.1...v4.59.0)

---
updated-dependencies:
- dependency-name: rollup
  dependency-version: 4.59.0
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-26 13:14:21 +01:00
Andrej730 cfea3de552 cmake - fix msvc warning on linking without /ltcg flag
Linking flags were missing for `MODULE` type libraries, example warning: `IfcPythonPYTHON_wrap.obj : MSIL .netmodule or module compiled with /GL found; restarting link with /LTCG; add /LTCG to the link command line to improve linker performance`
2026-02-26 17:12:55 +05:00
Andrej730 5b86eedb26 cmake - fix ifc geom mapping not linking against IfcGeom library 2026-02-26 17:12:55 +05:00
Andrej730 fc13bcd055 bump ccache-action 2026-02-26 17:12:55 +05:00
Andrej730 be4806471d cache_dependencies - use tar instead of tarfile for archiving 2026-02-26 17:12:55 +05:00
Andrej730 7909997d42 build workflows - reuse cache_dependencies.py 2026-02-26 17:12:54 +05:00
Andrej730 00cd0b76f9 .gersemirc - search src for definitions
To fix errors when parsing custom macro from `src\examples\CMakeLists.txt`, see https://github.com/BlankSpruce/gersemi/issues/105
2026-02-26 17:12:54 +05:00
Andrej730 aa7710dd74 cache_dependencies.py - note expected cwd 2026-02-26 17:12:54 +05:00
Andrej730 fc7d15324f build-all - don't use main repo pyproject.toml for wasm builds 2026-02-26 17:12:54 +05:00
Andrej730 f8f4725054 build-all - remove wasm cxx flags workaround
As issue is now fixed upstream (https://github.com/pyodide/pyodide-build/issues/251)
2026-02-26 17:12:54 +05:00
Andrej730 333b6210a4 black . 2026-02-26 17:12:52 +05:00
Andrej730 ff3933a117 Remove some unused imports 2026-02-26 17:12:46 +05:00
Andrej730 34ffaea2c9 cmake - link serializers against IfcGeom to fix wasm build
jsonserializer is using ifcgeom and also eigen3
2026-02-26 17:12:45 +05:00
Andrej730 526b9537a9 build_pyodide.sh - allow executing multiple times 2026-02-26 17:12:45 +05:00
Andrej730 fb1c9eb7e3 build-all - fix missing f-string 2026-02-26 17:12:45 +05:00
Andrej730 a61d5a12fb build-all - use cmake to build swig
To keep it in sync with Windows build. Also Removed pcre2 dependency as apparently it's not required - we were not using it on Windows.
2026-02-26 17:12:45 +05:00
Andrej730 e54d16ef57 build_osx - ensure we use bison from brew instead of the default one 2026-02-26 17:12:45 +05:00
Andrej730 4591b6d926 cmake - ignore rocksdb shared library
If makes code target it by default if it's available, leading to errors below, since we don't really support using shared rocksdb. See some more details in the code comment.

IfcPythonPYTHON_wrap.cxx.obj : error LNK2001: unresolved external symbol "public: __cdecl rocksdb::Cleanable::~Cleanable(void)" (??1Cleanable@rocksdb@@QEAA@XZ)
IfcPythonPYTHON_wrap.cxx.obj : error LNK2001: unresolved external symbol "public: __cdecl rocksdb::Cleanable::Cleanable(void)" (??0Cleanable@rocksdb@@QEAA@XZ)
IfcPythonPYTHON_wrap.cxx.obj : error LNK2001: unresolved external symbol "public: class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __cdecl rocksdb::Slice::ToString(bool)const " (?ToString@Slice@rocksdb@@QEBA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@_N@Z)
IfcParse.lib(IfcFile.cpp.obj) : error LNK2001: unresolved external symbol "const rocksdb::WriteBatch::`vftable'" (??_7WriteBatch@rocksdb@@6B@)
IfcParse.lib(IfcFile.cpp.obj) : error LNK2001: unresolved external symbol "public: virtual __cdecl rocksdb::WriteBatch::~WriteBatch(void)" (??1WriteBatch@rocksdb@@UEAA@XZ)
IfcParse.lib(IfcFile.cpp.obj) : error LNK2001: unresolved external symbol "public: __cdecl rocksdb::WriteBatch::WriteBatch(unsigned __int64,unsigned __int64,unsigned __int64,unsigned __int64)" (??0WriteBatch@rocksdb@@QEAA@_K000@Z)
IfcParse.lib(IfcFile.cpp.obj) : error LNK2001: unresolved external symbol "public: __cdecl rocksdb::ColumnFamilyOptions::ColumnFamilyOptions(void)" (??0ColumnFamilyOptions@rocksdb@@QEAA@XZ)
IfcParse.lib(IfcFile.cpp.obj) : error LNK2001: unresolved external symbol "protected: virtual class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __cdecl rocksdb::Configurable::GetOptionName(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &)const " (?GetOptionName@Configurable@rocksdb@@MEBA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@AEBV34@@Z)
IfcParse.lib(IfcFile.cpp.obj) : error LNK2001: unresolved external symbol "protected: virtual class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __cdecl rocksdb::Configurable::SerializeOptions(struct rocksdb::ConfigOptions const &,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &)const " (?SerializeOptions@Configurable@rocksdb@@MEBA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@AEBUConfigOptions@2@AEBV34@@Z)
IfcParse.lib(IfcFile.cpp.obj) : error LNK2001: unresolved external symbol "protected: virtual bool __cdecl rocksdb::Configurable::OptionsAreEqual(struct rocksdb::ConfigOptions const &,class rocksdb::OptionTypeInfo const &,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &,void const * const,void const * const,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > *)const " (?OptionsAreEqual@Configurable@rocksdb@@MEBA_NAEBUConfigOptions@2@AEBVOptionTypeInfo@2@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QEBX3PEAV56@@Z)
IfcParse.lib(IfcFile.cpp.obj) : error LNK2001: unresolved external symbol "protected: virtual class rocksdb::Status __cdecl rocksdb::Configurable::ParseOption(struct rocksdb::ConfigOptions const &,class rocksdb::OptionTypeInfo const &,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &,void *)" (?ParseOption@Configurable@rocksdb@@MEAA?AVStatus@2@AEBUConfigOptions@2@AEBVOptionTypeInfo@2@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@2PEAX@Z)
IfcParse.lib(IfcFile.cpp.obj) : error LNK2001: unresolved external symbol "protected: virtual class rocksdb::Status __cdecl rocksdb::Configurable::ConfigureOptions(struct rocksdb::ConfigOptions const &,class std::unordered_map<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,struct std::hash<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >,struct std::equal_to<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >,class std::allocator<struct std::pair<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const ,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > > > > const &,class std::unordered_map<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,struct std::hash<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >,struct std::equal_to<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >,class std::allocator<struct std::pair<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const ,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > > > > *)" (?ConfigureOptions@Configurable@rocksdb@@MEAA?AVStatus@2@AEBUConfigOptions@2@AEBV?$unordered_map@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V12@U?$hash@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@2@U?$equal_to@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@2@V?$allocator@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V12@@std@@@2@@std@@PEAV56@@Z)
IfcParse.lib(IfcFile.cpp.obj) : error LNK2001: unresolved external symbol "protected: virtual class rocksdb::Status __cdecl rocksdb::Configurable::ParseStringOptions(struct rocksdb::ConfigOptions const &,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &)" (?ParseStringOptions@Configurable@rocksdb@@MEAA?AVStatus@2@AEBUConfigOptions@2@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z)
IfcParse.lib(IfcFile.cpp.obj) : error LNK2001: unresolved external symbol "protected: virtual void const * __cdecl rocksdb::Configurable::GetOptionsPtr(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &)const " (?GetOptionsPtr@Configurable@rocksdb@@MEBAPEBXAEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z)
IfcParse.lib(IfcFile.cpp.obj) : error LNK2001: unresolved external symbol "public: virtual class rocksdb::Status __cdecl rocksdb::Configurable::ValidateOptions(struct rocksdb::DBOptions const &,struct rocksdb::ColumnFamilyOptions const &)const " (?ValidateOptions@Configurable@rocksdb@@UEBA?AVStatus@2@AEBUDBOptions@2@AEBUColumnFamilyOptions@2@@Z)
IfcParse.lib(IfcFile.cpp.obj) : error LNK2001: unresolved external symbol "public: virtual class rocksdb::Status __cdecl rocksdb::Configurable::PrepareOptions(struct rocksdb::ConfigOptions const &)" (?PrepareOptions@Configurable@rocksdb@@UEAA?AVStatus@2@AEBUConfigOptions@2@@Z)
IfcParse.lib(IfcFile.cpp.obj) : error LNK2001: unresolved external symbol "public: virtual bool __cdecl rocksdb::Configurable::AreEquivalent(struct rocksdb::ConfigOptions const &,class rocksdb::Configurable const *,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > *)const " (?AreEquivalent@Configurable@rocksdb@@UEBA_NAEBUConfigOptions@2@PEBV12@PEAV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z)
IfcParse.lib(IfcFile.cpp.obj) : error LNK2001: unresolved external symbol "public: virtual class rocksdb::Status __cdecl rocksdb::Configurable::GetOption(struct rocksdb::ConfigOptions const &,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > *)const " (?GetOption@Configurable@rocksdb@@UEBA?AVStatus@2@AEBUConfigOptions@2@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@PEAV56@@Z)
IfcParse.lib(IfcFile.cpp.obj) : error LNK2001: unresolved external symbol "class rocksdb::TableFactory * __cdecl rocksdb::NewBlockBasedTableFactory(struct rocksdb::BlockBasedTableOptions const &)" (?NewBlockBasedTableFactory@rocksdb@@YAPEAVTableFactory@1@AEBUBlockBasedTableOptions@1@@Z)
IfcParse.lib(IfcFile.cpp.obj) : error LNK2001: unresolved external symbol "public: class std::shared_ptr<class rocksdb::Cache> __cdecl rocksdb::LRUCacheOptions::MakeSharedCache(void)const " (?MakeSharedCache@LRUCacheOptions@rocksdb@@QEBA?AV?$shared_ptr@VCache@rocksdb@@@std@@XZ)
IfcParse.lib(IfcFile.cpp.obj) : error LNK2001: unresolved external symbol "public: static class rocksdb::Status __cdecl rocksdb::DB::OpenForReadOnly(struct rocksdb::Options const &,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &,class std::unique_ptr<class rocksdb::DB,struct std::default_delete<class rocksdb::DB> > *,bool)" (?OpenForReadOnly@DB@rocksdb@@SA?AVStatus@2@AEBUOptions@2@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@PEAV?$unique_ptr@VDB@rocksdb@@U?$default_delete@VDB@rocksdb@@@std@@@6@_N@Z)
IfcParse.lib(IfcFile.cpp.obj) : error LNK2001: unresolved external symbol "public: static class rocksdb::Status __cdecl rocksdb::DB::Open(struct rocksdb::Options const &,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &,class std::unique_ptr<class rocksdb::DB,struct std::default_delete<class rocksdb::DB> > *)" (?Open@DB@rocksdb@@SA?AVStatus@2@AEBUOptions@2@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@PEAV?$unique_ptr@VDB@rocksdb@@U?$default_delete@VDB@rocksdb@@@std@@@6@@Z)
IfcParse.lib(IfcFile.cpp.obj) : error LNK2001: unresolved external symbol "class std::vector<enum rocksdb::CompressionType,class std::allocator<enum rocksdb::CompressionType> > const & __cdecl rocksdb::GetSupportedCompressions(void)" (?GetSupportedCompressions@rocksdb@@YAAEBV?$vector@W4CompressionType@rocksdb@@V?$allocator@W4CompressionType@rocksdb@@@std@@@std@@XZ)
IfcParse.lib(IfcFile.cpp.obj) : error LNK2001: unresolved external symbol "public: virtual bool __cdecl rocksdb::MergeOperator::PartialMergeMulti(class rocksdb::Slice const &,class std::deque<class rocksdb::Slice,class std::allocator<class rocksdb::Slice> > const &,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > *,class rocksdb::Logger *)const " (?PartialMergeMulti@MergeOperator@rocksdb@@UEBA_NAEBVSlice@2@AEBV?$deque@VSlice@rocksdb@@V?$allocator@VSlice@rocksdb@@@std@@@std@@PEAV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@5@PEAVLogger@2@@Z)
IfcParse.lib(IfcFile.cpp.obj) : error LNK2001: unresolved external symbol "public: virtual bool __cdecl rocksdb::MergeOperator::FullMergeV3(struct rocksdb::MergeOperator::MergeOperationInputV3 const &,struct rocksdb::MergeOperator::MergeOperationOutputV3 *)const " (?FullMergeV3@MergeOperator@rocksdb@@UEBA_NAEBUMergeOperationInputV3@12@PEAUMergeOperationOutputV3@12@@Z)
IfcParse.lib(IfcFile.cpp.obj) : error LNK2001: unresolved external symbol "public: virtual bool __cdecl rocksdb::MergeOperator::FullMergeV2(struct rocksdb::MergeOperator::MergeOperationInput const &,struct rocksdb::MergeOperator::MergeOperationOutput *)const " (?FullMergeV2@MergeOperator@rocksdb@@UEBA_NAEBUMergeOperationInput@12@PEAUMergeOperationOutput@12@@Z)
IfcParse.lib(IfcFile.cpp.obj) : error LNK2001: unresolved external symbol "protected: virtual class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __cdecl rocksdb::Customizable::SerializeOptions(struct rocksdb::ConfigOptions const &,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &)const " (?SerializeOptions@Customizable@rocksdb@@MEBA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@AEBUConfigOptions@2@AEBV34@@Z)
IfcParse.lib(IfcFile.cpp.obj) : error LNK2001: unresolved external symbol "protected: virtual class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __cdecl rocksdb::Customizable::GetOptionName(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &)const " (?GetOptionName@Customizable@rocksdb@@MEBA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@AEBV34@@Z)
IfcParse.lib(IfcFile.cpp.obj) : error LNK2001: unresolved external symbol "public: virtual class rocksdb::Status __cdecl rocksdb::Customizable::GetOption(struct rocksdb::ConfigOptions const &,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > *)const " (?GetOption@Customizable@rocksdb@@UEBA?AVStatus@2@AEBUConfigOptions@2@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@PEAV56@@Z)
IfcParse.lib(IfcFile.cpp.obj) : error LNK2001: unresolved external symbol "public: virtual bool __cdecl rocksdb::Customizable::AreEquivalent(struct rocksdb::ConfigOptions const &,class rocksdb::Configurable const *,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > *)const " (?AreEquivalent@Customizable@rocksdb@@UEBA_NAEBUConfigOptions@2@PEBVConfigurable@2@PEAV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z)
IfcParse.lib(IfcFile.cpp.obj) : error LNK2001: unresolved external symbol "public: __cdecl rocksdb::DBOptions::DBOptions(void)" (??0DBOptions@rocksdb@@QEAA@XZ)
IfcParse.lib(IfcFile.cpp.obj) : error LNK2001: unresolved external symbol "private: virtual bool __cdecl rocksdb::AssociativeMergeOperator::PartialMerge(class rocksdb::Slice const &,class rocksdb::Slice const &,class rocksdb::Slice const &,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > *,class rocksdb::Logger *)const " (?PartialMerge@AssociativeMergeOperator@rocksdb@@EEBA_NAEBVSlice@2@00PEAV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@PEAVLogger@2@@Z)
IfcParse.lib(IfcFile.cpp.obj) : error LNK2001: unresolved external symbol "private: virtual bool __cdecl rocksdb::AssociativeMergeOperator::FullMergeV2(struct rocksdb::MergeOperator::MergeOperationInput const &,struct rocksdb::MergeOperator::MergeOperationOutput *)const " (?FullMergeV2@AssociativeMergeOperator@rocksdb@@EEBA_NAEBUMergeOperationInput@MergeOperator@2@PEAUMergeOperationOutput@42@@Z)
IfcParse.lib(IfcFile.cpp.obj) : error LNK2001: unresolved external symbol "bool const rocksdb::kDefaultToAdaptiveMutex" (?kDefaultToAdaptiveMutex@rocksdb@@3_NB)
ifcwrap\_ifcopenshell_wrapper.cp311-win_amd64.pyd : fatal error LNK1120: 34 unresolved externals

Or on Unix:
/usr/bin/ld: ../ifcparse/libIfcParse.a(IfcEntityInstanceData.cpp.o): in function `rocksdb::PinnableSlice::PinnableSlice(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*)':
/home/andrej/ifcopenshell/build/Linux/x86_64/install/rocksdb-9.11.2/include/rocksdb/slice.h:141: undefined reference to `rocksdb::Cleanable::Cleanable()'
/usr/bin/ld: ../ifcparse/libIfcParse.a(IfcEntityInstanceData.cpp.o): in function `rocksdb::PinnableSlice::~PinnableSlice()':
/home/andrej/ifcopenshell/build/Linux/x86_64/install/rocksdb-9.11.2/include/rocksdb/slice.h:138: undefined reference to `rocksdb::Cleanable::~Cleanable()'
/usr/bin/ld: /home/andrej/ifcopenshell/build/Linux/x86_64/install/rocksdb-9.11.2/include/rocksdb/slice.h:138: undefined reference to `rocksdb::Cleanable::~Cleanable()'
/usr/bin/ld: ../ifcparse/libIfcParse.a(IfcFile.cpp.o): in function `rocksdb::Configurable::~Configurable()':
/home/andrej/ifcopenshell/build/Linux/x86_64/install/rocksdb-9.11.2/include/rocksdb/configurable.h:59: undefined reference to `vtable for rocksdb::Configurable'
/usr/bin/ld: /home/andrej/ifcopenshell/build/Linux/x86_64/install/rocksdb-9.11.2/include/rocksdb/configurable.h:59: undefined reference to `vtable for rocksdb::Configurable'
/usr/bin/ld: /home/andrej/ifcopenshell/build/Linux/x86_64/install/rocksdb-9.11.2/include/rocksdb/configurable.h:59: undefined reference to `vtable for rocksdb::Configurable'
/usr/bin/ld: ../ifcparse/libIfcParse.a(IfcFile.cpp.o): in function `rocksdb::Customizable::GetOptionsPtr(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) const':
/home/andrej/ifcopenshell/build/Linux/x86_64/install/rocksdb-9.11.2/include/rocksdb/customizable.h:105: undefined reference to `rocksdb::Configurable::GetOptionsPtr(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) const'
/usr/bin/ld: /home/andrej/ifcopenshell/build/Linux/x86_64/install/rocksdb-9.11.2/include/rocksdb/customizable.h:105: undefined reference to `rocksdb::Configurable::GetOptionsPtr(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) const'
/usr/bin/ld: /home/andrej/ifcopenshell/build/Linux/x86_64/install/rocksdb-9.11.2/include/rocksdb/customizable.h:105: undefined reference to `rocksdb::Configurable::GetOptionsPtr(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) const'
/usr/bin/ld: ../ifcparse/libIfcParse.a(IfcFile.cpp.o): in function `rocksdb::Options::Options()':
/home/andrej/ifcopenshell/build/Linux/x86_64/install/rocksdb-9.11.2/include/rocksdb/options.h:1628: undefined reference to `rocksdb::DBOptions::DBOptions()'
/usr/bin/ld: /home/andrej/ifcopenshell/build/Linux/x86_64/install/rocksdb-9.11.2/include/rocksdb/options.h:1628: undefined reference to `rocksdb::ColumnFamilyOptions::ColumnFamilyOptions()'
/usr/bin/ld: ../ifcparse/libIfcParse.a(IfcFile.cpp.o): in function `IfcParse::impl::rocks_db_file_storage::rocks_db_file_storage(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, IfcParse::IfcFile*, bool)':
/home/andrej/ifcopenshell/src/ifcparse/IfcFile.cpp:421: undefined reference to `rocksdb::GetSupportedCompressions()'
/usr/bin/ld: ../ifcparse/libIfcParse.a(IfcFile.cpp.o): in function `init_db':
/home/andrej/ifcopenshell/src/ifcparse/IfcFile.cpp:440: undefined reference to `rocksdb::kDefaultToAdaptiveMutex'
/usr/bin/ld: ../ifcparse/libIfcParse.a(IfcFile.cpp.o): in function `rocksdb::NewLRUCache(unsigned long, int, bool, double, std::shared_ptr<rocksdb::MemoryAllocator>, bool, rocksdb::CacheMetadataChargePolicy, double)':
/home/andrej/ifcopenshell/build/Linux/x86_64/install/rocksdb-9.11.2/include/rocksdb/cache.h:282: undefined reference to `rocksdb::LRUCacheOptions::MakeSharedCache() const'
/usr/bin/ld: ../ifcparse/libIfcParse.a(IfcFile.cpp.o): in function `init_db':
/home/andrej/ifcopenshell/src/ifcparse/IfcFile.cpp:445: undefined reference to `rocksdb::NewBlockBasedTableFactory(rocksdb::BlockBasedTableOptions const&)'
/usr/bin/ld: ../ifcparse/libIfcParse.a(IfcFile.cpp.o): in function `rocksdb::DB::OpenForReadOnly(rocksdb::Options const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, rocksdb::DB**, bool)':
/home/andrej/ifcopenshell/build/Linux/x86_64/install/rocksdb-9.11.2/include/rocksdb/db.h:243: undefined reference to `rocksdb::DB::OpenForReadOnly(rocksdb::Options const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::unique_ptr<rocksdb::DB, std::default_delete<rocksdb::DB> >*, bool)'
/usr/bin/ld: ../ifcparse/libIfcParse.a(IfcFile.cpp.o): in function `rocksdb::DB::Open(rocksdb::Options const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, rocksdb::DB**)':
/home/andrej/ifcopenshell/build/Linux/x86_64/install/rocksdb-9.11.2/include/rocksdb/db.h:187: undefined reference to `rocksdb::DB::Open(rocksdb::Options const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::unique_ptr<rocksdb::DB, std::default_delete<rocksdb::DB> >*)'
/usr/bin/ld: ../ifcparse/libIfcParse.a(IfcFile.cpp.o): in function `rocksdb_set_view<unsigned long>::iterator::extract_current_value() const':
/home/andrej/ifcopenshell/src/ifcparse/rocksdb_set_view.h:70: undefined reference to `rocksdb::Slice::ToString[abi:cxx11](bool) const'
/usr/bin/ld: ../ifcparse/libIfcParse.a(IfcFile.cpp.o): in function `rocksdb::PinnableSlice::~PinnableSlice()':
/home/andrej/ifcopenshell/build/Linux/x86_64/install/rocksdb-9.11.2/include/rocksdb/slice.h:138: undefined reference to `rocksdb::Cleanable::~Cleanable()'
/usr/bin/ld: ../ifcparse/libIfcParse.a(IfcFile.cpp.o): in function `rocksdb::PinnableSlice::PinnableSlice(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*)':
/home/andrej/ifcopenshell/build/Linux/x86_64/install/rocksdb-9.11.2/include/rocksdb/slice.h:141: undefined reference to `rocksdb::Cleanable::Cleanable()'
/usr/bin/ld: ../ifcparse/libIfcParse.a(IfcFile.cpp.o): in function `rocksdb::PinnableSlice::~PinnableSlice()':
/home/andrej/ifcopenshell/build/Linux/x86_64/install/rocksdb-9.11.2/include/rocksdb/slice.h:138: undefined reference to `rocksdb::Cleanable::~Cleanable()'
/usr/bin/ld: ../ifcparse/libIfcParse.a(IfcFile.cpp.o): in function `rocksdb_set_view<unsigned long>::iterator::iterator(rocksdb_set_view<unsigned long>::iterator const&)':
/home/andrej/ifcopenshell/src/ifcparse/rocksdb_set_view.h:103: undefined reference to `rocksdb::Slice::ToString[abi:cxx11](bool) const'
/usr/bin/ld: /home/andrej/ifcopenshell/src/ifcparse/rocksdb_set_view.h:106: undefined reference to `rocksdb::Slice::ToString[abi:cxx11](bool) const'
/usr/bin/ld: ../ifcparse/libIfcParse.a(IfcFile.cpp.o): in function `IfcParse::impl::rocks_db_file_storage::process_deletion_inverse(IfcUtil::IfcBaseClass*)':
/home/andrej/ifcopenshell/src/ifcparse/IfcFile.cpp:526: undefined reference to `rocksdb::WriteBatch::~WriteBatch()'
/usr/bin/ld: ../ifcparse/libIfcParse.a(IfcFile.cpp.o): in function `rocksdb::WriteBatch::WriteBatch(unsigned long, unsigned long)':
/home/andrej/ifcopenshell/build/Linux/x86_64/install/rocksdb-9.11.2/include/rocksdb/write_batch.h:67: undefined reference to `rocksdb::WriteBatch::WriteBatch(unsigned long, unsigned long, unsigned long, unsigned long)'
/usr/bin/ld: ../ifcparse/libIfcParse.a(IfcFile.cpp.o): in function `rocksdb::WriteBatch::DeleteRange(rocksdb::Slice const&, rocksdb::Slice const&)':
/home/andrej/ifcopenshell/build/Linux/x86_64/install/rocksdb-9.11.2/include/rocksdb/write_batch.h:164: undefined reference to `rocksdb::WriteBatch::DeleteRange(rocksdb::ColumnFamilyHandle*, rocksdb::Slice const&, rocksdb::Slice const&)'
/usr/bin/ld: ../ifcparse/libIfcParse.a(IfcFile.cpp.o): in function `IfcParse::impl::rocks_db_file_storage::process_deletion_inverse(IfcUtil::IfcBaseClass*)':
/home/andrej/ifcopenshell/src/ifcparse/IfcFile.cpp:526: undefined reference to `rocksdb::WriteBatch::~WriteBatch()'
/usr/bin/ld: /home/andrej/ifcopenshell/src/ifcparse/IfcFile.cpp:547: undefined reference to `rocksdb::Slice::ToString[abi:cxx11](bool) const'
/usr/bin/ld: /home/andrej/ifcopenshell/src/ifcparse/IfcFile.cpp:526: undefined reference to `rocksdb::WriteBatch::~WriteBatch()'
/usr/bin/ld: ../ifcparse/libIfcParse.a(IfcFile.cpp.o):(.data.rel.ro._ZTIN12_GLOBAL__N_126ConcatenateIdMergeOperatorE+0x10): undefined reference to `typeinfo for rocksdb::AssociativeMergeOperator'
/usr/bin/ld: ../ifcparse/libIfcParse.a(IfcFile.cpp.o):(.data.rel.ro._ZTVN12_GLOBAL__N_126ConcatenateIdMergeOperatorE+0x20): undefined reference to `rocksdb::Customizable::GetOption(rocksdb::ConfigOptions const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*) const'
/usr/bin/ld: ../ifcparse/libIfcParse.a(IfcFile.cpp.o):(.data.rel.ro._ZTVN12_GLOBAL__N_126ConcatenateIdMergeOperatorE+0x28): undefined reference to `rocksdb::Customizable::AreEquivalent(rocksdb::ConfigOptions const&, rocksdb::Configurable const*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*) const'
/usr/bin/ld: ../ifcparse/libIfcParse.a(IfcFile.cpp.o):(.data.rel.ro._ZTVN12_GLOBAL__N_126ConcatenateIdMergeOperatorE+0x38): undefined reference to `rocksdb::Configurable::PrepareOptions(rocksdb::ConfigOptions const&)'
/usr/bin/ld: ../ifcparse/libIfcParse.a(IfcFile.cpp.o):(.data.rel.ro._ZTVN12_GLOBAL__N_126ConcatenateIdMergeOperatorE+0x40): undefined reference to `rocksdb::Configurable::ValidateOptions(rocksdb::DBOptions const&, rocksdb::ColumnFamilyOptions const&) const'
/usr/bin/ld: ../ifcparse/libIfcParse.a(IfcFile.cpp.o):(.data.rel.ro._ZTVN12_GLOBAL__N_126ConcatenateIdMergeOperatorE+0x50): undefined reference to `rocksdb::Configurable::ParseStringOptions(rocksdb::ConfigOptions const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'
/usr/bin/ld: ../ifcparse/libIfcParse.a(IfcFile.cpp.o):(.data.rel.ro._ZTVN12_GLOBAL__N_126ConcatenateIdMergeOperatorE+0x58): undefined reference to `rocksdb::Configurable::ConfigureOptions(rocksdb::ConfigOptions const&, std::unordered_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > > const&, std::unordered_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >*)'
/usr/bin/ld: ../ifcparse/libIfcParse.a(IfcFile.cpp.o):(.data.rel.ro._ZTVN12_GLOBAL__N_126ConcatenateIdMergeOperatorE+0x60): undefined reference to `rocksdb::Configurable::ParseOption(rocksdb::ConfigOptions const&, rocksdb::OptionTypeInfo const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, void*)'
/usr/bin/ld: ../ifcparse/libIfcParse.a(IfcFile.cpp.o):(.data.rel.ro._ZTVN12_GLOBAL__N_126ConcatenateIdMergeOperatorE+0x68): undefined reference to `rocksdb::Configurable::OptionsAreEqual(rocksdb::ConfigOptions const&, rocksdb::OptionTypeInfo const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, void const*, void const*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*) const'
/usr/bin/ld: ../ifcparse/libIfcParse.a(IfcFile.cpp.o):(.data.rel.ro._ZTVN12_GLOBAL__N_126ConcatenateIdMergeOperatorE+0x70): undefined reference to `rocksdb::Customizable::SerializeOptions(rocksdb::ConfigOptions const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) const'
/usr/bin/ld: ../ifcparse/libIfcParse.a(IfcFile.cpp.o):(.data.rel.ro._ZTVN12_GLOBAL__N_126ConcatenateIdMergeOperatorE+0x78): undefined reference to `rocksdb::Customizable::GetOptionName(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) const'
/usr/bin/ld: ../ifcparse/libIfcParse.a(IfcFile.cpp.o):(.data.rel.ro._ZTVN12_GLOBAL__N_126ConcatenateIdMergeOperatorE+0xb8): undefined reference to `rocksdb::MergeOperator::FullMergeV3(rocksdb::MergeOperator::MergeOperationInputV3 const&, rocksdb::MergeOperator::MergeOperationOutputV3*) const'
/usr/bin/ld: ../ifcparse/libIfcParse.a(IfcFile.cpp.o):(.data.rel.ro._ZTVN12_GLOBAL__N_126ConcatenateIdMergeOperatorE+0xc0): undefined reference to `rocksdb::AssociativeMergeOperator::PartialMerge(rocksdb::Slice const&, rocksdb::Slice const&, rocksdb::Slice const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*, rocksdb::Logger*) const'
/usr/bin/ld: ../ifcparse/libIfcParse.a(IfcFile.cpp.o):(.data.rel.ro._ZTVN12_GLOBAL__N_126ConcatenateIdMergeOperatorE+0xc8): undefined reference to `rocksdb::MergeOperator::PartialMergeMulti(rocksdb::Slice const&, std::deque<rocksdb::Slice, std::allocator<rocksdb::Slice> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*, rocksdb::Logger*) const'
/usr/bin/ld: ../ifcparse/libIfcParse.a(IfcParse.cpp.o): in function `rocksdb_map_adapter<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, unsigned long, DefaultCodec<unsigned long> >::iterator::operator*() const':
/home/andrej/ifcopenshell/src/ifcparse/rocksdb_map_adapter.h:261: undefined reference to `rocksdb::Slice::ToString[abi:cxx11](bool) const'
/usr/bin/ld: /home/andrej/ifcopenshell/src/ifcparse/rocksdb_map_adapter.h:263: undefined reference to `rocksdb::Slice::ToString[abi:cxx11](bool) const'
/usr/bin/ld: ../ifcparse/libIfcParse.a(IfcParse.cpp.o): in function `rocksdb_map_adapter<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, unsigned long, DefaultCodec<unsigned long> >::iterator::operator==(rocksdb_map_adapter<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, unsigned long, DefaultCodec<unsigned long> >::iterator const&) const':
/home/andrej/ifcopenshell/src/ifcparse/rocksdb_map_adapter.h:296: undefined reference to `rocksdb::Slice::ToString[abi:cxx11](bool) const'
/usr/bin/ld: /home/andrej/ifcopenshell/src/ifcparse/rocksdb_map_adapter.h:296: undefined reference to `rocksdb::Slice::ToString[abi:cxx11](bool) const'
/usr/bin/ld: ../ifcparse/libIfcParse.a(IfcParse.cpp.o): in function `rocksdb::PinnableSlice::~PinnableSlice()':
/home/andrej/ifcopenshell/build/Linux/x86_64/install/rocksdb-9.11.2/include/rocksdb/slice.h:138: undefined reference to `rocksdb::Cleanable::~Cleanable()'
/usr/bin/ld: ../ifcparse/libIfcParse.a(IfcParse.cpp.o): in function `rocksdb::PinnableSlice::PinnableSlice(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*)':
/home/andrej/ifcopenshell/build/Linux/x86_64/install/rocksdb-9.11.2/include/rocksdb/slice.h:141: undefined reference to `rocksdb::Cleanable::Cleanable()'
/usr/bin/ld: ../ifcparse/libIfcParse.a(IfcParse.cpp.o): in function `rocksdb::PinnableSlice::~PinnableSlice()':
/home/andrej/ifcopenshell/build/Linux/x86_64/install/rocksdb-9.11.2/include/rocksdb/slice.h:138: undefined reference to `rocksdb::Cleanable::~Cleanable()'
/usr/bin/ld: /home/andrej/ifcopenshell/build/Linux/x86_64/install/rocksdb-9.11.2/include/rocksdb/slice.h:138: undefined reference to `rocksdb::Cleanable::~Cleanable()'
/usr/bin/ld: ../ifcparse/libIfcParse.a(IfcParse.cpp.o): in function `rocksdb::PinnableSlice::PinnableSlice(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*)':
/home/andrej/ifcopenshell/build/Linux/x86_64/install/rocksdb-9.11.2/include/rocksdb/slice.h:141: undefined reference to `rocksdb::Cleanable::Cleanable()'
/usr/bin/ld: ../ifcparse/libIfcParse.a(IfcParse.cpp.o): in function `rocksdb::PinnableSlice::~PinnableSlice()':
/home/andrej/ifcopenshell/build/Linux/x86_64/install/rocksdb-9.11.2/include/rocksdb/slice.h:138: undefined reference to `rocksdb::Cleanable::~Cleanable()'
/usr/bin/ld: ../ifcparse/libIfcParse.a(IfcParse.cpp.o): in function `rocksdb_map_adapter<unsigned long, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, DefaultCodec<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::iterator::operator*() const':
/home/andrej/ifcopenshell/src/ifcparse/rocksdb_map_adapter.h:261: undefined reference to `rocksdb::Slice::ToString[abi:cxx11](bool) const'
/usr/bin/ld: /home/andrej/ifcopenshell/src/ifcparse/rocksdb_map_adapter.h:263: undefined reference to `rocksdb::Slice::ToString[abi:cxx11](bool) const'
/usr/bin/ld: ../ifcparse/libIfcParse.a(IfcParse.cpp.o): in function `rocksdb_map_adapter<unsigned long, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, DefaultCodec<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::find(unsigned long const&) const':
/home/andrej/ifcopenshell/src/ifcparse/rocksdb_map_adapter.h:327: undefined reference to `rocksdb::Slice::ToString[abi:cxx11](bool) const'
/usr/bin/ld: ../ifcparse/libIfcParse.a(IfcParse.cpp.o): in function `rocksdb_map_adapter<std::tuple<int, int, int>, std::vector<unsigned int, std::allocator<unsigned int> >, DefaultCodec<std::vector<unsigned int, std::allocator<unsigned int> > > >::find(std::tuple<int, int, int> const&) const':
/home/andrej/ifcopenshell/src/ifcparse/rocksdb_map_adapter.h:327: undefined reference to `rocksdb::Slice::ToString[abi:cxx11](bool) const'
/usr/bin/ld: ../ifcparse/libIfcParse.a(IfcParse.cpp.o): in function `rocksdb_map_adapter<std::tuple<int, int, int>, std::vector<unsigned int, std::allocator<unsigned int> >, DefaultCodec<std::vector<unsigned int, std::allocator<unsigned int> > > >::iterator::operator*() const':
/home/andrej/ifcopenshell/src/ifcparse/rocksdb_map_adapter.h:261: undefined reference to `rocksdb::Slice::ToString[abi:cxx11](bool) const'
/usr/bin/ld: ../ifcparse/libIfcParse.a(IfcParse.cpp.o):/home/andrej/ifcopenshell/src/ifcparse/rocksdb_map_adapter.h:263: more undefined references to `rocksdb::Slice::ToString[abi:cxx11](bool) const' follow
/usr/bin/ld: ../ifcparse/libIfcParse.a(IfcParse.cpp.o): in function `rocksdb::PinnableSlice::~PinnableSlice()':
/home/andrej/ifcopenshell/build/Linux/x86_64/install/rocksdb-9.11.2/include/rocksdb/slice.h:138: undefined reference to `rocksdb::Cleanable::~Cleanable()'
/usr/bin/ld: ../ifcparse/libIfcParse.a(IfcParse.cpp.o): in function `rocksdb::PinnableSlice::PinnableSlice(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*)':
/home/andrej/ifcopenshell/build/Linux/x86_64/install/rocksdb-9.11.2/include/rocksdb/slice.h:141: undefined reference to `rocksdb::Cleanable::Cleanable()'
/usr/bin/ld: ../ifcparse/libIfcParse.a(IfcParse.cpp.o): in function `rocksdb::PinnableSlice::~PinnableSlice()':
/home/andrej/ifcopenshell/build/Linux/x86_64/install/rocksdb-9.11.2/include/rocksdb/slice.h:138: undefined reference to `rocksdb::Cleanable::~Cleanable()'
/usr/bin/ld: ../ifcparse/libIfcParse.a(IfcParse.cpp.o): in function `rocksdb_map_adapter<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, unsigned long, DefaultCodec<unsigned long> >::find(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) const':
/home/andrej/ifcopenshell/src/ifcparse/rocksdb_map_adapter.h:327: undefined reference to `rocksdb::Slice::ToString[abi:cxx11](bool) const'
/usr/bin/ld: ../ifcparse/libIfcParse.a(IfcParse.cpp.o): in function `rocksdb_map_adapter<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, unsigned long, DefaultCodec<unsigned long> >::iterator::iterator(rocksdb_map_adapter<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, unsigned long, DefaultCodec<unsigned long> >::iterator const&)':
/home/andrej/ifcopenshell/src/ifcparse/rocksdb_map_adapter.h:230: undefined reference to `rocksdb::Slice::ToString[abi:cxx11](bool) const'
/usr/bin/ld: /home/andrej/ifcopenshell/src/ifcparse/rocksdb_map_adapter.h:233: undefined reference to `rocksdb::Slice::ToString[abi:cxx11](bool) const'
/usr/bin/ld: ../ifcparse/libIfcParse.a(IfcParse.cpp.o): in function `rocksdb::PinnableSlice::PinnableSlice(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*)':
/home/andrej/ifcopenshell/build/Linux/x86_64/install/rocksdb-9.11.2/include/rocksdb/slice.h:141: undefined reference to `rocksdb::Cleanable::Cleanable()'
/usr/bin/ld: ../ifcparse/libIfcParse.a(IfcParse.cpp.o): in function `rocksdb::PinnableSlice::~PinnableSlice()':
/home/andrej/ifcopenshell/build/Linux/x86_64/install/rocksdb-9.11.2/include/rocksdb/slice.h:138: undefined reference to `rocksdb::Cleanable::~Cleanable()'
/usr/bin/ld: /home/andrej/ifcopenshell/build/Linux/x86_64/install/rocksdb-9.11.2/include/rocksdb/slice.h:138: undefined reference to `rocksdb::Cleanable::~Cleanable()'
/usr/bin/ld: ../ifcparse/libIfcParse.a(IfcParse.cpp.o): in function `rocksdb_set_view<unsigned long>::iterator::operator==(rocksdb_set_view<unsigned long>::iterator const&) const':
/home/andrej/ifcopenshell/src/ifcparse/rocksdb_set_view.h:170: undefined reference to `rocksdb::Slice::ToString[abi:cxx11](bool) const'
/usr/bin/ld: /home/andrej/ifcopenshell/src/ifcparse/rocksdb_set_view.h:170: undefined reference to `rocksdb::Slice::ToString[abi:cxx11](bool) const'
collect2: error: ld returned 1 exit status
make[2]: *** [ifcconvert/CMakeFiles/IfcConvert.dir/build.make:236: ifcconvert/IfcConvert] Error 1
make[1]: *** [CMakeFiles/Makefile2:569: ifcconvert/CMakeFiles/IfcConvert.dir/all] Error 2
2026-02-26 17:12:44 +05:00
Andrej730 6492fdeb05 build-all - add zlib and openssl to RHEL packages 2026-02-26 17:12:44 +05:00
Andrej730 8eb0641e70 build-all - mention zlib requirement 2026-02-26 17:12:44 +05:00
Andrej730 6face696cb build-all - use cmake arg instead of a patch to disable ExpToCasExe 2026-02-26 17:12:42 +05:00
Andrej730 4c4eed5dd4 build_rocky - switch to rocky 9
As rocky 8 is not updating anymore for 2 years and we need some updated dependencies (e.g. `bison` 3.5+ for newer version of `swig`).
2026-02-26 17:01:56 +05:00
Andrej730 634600b65f FindOpenCASCADE - rescan dependencies for cmake config 2026-02-26 17:01:56 +05:00
Andrej730 d43b9ee353 build-all - ensure Python was built with openssl 2026-02-26 17:01:56 +05:00
Andrej730 5ea4290920 build-all - ensure bison is installed 2026-02-26 17:01:56 +05:00
Andrej730 c8ca904333 build-all - distinct command and path in logs 2026-02-26 17:01:56 +05:00
Andrej730 59c28b5ae6 build_rocky - use dnf instead of yum
It's using `dnf` either way, but just to make it more explicit.
2026-02-26 17:01:56 +05:00
Andrej730 c649a4b522 build-all - don't fail silently on missing Python dependencies 2026-02-26 17:01:55 +05:00
Andrej730 5ebd4256a1 build-all-win.py - fix missing compression
Resulting in larger zip files for builds, reported in 7404
2026-02-26 17:01:55 +05:00
Andrej730 3ec9d69556 build-deps - support building Boost for VS2026 2026-02-26 17:01:55 +05:00
Andrej730 54a6fb651e tool.ps1 - support commands with 0 args
No such commands atm though.
2026-02-26 17:01:55 +05:00
Andrej730 dcac336b98 tool.ps1 - refer to cecho.cmd directly, use return instead of exit 0
Which is useful when debugging and calling tools.ps1 directly - less thing to modify to make it work.
Also replaced `exit 0` with `return`, so it would be possible to reuse functions inside `tools.ps1`
2026-02-26 17:01:55 +05:00
Andrej730 88a5717295 build-deps.cmd - fix issue building opencollada in cmake 4 2026-02-26 17:01:55 +05:00
Andrej730 8bfceec1fd vs-cfg.cmd - document some output vars 2026-02-26 17:01:55 +05:00
Andrej730 3807479e42 build-deps - update occt config to support cmake 4
And also to make it work in sync with `build-all.py`.
2026-02-26 17:01:54 +05:00
Andrej730 aebcb676f2 windows - add occt patch to support cmake 4 2026-02-26 17:01:54 +05:00
Andrej730 ba5ea08aee Bump swig version to support cmake 4 2026-02-26 17:01:54 +05:00
Andrej730 d4ebf3f308 cmake - error if svgpp submodule is not initialized 2026-02-26 17:01:54 +05:00
Andrej730 d9e488d518 cmake format 2026-02-26 17:01:54 +05:00
Andrej730 1fb6227d13 build-deps - use other mpir fork to support VS 2026 2026-02-26 17:01:54 +05:00
Andrej730 0e90cd81b3 vs-cfg.cmd - add support for Visual Studio 18 2026 2026-02-26 17:01:53 +05:00
Andrej730 ac23c7a74b vs-cfg.cmd - more readable error on supported versions of VS 2026-02-26 17:01:51 +05:00
Andrej730 7322082a0d typing 2026-02-26 17:01:48 +05:00
Andrej730 0234809d0b Prefer direct api calls over tool.Ifc.run 2026-02-26 17:01:48 +05:00
Andrej730 38381f44b9 ci-bonsai-daily - generate timestamp once for all builds
To avoid running in a situation when some builds are using one tag and some are using another and then unstable repo script fails to find builds for some platforms.
2026-02-26 17:01:47 +05:00
Andrej730 83fed6257e run-cmake.bat - deduplicate cmake args code 2026-02-26 17:01:47 +05:00
Andrej730 40d43732ca build-deps - bump proj version to avoid errors in cmake 4+ 2026-02-26 17:01:47 +05:00
Andrej730 521c8eae0d run-cmake.bat - document USE_NINJA env var 2026-02-26 17:01:47 +05:00
Andrej730 5aa7ba6be6 IfcConvert - fix Windows builds stuck on 0.8.0 version 2026-02-26 17:01:47 +05:00
Thomas Krijnen e3464b395e --recursion-limit option in validate.py 2026-02-26 12:38:36 +01:00
Thomas Krijnen 9ab9da2ca8 Update black exclude dirs 2026-02-26 12:36:17 +01:00
Thomas Krijnen 077a0c3755 Run black on express/ 2026-02-26 12:36:01 +01:00
Thomas Krijnen 18527a78e1 rule_executor.py don't log RecursionError as error 2026-02-26 12:35:40 +01:00
falken10vdl 0be348707c Update scale_font_size method to accept a None parameter so it is cleaner the calls from the rest of the code base 2026-02-25 13:28:58 -03:00
falken10vdl 1b784e22af Add decorator font scale property addon setting 2026-02-25 13:28:58 -03:00
falken10vdl c0857c715a Refactor scale_font_size to improve DPI and pixel size handling for better font scaling 2026-02-25 13:28:58 -03:00
falken10vdl ecaea5f776 refactor scale_font_size as per developers feedback 2026-02-25 13:28:58 -03:00
falken10vdl dde6e2d62b black 2026-02-25 13:28:58 -03:00
falken10vdl 8df4b2cd56 Scale font size in PolylineDecorator and BoundingBoxDecorator based on Blender's UI preferences 2026-02-25 13:28:58 -03:00
Richard Brice ece7d6b97f Fixes example in documentation 2026-02-25 14:21:10 +01:00
Thomas Krijnen 2d7a556dd5 Fix sectioned solid cap #7674 2026-02-24 11:26:18 +01:00
Dion Moult dcc25038f9 Fix #7646. Bug with layer thumbnail orientation. 2026-02-24 10:03:33 +11:00
Dion Moult 0d382119dd Fix docs table for selector syntax 2026-02-24 09:53:57 +11:00
Dion Moult 41afaaec0d Revert "Fix #7681: Fix isolate_objects ignoring hide_select/hide_viewport (#7710)"
This reverts commit 7d8c7a2c3d.
2026-02-24 09:53:28 +11:00
Dion Moult f69ea82789 Revert "Fix #7646: Fix layer thumbnail orientation for IFC types"
This reverts commit 514cbb49cc.
2026-02-24 09:53:27 +11:00
Dion Moult 2f5c71588e Revert "Table was not rendering correctly."
This reverts commit 9ff4a7f0e0.
2026-02-24 09:53:24 +11:00
Ryan Schultz 7d8c7a2c3d Fix #7681: Fix isolate_objects ignoring hide_select/hide_viewport (#7710)
Objects with hide_select=True could not be selected during
isolation, causing hide_view_set to incorrectly hide them.
Objects with hide_viewport=True had their H-key hide state
modified as a side effect of hide_view_clear/hide_view_set.
Both are now left unaffected by bim.activate_drawing.

Generated with the assistance of an AI coding tool.
2026-02-23 07:09:18 -06:00
Ryan Schultz 514cbb49cc Fix #7646: Fix layer thumbnail orientation for IFC types
Use EPset_Parametric.LayerSetDirection exclusively to
determine horizontal vs vertical layer rendering in type
thumbnails, rather than hardcoding IfcSlabType checks.
Also fix line drawing to use the is_horizontal flag
consistently.

Generated with the assistance of an AI coding tool.
2026-02-22 17:46:10 -06:00
Ryan Schultz 9ff4a7f0e0 Table was not rendering correctly.
Fix Sphinx docs: replace csv-table with list-table for formatting functions

The documentation table of formatting/query functions was not rendering
because `.. csv-table::` requires strict RFC4180 CSV escaping. The table
contains nested quotes, inch marks (e.g. `3' - 0"`), backticks, and code
examples, which cause the CSV parser in docutils to treat rows as malformed
and drop the entire directive.

Replaced the directive with `.. list-table::`, which parses reStructuredText
instead of CSV and safely supports inline code, quotes, and multi-line cells.

Also moved the examples text outside the directive block and ensured a blank
line after the table so Sphinx does not interpret following paragraphs as
table rows.

No content changes — documentation now renders correctly.

Generated with the assistance of an AI coding tool.
2026-02-22 15:10:29 -06:00
dependabot[bot] 8afe05601e Bump tar from 7.5.7 to 7.5.9 in /src/ifctester/webapp
Bumps [tar](https://github.com/isaacs/node-tar) from 7.5.7 to 7.5.9.
- [Release notes](https://github.com/isaacs/node-tar/releases)
- [Changelog](https://github.com/isaacs/node-tar/blob/main/CHANGELOG.md)
- [Commits](https://github.com/isaacs/node-tar/compare/v7.5.7...v7.5.9)

---
updated-dependencies:
- dependency-name: tar
  dependency-version: 7.5.9
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-20 08:56:50 +11:00
falken10vdl 1751c36c67 AddReferenceImage: implement option to show texture in solid mode (#7689) 2026-02-19 21:02:57 +11:00
falken10vdl d4388ec76d AddReferenceImage: fix regression with IFC2X3 support, refactor to no longer depend on add_representation or update_representation, remove legacy style updating functionality
* Enhance AddReferenceImage operator to use file browser instead of independent popup dialogue

* Fix dimensions assertion in TestAddReferenceImage

* Remove error in return in _execute (it is not execute)

* Add  IFC2X3 support to AddReferenceImage

* Adde unit="LENGTH" to the x/y properties (every length dimension everywhere in the UI is in project length units. No need to say it explicitly)

* Manually create the texture always, not just for IFC2X3

* Add poll method to AddReferenceImage operator to check for loaded IFC project

* Refactor AddReferenceImage to add representation manually following pattern in root/operator.py's bim.add_element

* Improve File explorer options between new and select from existing project Ifc Reference Images

* Refactor get_existing_reference_images to use selector for filtering image annotations

* No extra args needed after should_add_representation is False

* Doing clean=True deletes everything

* Don't manually add geometry and materials, don't call bpy.ops. Only create IFC data, then use preexisting loading functions to create geometry.

* Black formatting, also now we can start to remove this operator as it becomes obsolete

* Consolidate duplicate UV generation into Loader.load_generated_uv_map

Replace 3 identical XY-UV baking blocks (create_object IMAGE,
bm_add_image_plane, ImageScalingTool) with a single reusable
classmethod in tool.Loader.

* Fix IFC4 texture display in Solid viewport Texture mode

IFC4 IfcTextureCoordinateGenerator Mode=COORD is used, load_texture_maps
falls back to load_generated_uv_map to bake XY-UV data onto the mesh.

* Fix IFC2X3 texture display

* This looks wrong

* Remove legacy override image feature, because we now have a proper styles and texture manager

* Remove legacy override existing image element, because we now have a dedicated styles texture manager

* Remove unnecessary roundtrip to bmesh and mesh

---------

Co-authored-by: Dion Moult <dion@thinkmoult.com>
2026-02-19 11:56:10 +11:00
falken10vdl 7141f2cf90 Fixes to PR7607 (Linked IFC Projects): Wireframe toggle. More permisive to get has_transformation = False. Show enable_editing_link if link is loaded 2026-02-19 10:53:01 +11:00
Sebastian Schilling 418d410b5c moved change of bsdd baseurl change to addon settings 2026-02-18 09:11:25 +11:00
Sebastian Schilling a5461c0748 buildingSMART Data Dictionary module: added textfield to change data dictionary url 2026-02-18 09:11:25 +11:00
Bruno Postle 291e815770 Add AGENTS.md contributor guide
Guidelines for external contributors using AI coding tools,
covering licensing, AI disclosure requirements, PR scope,
commit style, code formatting, and testing expectations.

Generated with the assistance of an AI coding tool.
2026-02-18 09:09:46 +11:00
Dion Moult ed500d58ba For consistency, maxfail=1 for module tool tests 2026-02-17 18:16:33 +11:00
Dion Moult 8023a992da Fix tests where panel name and tab panel name is identical
For now probably just easier to skip tabs. They are just containers and
not worth testing. Famous last words :)
2026-02-17 18:16:20 +11:00
Dion Moult fcc80ad14a Simplify add reference image size implementation and fix segfaulting tests
Previously, there was a dance between invoke, execute, and draw. This
can probably be resolved, but is a high-risk for undo bugs. This
simplifies the logic flow to just a traditional _invoke -> _execute.

I add a new feature test to at least make sure it does something, and
this also fixes the segfault in tool tests as it no longer requires the
launching of the file browser.
2026-02-17 18:11:13 +11:00
José Aliste c6b14d1474 Fixes snap angle.
In my previous commit, I mistakenly believed that there was an API change from
snap_angle_increment to snap_angle_increment_3d
But since the feature was introduced in blender 4.2 the setting is called
snap_angle_increment_3d.
2026-02-17 13:39:03 +11:00
Dion Moult 37fe0ad993 Reimplement adding multiple references / schedules cf5ffad9af
Previously it was implemented inline. This now implements it as a
tool.Blender function with tests. Also the previous tests didn't
actually run and weren't actually testing any tools despite being in a
tool tests.
2026-02-17 11:18:24 +11:00
Dion Moult e20e286168 Revert "feat(drawing): support multiple file selection in Add Reference"
This reverts commit cf5ffad9af.
2026-02-16 18:25:54 +11:00
Dion Moult 8c0bed0c61 Stub open command so running tests doesn't keep on launching apps 2026-02-16 18:24:37 +11:00
Dion Moult 8cfb162851 Fix #7656. Regression in text editing where leaders were accidentally removed. Added tests. 2026-02-16 17:57:09 +11:00
dependabot[bot] 379c74b31f Bump ruff from 0.15.0 to 0.15.1
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.15.0 to 0.15.1.
- [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.0...0.15.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-16 14:57:13 +11:00
Dion Moult 1d1f158fe2 Remove no longer relevant invoke code for linking IFCs 2026-02-16 08:23:35 +11:00
Richard Brice 65d5df7801 IfcAxis2PlacementLinear mapping used with IfcSectionedSurface and IfcSectionedSolidHorizontal
IfcSectionedSurface and IfcSectionedSolidHorizontal both of CrossSectionPositions attributes which are lists of IfcAxis2PlacementLinear. The implementation of each class used its own bespoke mapping of IfcAxis2PlacementLinear, which were identical to each other and slightly different than IfcAxis2PlacementLinear. Now the two sectioned classes use the one and only mapping for IfcAxis2PlacementLinear
2026-02-15 11:16:07 -08:00
falken10vdl b246998f68 Linked IFC projects enhancement (multiple links to same project file) (#7607)
* Linked IFC projects enhancement (multiple links to same project file)

- Implement link management system using UUIDs as identifiers to support multiple links to the same IFC file
- Add georeferencing compatibility detection and UI display (NONE, NOT_COMPATIBLE, PARTIAL_COMPATIBLE, FULL_COMPATIBLE)
- Support for duplicate link creation with Shift+D shortcut and automatic position offset
- Add false origin and project north calculation from 3D cursor for MANUAL mode
- Only store one cache per file, regardless of the amount of links
- Prevent duplicate links based on filepath and position comparison
- Improve error handling for missing files and loading failures
- Update tests

* Remove duplicate georef UI

I try to avoid duplicate UI (especially for one that can be as
sophisticated as georef - e.g. missing is WCS) as it means double the
code, double the tests, potential user confusion. BTW the note about
vertical datum isn't quite accurate as it may be included in the CRS
definition so vertical datum is optional.

* Remove depsgraph_update_post handler for update_link_ui_on_transform as per core developer feedback

* Move get_projected_crs to geolocation module

* Refactor get_projected_crs to simplify as per core developer feedback

* Remove unused import of bonsai.tool from project module

* Use IfcDocumentInformation per linked file and IfcDocumentReference for locaiton information

* Refactor SaveBlendMetadataFile operator to remove  try-except blocks and remove linked projects collections since they are recreated by bonsai

* Cleanup removing empty collection instances for linked models in metadata.blend file and call determine_georeferencing_compatibility on link reload

* Add locking mechanism for linked models and update UI to reflect lock status

* Update logic that track IFC to execute_ifc_duplicate_operator instead of having it in execute() which does not track IFC undo/redo

* Refactor link handling to use get_link_empty_handle and set_link_empty_handle methods which in turn use the standard blender-ifc integrations patters (tool.Ifc.get_object(doc_reference) and tool.Ifc.link(doc_reference, empty_handle)

* remove operator.DuplicateLink and move it to tool.Project.duplicate_link()

* Refactor link handling to use sequential identifiers (no need for STEP ID DocRef)

* Refactor IFC linking logic to handle cases without a parent IFC file loaded. Firts link flase origin becomes parent origin

* Lock should not affect selection.

This makes it consistent with grid / spatial lock, and also toggle
selectability is already implemented.

* Remove unnecessary check for loaded library as Blender seems to do this internally already

* Rename util to get_crs because in IFC4X3 you can also have geographic CRS not just projected

* Remove unnecessary call to determine_georeferencing_compatibility

This function is already always called prior to calculate_link_position
so shouldn't be called here. It's also a very expensive function: as it
currently stands, just to link a single IFC, ifcopenshell.open() is
called 3 times. This reduces it to 2.

* Store CRS as metadata for linked models, and compare metadata when indicating georeferencing compatibility

Previously, to check georeferencing compatibility, ifcopenshell.open()
was used. When linking large models, this adds considerable time and
memory usage. This instead captures the georef as standard metadata in
our .cache.json. This now reduces the ifcopenshell.open() calls back
down to only 1 as necessary (see previous commit).

* Use link index instead of link name to fetch link collection item

Link name runs into issues with name uniqueness. This is why you created
a function for "get next link ID". After this refactoring, we can no
longer worry about uniqueness and that function may be removed.

* Simplify reloadlink into just unload and reload (with cache disabled)

This function should not be responsible for editing any data.

* Remove unnecessary get_next_link_id as names no longer need uniqueness

This now frees up the name variable to track a more meaningful, human
name like IfcDocumentInformation's Name attribute.

* Rewrite get / set link_empty_handle to just use the link directly

This prevents needless logic to fetch the link and also removes issues
related to duplicate names.

* Temporarily remove logic in prop callback

Right now, pretty much all the logic is done in a prop callback. In
general logic in prop callbacks should be minimised, since it's hard to
test and easily triggered as a domino effect of another change, and may
also impact undo/redo.

* Remove code that unnecessarily removes cache

This code removes cache, which means any project unlinking an IFC auto
clears the cache for any other project which doesn't make sense, and
also breaks the ability to readd it quickly.

* Rewrite link, unlink, load, and unload IFC

There were a few issues tackled here:

 - Operators that change any IFC data must use tool.Ifc.Operator and
_execute, otherwise undo/redo will break. That's one of the risks of
using prop callbacks, as it is not explicit when an IFC edit happens.
 - The usage of IfcDocumentReference was not correct. The Location
should store the URL, _not_ the position. The position should be in the
Identification attribute.
 - The URL was stored in IfcDocumentInformation location, which does not
work in IFC2X3. There are a few changes here to make it IFC2X3
compatible.
 - Generally move logic in operators, not prop callback.

* Remove restriction around manual mode.

Users should be able to use manual mode if they want.

* Restore AUTOMATIC mode to identical behaviour to file open

This is the first step to reusing cache files agnostic of the host.

* Revert tests for a fresh start for updating tests

* Revert "test_feature - clean up .ifc.cache. files after test was executed"

This reverts commit 99ae768ddf.

* Update tests and reimplement calculations for matrix of empty handle

Previously, the empty would always be placed at the origin, unless a
"position" offset was present. This is a problem, because the "position"
is simply a local offset relative to the Blender cache! If the cache was
regenerated, the offsets would be outdated. Also, the cache appeared in
different locations depending on the false origin mode, so the offset
would mean different things to different people.

Instead, a more robust method is:

 1. When you link a file, a Blender cache is generated. The Blender
origin of this cache is arbitrary! It depends on the user's false origin
mode and is purely a Blender session specific thing.
 2. When you load a link, a link is _always_ loaded into the correct
location with regards to IFC global coordinates. All math is done from
the perspective of IFC.
 3. If you choose to transform (move / rotate / scale!?) this link from
its correct location, that gets recorded as a 4x4 transformation matrix.
Note: I haven't implemented this properly yet.

Tests all pass, with a minor modification to the new behaviour that
false origin mode now won't affect the location it ends up in, only the
generation of the cache.

* Remove arbitrary convention around display name

Not needed anymore now that A/M/D is a detail and not significant on
actual coordinates, and also that the UUID is no longer needed.

* Simplify implementation of loading linked models when opening an IFC

* Move link matrix calculation from operator to tool for reuse

* Implement editing link location and calculation of transformation matrix

I changed my mind on the is_locked thing, since it isn't clear to the
user that locking need to be done to save changes.

* Remove old is_locked, prop update callback no longer needed (dedicated operator instead), remove old calculation code

* Simplify code related to placed_as_per_georef

* For now, simple skip for duplicate / delete

IMO duplicate / delete / move a link are very rare and explicit
operations.

* Update tests

* Remove host_model coordinate data as cache is no longer host model dependent

* Move icons outside list because there are too many

* Minor tweaks

---------

Co-authored-by: Dion Moult <dionmoult@gmail.com>
Co-authored-by: Dion Moult <dion@thinkmoult.com>
2026-02-15 19:28:43 +11:00
Ryan Schultz a88c5938dc typos 2026-02-14 12:18:29 -06:00
Thomas Krijnen 7978f1fb08 Fix compilation on gcc #7666 2026-02-13 10:17:28 +01:00
ssg3d 7b4889d2ec Update IfcParse.cpp
IfcOpenshell read file, and write file without changes. This round trip introduces truncation noise. It should not hurt to increase the precision to keep this clean.
2026-02-13 10:03:05 +01:00
José Aliste 740fcf7768 Use Blender's angle snap setting in wall.py and profile.py
Replace hardcoded 5-degree angle snapping with Blender's
snap_angle_increment setting in create_wall_from_2_points()
and create_profile_from_2_points().

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-11 22:29:43 -03:00
José Aliste 067e04b564 Use Blender's angle snap setting in model/polyline.py
Replace hardcoded 5-degree angle snapping with Blender's
snap_angle_increment setting in handle_lock_axis() for:
- Initial angle rounding when locking axis (A key)
- Angle rounding and increments on Shift+Wheel scroll

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-11 22:29:43 -03:00
José Aliste cd95f46db5 Use Blender's angle snap setting in tool/polyline.py
Replace hardcoded 5-degree angle snapping with Blender's
snap_angle_increment setting in calculate_distance_and_angle().

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-11 22:29:43 -03:00
José Aliste 348e48b49c Add get_angle_snap_value() helper to tool/snap.py
This function retrieves the angle snap increment from Blender's
tool_settings.snap_angle_increment property, which was added in
Blender 4.2. This allows users to configure the angle snap value
through Blender's native UI instead of using hardcoded values.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-11 22:29:43 -03:00
Thomas Krijnen 6bb8abdc5a Fix for 4.2 schema after a46cdbb907 2026-02-11 12:11:23 +01:00
Thomas Krijnen b7a8c9b330 Fix for 4.2 schema after a46cdbb907 2026-02-11 11:43:58 +01:00
Thomas Krijnen e6780973da arrange_poly: Refactor into logical blocks; add timing 2026-02-10 14:01:10 +01:00
Thomas Krijnen c6072e416c N-Section Lofting for Non-Polygonal (Curved) Shapes #7658 2026-02-10 11:04:43 +01:00
Thomas Krijnen f5686fff26 Simplify destructor by removing null check #7650 2026-02-10 09:25:02 +01:00
Thomas Krijnen a46cdbb907 Ignore site placement also for site geometry - add queue #7654 2026-02-09 21:37:21 +01:00
Thomas Krijnen a4d5d4e19a Ignore site placement also for site geometry #7654 2026-02-09 21:21:10 +01:00
494 changed files with 33095 additions and 15324 deletions
+3 -2
View File
@@ -1,7 +1,8 @@
# yaml-language-server: $schema=https://raw.githubusercontent.com/BlankSpruce/gersemi/0.24.0/gersemi/configuration.schema.json
# Needed for gersemi to detect custom functions and macros.
definitions: ["./cmake"]
# Gersemi doesn't support autodetection of macros/functions from other files or from the current one
# and requires to explicitly list directories/cmake files that define them.
definitions: ["./cmake", "./src"]
disable_formatting: false
extensions: []
indent: 4
+7 -7
View File
@@ -40,6 +40,8 @@ jobs:
# preinstalled: xz, cmake
brew install git bison autoconf automake libffi findutils
echo "$(brew --prefix findutils)/libexec/gnubin" >> $GITHUB_PATH
# Mac is using bison 2.5 by default, but we need 3.5+ for swig.
echo "$(brew --prefix bison)/bin" >> $GITHUB_PATH
- name: Install aws cli
run: |
@@ -47,11 +49,11 @@ jobs:
- name: Unpack Dependencies
run: |
install_root=$(find ./build -maxdepth 4 -type d -name install 2>/dev/null | head -n 1 || true)
[ -n "$install_root" ] && find "$install_root" -type f -name 'cache-*.tar.gz' -maxdepth 1 -exec tar -xzf {} -C "$install_root" \; || true
cd build
python ../nix/cache_dependencies.py unpack
- name: ccache
uses: hendrikmuhs/ccache-action@v1.2
uses: hendrikmuhs/ccache-action@v1.2.20
with:
key: mac-${{ matrix.arch }}
@@ -81,7 +83,7 @@ jobs:
- name: Upload Build Logs
if: always()
uses: actions/upload-artifact@v6
uses: actions/upload-artifact@v7
with:
name: build-logs-osx-${{ matrix.arch }}
path: |
@@ -93,9 +95,7 @@ jobs:
- name: Pack Dependencies
run: |
cd build
for install_dir in $(find $(find . -maxdepth 4 -name install) -mindepth 1 -maxdepth 1 -type d); do
test -f $(dirname "$install_dir")/cache-$(basename "$install_dir").tar.gz || tar -czf $(dirname "$install_dir")/cache-$(basename "$install_dir").tar.gz -C $(dirname "$install_dir") $(basename "$install_dir");
done
python ../nix/cache_dependencies.py pack
- name: Commit and Push Changes to Build Repository
run: |
+4 -4
View File
@@ -26,10 +26,10 @@ jobs:
- name: Unpack Dependencies
run: |
cd ifcopenshell_build
python ../IfcOpenShell/pyodide/cache_dependencies.py unpack
python ../IfcOpenShell/nix/cache_dependencies.py unpack
- name: ccache
uses: hendrikmuhs/ccache-action@v1.2
uses: hendrikmuhs/ccache-action@v1.2.20
with:
key: ubuntu-22.04-${{ runner.arch }}
@@ -42,7 +42,7 @@ jobs:
- name: Upload Build Logs
if: always()
uses: actions/upload-artifact@v6
uses: actions/upload-artifact@v7
with:
name: build-logs-pyodide
path: |
@@ -65,7 +65,7 @@ jobs:
- name: Pack Dependencies
run: |
cd ifcopenshell_build
python ../IfcOpenShell/pyodide/cache_dependencies.py pack
python ../IfcOpenShell/nix/cache_dependencies.py pack
- name: Commit and Push Changes to Build Repository
run: |
+10 -13
View File
@@ -6,13 +6,13 @@ on:
jobs:
build_ifcopenshell:
runs-on: ubuntu-22.04
container: rockylinux:8
container: rockylinux:9
steps:
- name: Install Dependencies
run: |
yum update -y
yum install -y gcc gcc-c++ git autoconf automake bison make zip cmake python3 \
dnf update -y
dnf install -y gcc gcc-c++ git autoconf automake bison make zip cmake python3 python3-pip \
bzip2 patch mesa-libGL-devel libffi-devel fontconfig-devel \
sqlite-devel bzip2-devel zlib-devel openssl-devel xz-devel \
readline-devel ncurses-devel libffi-devel libuuid-devel git-lfs \
@@ -38,20 +38,19 @@ jobs:
with:
repository: IfcOpenShell/build-outputs
path: ./build
ref: rockylinux8-x64
ref: rockylinux9-x64
lfs: true
token: ${{ secrets.BUILD_REPO_TOKEN }}
- name: Unpack Dependencies
run: |
install_root=$(find ./build -maxdepth 4 -type d -name install 2>/dev/null | head -n 1 || true)
[ -n "$install_root" ] && find "$install_root" -type f -name 'cache-*.tar.gz' -maxdepth 1 -exec tar -xzf {} -C "$install_root" \; || true
cd build
python3 ../nix/cache_dependencies.py unpack
- name: ccache
# TODO: Use tag after 1.2.20 releases.
uses: hendrikmuhs/ccache-action@5ebbd400eff9e74630f759d94ddd7b6c26299639
uses: hendrikmuhs/ccache-action@v1.2.20
with:
key: ubuntu-22.04-${{ runner.arch }}-rockylinux8
key: ubuntu-22.04-${{ runner.arch }}-rockylinux9
- name: Run Build Script
shell: bash
@@ -61,7 +60,7 @@ jobs:
- name: Upload Build Logs
if: always()
uses: actions/upload-artifact@v6
uses: actions/upload-artifact@v7
with:
name: build-logs-rocky
path: |
@@ -72,9 +71,7 @@ jobs:
- name: Pack Dependencies
run: |
cd build
for install_dir in $(find $(find . -maxdepth 4 -name install) -mindepth 1 -maxdepth 1 -type d); do
test -f $(dirname "$install_dir")/cache-$(basename "$install_dir").tar.gz || tar -czf $(dirname "$install_dir")/cache-$(basename "$install_dir").tar.gz -C $(dirname "$install_dir") $(basename "$install_dir");
done
python3 ../nix/cache_dependencies.py pack
- name: Commit and Push Changes to Build Repository
run: |
+10 -13
View File
@@ -6,13 +6,13 @@ on:
jobs:
build_ifcopenshell:
runs-on: ubuntu-22.04-arm
container: arm64v8/rockylinux:8
container: arm64v8/rockylinux:9
steps:
- name: Install Dependencies
run: |
yum update -y
yum install -y gcc gcc-c++ git autoconf automake bison make zip cmake python3 \
dnf update -y
dnf install -y gcc gcc-c++ git autoconf automake bison make zip cmake python3 python3-pip \
bzip2 patch mesa-libGL-devel libffi-devel fontconfig-devel \
sqlite-devel bzip2-devel zlib-devel openssl-devel xz-devel \
readline-devel ncurses-devel libffi-devel libuuid-devel git-lfs \
@@ -38,20 +38,19 @@ jobs:
with:
repository: IfcOpenShell/build-outputs
path: ./build
ref: rockylinux8-arm64
ref: rockylinux9-arm64
lfs: true
token: ${{ secrets.BUILD_REPO_TOKEN }}
- name: Unpack Dependencies
run: |
install_root=$(find ./build -maxdepth 4 -type d -name install 2>/dev/null | head -n 1 || true)
[ -n "$install_root" ] && find "$install_root" -type f -name 'cache-*.tar.gz' -maxdepth 1 -exec tar -xzf {} -C "$install_root" \; || true
cd build
python3 ../nix/cache_dependencies.py unpack
- name: ccache
# TODO: Use tag after 1.2.20 releases.
uses: hendrikmuhs/ccache-action@5ebbd400eff9e74630f759d94ddd7b6c26299639
uses: hendrikmuhs/ccache-action@v1.2.20
with:
key: ubuntu-22.04-${{ runner.arch }}-rockylinux8
key: ubuntu-22.04-${{ runner.arch }}-rockylinux9
- name: Run Build Script
shell: bash
@@ -61,7 +60,7 @@ jobs:
- name: Upload Build Logs
if: always()
uses: actions/upload-artifact@v6
uses: actions/upload-artifact@v7
with:
name: build-logs-rocky-arm64
path: |
@@ -72,9 +71,7 @@ jobs:
- name: Pack Dependencies
run: |
cd build
for install_dir in $(find $(find . -maxdepth 4 -name install) -mindepth 1 -maxdepth 1 -type d); do
test -f $(dirname "$install_dir")/cache-$(basename "$install_dir").tar.gz || tar -czf $(dirname "$install_dir")/cache-$(basename "$install_dir").tar.gz -C $(dirname "$install_dir") $(basename "$install_dir");
done
python3 ../nix/cache_dependencies.py pack
- name: Commit and Push Changes to Build Repository
run: |
+28 -11
View File
@@ -5,11 +5,26 @@ on:
jobs:
build_ifcopenshell:
runs-on: windows-2022
strategy:
fail-fast: false
matrix:
arch: ['x64']
include:
- arch: x64
runs_on: windows-2022
deps_dir: _deps-vs2022-x64-installed
vcvars: '"C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat"'
build_branch: windows-x64
zip_suffix: win64
- arch: ARM64
runs_on: windows-11-arm
deps_dir: _deps-vs2022-ARM64-installed
vcvars: '"C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsarm64.bat"'
build_branch: windows-arm64
zip_suffix: win-arm64
runs-on: ${{ matrix.runs_on }}
steps:
- name: Checkout Repository
uses: actions/checkout@v6
@@ -20,8 +35,8 @@ jobs:
uses: actions/checkout@v6
with:
repository: IfcOpenShell/build-outputs
path: _deps-vs2022-x64-installed
ref: windows-${{ matrix.arch }}
path: ${{ matrix.deps_dir }}
ref: ${{ matrix.build_branch }}
lfs: true
token: ${{ secrets.BUILD_REPO_TOKEN }}
@@ -31,14 +46,13 @@ jobs:
- name: Unpack Dependencies
run: |
cd _deps-vs2022-x64-installed
cd ${{ matrix.deps_dir }}
Get-ChildItem -Path . -Filter 'cache-*.zip' | ForEach-Object {
7z x $_.FullName
}
- name: ccache
# TODO: Use tag after 1.2.20 releases.
uses: hendrikmuhs/ccache-action@5ebbd400eff9e74630f759d94ddd7b6c26299639
uses: hendrikmuhs/ccache-action@v1.2.20
with:
key: win-${{ matrix.arch }}
# Windows ccache needs ~1GB
@@ -47,14 +61,16 @@ jobs:
- name: Run Build Script And Pack .zip Archives
shell: cmd
env:
TARGET_ARCH: ${{ matrix.arch }} # lets the Python script know which arch to target (optional override)
run: |
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat"
call ${{ matrix.vcvars }}
cd win
python build-all-win.py
- name: Pack Dependencies
run: |
cd _deps-vs2022-x64-installed
cd ${{ matrix.deps_dir }}
Get-ChildItem -Path . -Directory | ForEach-Object {
$cacheFile = "cache-$($_.Name).zip"
echo $cacheFile
@@ -65,12 +81,13 @@ jobs:
- name: Commit and Push Changes to Build Repository
run: |
cd _deps-vs2022-x64-installed
cd ${{ matrix.deps_dir }}
git config user.name "IfcOpenBot"
git config user.email "ifcopenbot@ifcopenshell.org"
git checkout -B ${{ matrix.build_branch }}
git add *.zip
git commit -m "Update build artifacts [skip ci]" || echo "No changes to commit"
git push || echo "Push failed"
git push --set-upstream origin ${{ matrix.build_branch }} || echo "Push failed"
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v6
@@ -33,6 +33,8 @@ jobs:
id: syntax-errors
run: |
ERROR=0
# Using 2 Python versions - one minimum required for IfcOpenShell
# and other that's used by Blender currently.
python3.10 -W error -m compileall -q src/ifcopenshell-python || ERROR=1
python3.11 -W error -m compileall -q src/bonsai || ERROR=1
exit $ERROR
+10 -10
View File
@@ -24,9 +24,15 @@ jobs:
runs-on: ubuntu-latest
if: |
github.repository == 'IfcOpenShell/IfcOpenShell'
outputs:
timestamp: ${{ steps.timestamp.outputs.timestamp }}
steps:
- name: Set env
run: echo ok go
- name: Get current timestamp
id: timestamp
# Include hours and minutes to release tag
# to avoid possibility of unstable repo's index.json
# pointing to the new file when index.json itself wasn't yet updated.
run: echo "timestamp=$(date +'%y%m%d%H%M')" >> $GITHUB_OUTPUT
build:
needs: activate
@@ -67,12 +73,6 @@ jobs:
- name: Get current version
id: version
run: echo "version=$(cat VERSION)" >> $GITHUB_OUTPUT
- name: Get current date
id: date
# Include hours and minutes to release tag
# to avoid possibility of unstable repo's index.json
# pointing to the new file when index.json itself wasn't yet updated.
run: echo "date=$(date +'%y%m%d%H%M')" >> $GITHUB_OUTPUT
- name: Compile
run: |
cd src/bonsai && make dist PLATFORM=${{ matrix.config.short_name }} PYVERSION=${{ matrix.pyver }}
@@ -88,8 +88,8 @@ jobs:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: ${{ steps.find_zip.outputs.filepath }}
asset_name: ${{ steps.find_zip.outputs.filename }}
release_name: "bonsai-${{steps.version.outputs.version}}-alpha${{steps.date.outputs.date}} (unstable)"
tag: "bonsai-${{steps.version.outputs.version}}-alpha${{steps.date.outputs.date}}"
release_name: "bonsai-${{steps.version.outputs.version}}-alpha${{ needs.activate.outputs.timestamp }} (unstable)"
tag: "bonsai-${{steps.version.outputs.version}}-alpha${{ needs.activate.outputs.timestamp }}"
overwrite: true
body: "See README in https://github.com/IfcOpenShell/bonsai_unstable_repo/ on how to setup autoupdates for daily Bonsai builds."
+7 -7
View File
@@ -35,7 +35,7 @@ jobs:
-
name: ccache
uses: hendrikmuhs/ccache-action@v1.2
uses: hendrikmuhs/ccache-action@v1.2.20
-
name: Build ifcopenshell
@@ -73,7 +73,7 @@ jobs:
make package
working-directory: build
- name: Upload
uses: actions/upload-artifact@v6
uses: actions/upload-artifact@v7
with:
# Artifact name
name: ifcos-artifacts
@@ -91,26 +91,26 @@ jobs:
lfs: true
- name: Download
uses: actions/download-artifact@v7.0.0
uses: actions/download-artifact@v8.0.0
with:
# Artifact name
name: ifcos-artifacts
path: artifacts/
-
name: Set up QEMU
uses: docker/setup-qemu-action@v3
uses: docker/setup-qemu-action@v4
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
uses: docker/setup-buildx-action@v4
-
name: Login to Dockerhub
uses: docker/login-action@v3
uses: docker/login-action@v4
with:
username: aecgeeks
password: ${{ secrets.DOCKER_HUB_TOKEN }}
-
name: Build container image
uses: docker/build-push-action@v6
uses: docker/build-push-action@v7
with:
context: artifacts
repository: aecgeeks/ifcopenshell
+2 -4
View File
@@ -79,10 +79,7 @@ jobs:
libhdf5-dev libcgal-dev libeigen3-dev
- name: ccache
# TODO: temporarily pointing to 1.2.19 to get notified by dependabot when 1.2.20 is released
# to update hardcoded references to commits in some other workflows.
# Then we can switch back to 1.2 in all actions.
uses: hendrikmuhs/ccache-action@v1.2.19
uses: hendrikmuhs/ccache-action@v1.2.20
with:
key: ubuntu-22.04-${{ runner.arch }}
@@ -184,6 +181,7 @@ jobs:
"-DSCHEMA_VERSIONS=2x3;4;4x3_add2" \
-DGLTF_SUPPORT=On \
-DWITH_ROCKSDB=On \
-DBUILD_EXAMPLES=ON \
../cmake
sudo make -j $(nproc)
sudo make install
+2 -1
View File
@@ -82,6 +82,8 @@ src/bonsai/bonsai/translations.py
# bonsai test temp files
src/bonsai/test/files/temp
src/bonsai/test/files/basic.ifc.cache.blend
src/bonsai/test/files/basic.ifc.cache.sqlite
# bonsai data
src/bonsai/bonsai/bim/data/build/
@@ -113,4 +115,3 @@ dev_environment.bat
src/ifcopenshell-python/ifcopenshell/express/*.exp
src/ifcopenshell-python/ifcopenshell/express/*.exp.cache.dat
src/ifcquery/build/
+18 -10
View File
@@ -80,7 +80,7 @@ option(BUILD_IFCGEOM "Build IfcGeom." ON)
option(BUILD_IFCPYTHON "Build IfcPython." ON)
option(BUILD_CONVERT "Build IfcConvert executable." ON)
option(BUILD_DOCUMENTATION "Build IfcOpenShell Documentation." OFF)
option(BUILD_EXAMPLES "Build example applications." ON)
option(BUILD_EXAMPLES "Build example applications." OFF)
option(BUILD_GEOMSERVER "Build IfcGeomServer executable (Open CASCADE is required)." ON)
option(BUILD_IFCMAX "Build IfcMax, a 3ds Max plug-in, Windows-only." OFF)
option(BUILD_QTVIEWER "Build IfcOpenShell Qt GUI Viewer" OFF) # QtViewer requires Qt6
@@ -258,10 +258,10 @@ if(WITH_ROCKSDB)
set(ROCKSDB_LIBRARIES "IFCOPENSHELL_RocksDB")
target_compile_definitions(IFCOPENSHELL_RocksDB INTERFACE IFOPSH_WITH_ROCKSDB)
set(SWIG_DEFINES ${SWIG_DEFINES} -DIFOPSH_WITH_ROCKSDB)
target_link_libraries(
IFCOPENSHELL_RocksDB
INTERFACE $<IF:$<TARGET_EXISTS:RocksDB::rocksdb-shared>,RocksDB::rocksdb-shared,RocksDB::rocksdb>
)
# Shared binaries for `rocksdb` only support limited API (only `c.h`), but we use `db.h` API.
# So rocksdb supported only as a static library.
# See https://github.com/facebook/rocksdb/issues/981.
target_link_libraries(IFCOPENSHELL_RocksDB INTERFACE RocksDB::rocksdb)
if(WITH_ZSTD)
# @todo do we actually need the zstd include dir or rather just pass
@@ -368,12 +368,20 @@ if(ENABLE_BUILD_OPTIMIZATIONS)
# Linker
# /OPT:REF enables also /OPT:ICF and disables INCREMENTAL
set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /LTCG /OPT:REF")
set(LINKER_FLAGS_RELEASE "/LTCG /OPT:REF")
# /OPT:NOICF is recommended when /DEBUG is used (http://msdn.microsoft.com/en-us/library/xe4t6fc1.aspx)
set(CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /DEBUG /OPT:NOICF")
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /LTCG /OPT:REF")
set(CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /DEBUG /OPT:NOICF")
set(LINKER_FLAGS_RELWITHDEBINFO "/DEBUG /OPT:NOICF")
set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} ${LINKER_FLAGS_RELEASE}")
set(CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO
"${CMAKE_SHARED_LINKER_FLAGS_RELEASE} ${LINKER_FLAGS_RELWITHDEBINFO}"
)
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} ${LINKER_FLAGS_RELEASE}")
set(CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_EXE_LINKER_FLAGS_RELEASE} ${LINKER_FLAGS_RELWITHDEBINFO}")
set(CMAKE_MODULE_LINKER_FLAGS_RELEASE "${CMAKE_MODULE_LINKER_FLAGS_RELEASE} ${LINKER_FLAGS_RELEASE}")
set(CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO
"${CMAKE_MODULE_LINKER_FLAGS_RELEASE} ${LINKER_FLAGS_RELWITHDEBINFO}"
)
else()
# GCC-like: Release should use O3 but RelWithDebInfo 02 so enforce 03. Anything other useful that could be added here?
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3")
+11
View File
@@ -43,6 +43,17 @@ if(NOT OCC_INCLUDE_DIR AND NOT OCC_LIBRARY_DIR)
set_target_properties(TKernel PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${OpenCASCADE_INCLUDE_DIR}")
endif()
if(
OpenCASCADE_VERSION VERSION_LESS "7.9.0"
AND CMAKE_VERSION GREATER_EQUAL "3.24"
AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU"
)
# Before 7.9.0 targets in OCCT cmake configs are not linked to each other
# leading to missing symbols on Unix. Link them as a single group as a workaround.
# Only needed for gcc, because other compilers (e.g. Apple Clang, MSVC) do rescan automatically.
set(OpenCASCADE_LIBRARIES "$<LINK_GROUP:RESCAN,${OpenCASCADE_LIBRARIES}>")
endif()
if(OpenCASCADE_VERSION VERSION_LESS "7.9.0" AND WIN32)
# Bug in OCCT cmake configs < 7.9.0 - missing linked library.
list(APPEND OpenCASCADE_LIBRARIES WSOCK32.lib)
+59 -76
View File
@@ -75,27 +75,30 @@ Used environment variables:
# #
# for python37 to install correctly additionally: #
# * libffi(-dev[el]) #
# for Python build we also needs ssl #
# for Python build we also needs ssl and zlib #
# (since we do `pip install numpy` at the end) #
# * libssl-dev #
# #
# on debian 7.8 these can be obtained with: #
# $ apt-get install git gcc g++ autoconf bison bzip2 cmake #
# mesa-common-dev libffi-dev libfontconfig1-dev #
# libssl-dev xz #
# libssl-dev xz zlib1g-dev #
# #
# on ubuntu 14.04: #
# $ apt-get install git gcc g++ autoconf bison make cmake #
# mesa-common-dev libffi-dev libfontconfig1-dev #
# libssl-dev xz-utils #
# libssl-dev xz-utils zlib1g-dev #
# #
# on OS X El Capitan with homebrew: #
# $ brew install git bison autoconf automake libffi cmake #
# $ # `bison` shipped with Mac is too old for swig build, #
# $ # so we use `brew`. #
# $ export PATH=$(brew --prefix bison)/bin:$PATH #
# #
# on RHEL-related distros: #
# $ yum install git gcc gcc-c++ autoconf bison make cmake #
# $ dnf install git gcc gcc-c++ autoconf bison make cmake #
# mesa-libGL-devel libffi-devel fontconfig-devel bzip2 #
# automake patch byacc xz #
# automake patch byacc xz zlib-devel openssl-devel #
"""
@@ -147,9 +150,8 @@ OCCT_VERSION = "7.8.1"
BOOST_VERSION = "1.86.0"
EIGEN_VERSION = "3.4.0"
PCRE_VERSION = "8.41"
PCRE2_VERSION = "10.32"
LIBXML2_VERSION = "2.13.8"
SWIG_VERSION = "4.1.0"
SWIG_VERSION = "4.2.1"
OPENCOLLADA_VERSION = "v1.6.68"
HDF5_VERSION = "1.13.1"
@@ -246,15 +248,8 @@ if WASM:
# https://github.com/pyodide/pyodide-build/pull/249
WASM_CMAKE_IS_USING_INIT_VARS = get_pyodide_build_version() >= (99, 0, 0)
# pyodide provide empty `CXXFLAGS`, leading to issues using C++ files compiled with `-fexceptions`
# which is used by OCCT.
# https://github.com/pyodide/pyodide-build/issues/251
side_module_cxx_flags = os.environ.get("SIDE_MODULE_CXXFLAGS", "")
if side_module_cxx_flags.strip():
print("SIDE_MODULE_CXXFLAGS are already passed from pyodide build ('{side_module_cxx_flags}').")
print("Maybe it's time to stop overriding them in the script?")
os.environ["SIDE_MODULE_CXXFLAGS"] = os.environ["SIDE_MODULE_CFLAGS"]
# 0.31 is required for SIDE_MODULE_CXXFLAGS to be provided.
assert get_pyodide_build_version() >= (0, 31)
# Set defaults for missing empty environment variables
@@ -294,6 +289,7 @@ DEPS_DIR = os.getenv("DEPS_DIR", DEFAULT_DEPS_DIR)
if not os.path.exists(DEPS_DIR):
os.makedirs(DEPS_DIR)
INSTALL_DIR = Path(DEPS_DIR) / "install"
BUILD_CFG = os.getenv("BUILD_CFG", "RelWithDebInfo")
@@ -319,24 +315,18 @@ cecho(f"* Build Directory = {BUILD_DIR}", MAGENTA)
cecho(f"* Dependency Directory = {DEPS_DIR}", MAGENTA)
cecho(f" - The directory where {PROJECT_NAME} dependencies are installed.")
cecho(f"* Build Config Type = {BUILD_CFG}", MAGENTA)
cecho(
""" - The used build configuration type for the dependencies.
Defaults to RelWithDebInfo if not specified."""
)
cecho(""" - The used build configuration type for the dependencies.
Defaults to RelWithDebInfo if not specified.""")
if BUILD_CFG == "MinSizeRel":
cecho(" WARNING: MinSizeRel build can suffer from a significant performance loss.", RED)
cecho(f"* IFCOS_NUM_BUILD_PROCS = {IFCOS_NUM_BUILD_PROCS}", MAGENTA)
cecho(
""" - How many compiler processes may be run in parallel.
"""
)
cecho(""" - How many compiler processes may be run in parallel.
""")
cecho(f" * IFCOS_SCHEMAS = '{os.environ.get('IFCOS_SCHEMAS')}'", MAGENTA)
cecho(
""" - IFC Schemas to compile. If not provided, fallback to default provided in cmake.
"""
)
cecho(""" - IFC Schemas to compile. If not provided, fallback to default provided in cmake.
""")
dependency_tree: "dict[str, tuple[str, ...]]" = {
"IfcParse": ("boost", "libxml2", "hdf5", "rocksdb"),
@@ -345,13 +335,12 @@ dependency_tree: "dict[str, tuple[str, ...]]" = {
"OpenCOLLADA": ("libxml2", "pcre"),
"IfcGeomServer": ("IfcGeom",),
"IfcOpenShell-Python": ("python", "swig", "IfcGeom"),
"swig": ("pcre2",),
"swig": (),
"boost": (),
"libxml2": (),
"python": (),
"occ": (),
"pcre": (),
"pcre2": (),
"json": (),
"hdf5": (),
"cgal": (),
@@ -418,7 +407,6 @@ if WASM:
"opencollada",
"swig",
"pcre",
"pcre2",
"IfcGeom",
"IfcConvert",
"IfcGeomServer",
@@ -433,13 +421,16 @@ print("Building:", *sorted(targets, key=lambda t: len(list(gather_dependencies(t
# Check that required tools are in PATH
yacc = "yacc" # Used during swig building process, installed with `bison` on Debian / `byacc` on Red Hat.
bison = "bison"
missing_commands: "list[str]" = []
required_commands = [git, bunzip2, tar, cc, cplusplus, autoconf, automake, make, "patch", "cmake", yacc, xz]
required_commands = [git, bunzip2, tar, cc, cplusplus, autoconf, automake, make, "patch", "cmake", yacc, xz, bison]
if "wasm" in flags:
# Skip swig build for WASM.
required_commands.append("swig")
required_commands.append("pyodide")
required_commands.remove(yacc)
required_commands.remove(bison)
for cmd in required_commands:
if shutil.which(cmd) is None:
@@ -498,7 +489,7 @@ def run(cmds: "Sequence[str]", cwd: "Union[str, None]" = None, can_fail: bool =
collector.append(line)
pipe.close()
logger.debug(f"running command {' '.join(cmds)} in directory {cwd}")
logger.debug(f"running command `{' '.join(cmds)}` in directory '{cwd}'")
stdout: list[str] = []
stderr: list[str] = []
@@ -544,14 +535,14 @@ BOOST_LOCATION = f"https://github.com/boostorg/boost/releases/download/boost-{BO
# Helper functions
def run_autoconf(arg1: str, configure_args: "list[str]", cwd: str) -> None:
def run_autoconf(dependency_name: str, configure_args: "list[str]", cwd: str) -> None:
configure_path = os.path.realpath(os.path.join(cwd, "..", "configure"))
if not os.path.exists(configure_path):
run(
[bash, "./autogen.sh"], cwd=os.path.realpath(os.path.join(cwd, ".."))
) # only run autogen.sh in the directory it is located and use cwd to achieve that in order to not mess up things
# Using `sh` over `bash` fixes issues with building swig
prefix = os.path.realpath(f"{DEPS_DIR}/install/{arg1}")
prefix = os.path.realpath(f"{DEPS_DIR}/install/{dependency_name}")
wasm = []
if "wasm" in flags:
@@ -930,20 +921,15 @@ if "pcre" in targets:
restore_env("CC", OLD_CC)
restore_env("CXX", OLD_CXX)
if "pcre2" in targets:
build_dependency(
name=f"pcre2-{PCRE2_VERSION}",
mode="autoconf",
build_tool_args=[DISABLE_FLAG],
download_url=f"https://downloads.sourceforge.net/project/pcre/pcre2/{PCRE2_VERSION}/",
download_name=f"pcre2-{PCRE2_VERSION}.tar.bz2",
)
if "swig" in targets:
dependency_name = f"swig-{SWIG_VERSION}"
build_dependency(
name=f"swig-{SWIG_VERSION}",
mode="autoconf",
build_tool_args=["--disable-ccache", f"--with-pcre2-prefix={DEPS_DIR}/install/pcre2-{PCRE2_VERSION}"],
name=dependency_name,
mode="cmake",
build_tool_args=[
"-DWITH_PCRE=OFF",
f"-DCMAKE_INSTALL_PREFIX={DEPS_DIR}/install/{dependency_name}",
],
download_url="https://github.com/swig/swig.git",
download_name="swig",
download_tool=download_tool_git,
@@ -951,21 +937,18 @@ if "swig" in targets:
)
if USE_OCCT and "occ" in targets:
patches = []
occt_args: "list[str]" = []
patches: "list[str]" = []
if OCCT_VERSION < "7.4":
patches.append("./patches/occt/enable-exception-handling.patch")
if OCCT_VERSION == "7.7.1":
# Skip ExpToCasExe as we don't need it and it requires additional dependencies.
# Before 7.7.2 ExpToCasExe is part of DataExchange, DETools doesn't exist yet.
# Since we do need DataExchange (used for IgesSerializer), we use a patch to skip only ExpToCasExe.
if "7.7.2" > OCCT_VERSION >= "7.7":
patches.append("./patches/occt/no_ExpToCasExe.patch")
if OCCT_VERSION == "7.7.2":
patches.append("./patches/occt/no_ExpToCasExe_7_7_2.patch")
if OCCT_VERSION == "7.8.1":
patches.append("./patches/occt/no_ExpToCasExe_7_8_1.patch")
if OCCT_VERSION == "7.9.1":
patches.append("./patches/occt/no_ExpToCasExe_7_9_1.patch")
elif OCCT_VERSION >= "7.7.2":
occt_args.append("-DBUILD_MODULE_DETools=OFF")
if "wasm" in flags:
patches.append("./patches/occt/no_em_js.patch")
@@ -986,6 +969,7 @@ if USE_OCCT and "occ" in targets:
f"-DUSE_GLES2=OFF",
f"-DCMAKE_POLICY_VERSION_MINIMUM=3.5",
*MAC_CROSS_COMPILE_INTEL_ARGS,
*occt_args,
],
download_url="https://github.com/Open-Cascade-SAS/OCCT",
download_name="occt",
@@ -1101,23 +1085,19 @@ if "python" in targets and not USE_CURRENT_PYTHON_VERSION and "wasm" not in flag
PYTHON_CONFIGURE_ARGS.extend(["--with-universal-archs=intel-64", "--enable-universalsdk"])
for PYTHON_VERSION in PYTHON_VERSIONS:
try:
build_dependency(
f"python-{PYTHON_VERSION}",
"autoconf",
PYTHON_CONFIGURE_ARGS,
f"http://www.python.org/ftp/python/{PYTHON_VERSION}/",
f"Python-{PYTHON_VERSION}.tgz",
)
except RuntimeError as e:
# Sometimes setting up modules such as pip/lzma can cause
# the python installer script to return a non zero exit
# code where actually the headers and dynamic libraries
# are installed correctly. This is all we need so we catch
# the exception and only reraise if a partially successful
# install is not detected.
if not os.path.exists(os.path.join(DEPS_DIR, "install", f"python-{PYTHON_VERSION}")):
raise e
# Don't fail silently on missing Python dependencies (e.g. openssl or zlib),
# because later ifcopenshell-python build will fail too but in a more confusing way.
build_dependency(
f"python-{PYTHON_VERSION}",
"autoconf",
PYTHON_CONFIGURE_ARGS,
f"http://www.python.org/ftp/python/{PYTHON_VERSION}/",
f"Python-{PYTHON_VERSION}.tgz",
)
python_bin = INSTALL_DIR / f"python-{PYTHON_VERSION}" / "bin" / "python3"
# `_ssl` module is present -> we will be able to install `numpy` later
# to verify IfcOpenShell installation
run([str(python_bin), "-c", "import _ssl"])
if MAC_CROSS_COMPILE_INTEL:
assert original_path
@@ -1535,13 +1515,16 @@ if "IfcOpenShell-Python" in targets:
)
# Copy setup.py where pyodide build system expects it.
shutil.copy(REPO_PATH / "pyodide" / "setup.py", REPO_PATH)
# Empty pyproject so it's contents won't affect the resulting wheelthe the
# otherwise the wheel will use version and dependencies from toml, not setup.py.
(REPO_PATH / "pyproject.toml").write_text("")
elif USE_CURRENT_PYTHON_VERSION:
python_info = sysconfig.get_paths()
compile_python_wrapper(platform.python_version(), python_info["include"], sys.executable)
else:
for python_version in PYTHON_VERSIONS:
python_path = Path(DEPS_DIR) / "install" / f"python-{python_version}"
python_path = INSTALL_DIR / f"python-{python_version}"
module_dir = compile_python_wrapper(python_version, python_path=python_path)
assert module_dir
# Not sure why, but added after reading this in the logs
@@ -5,9 +5,13 @@ This script is finding common install directory and either
packs each folder into a tar.gz archive, if it wasn't packed before,
or unpacks existing archives.
Expected to be executed from 'build' directory (e.g. that might contain 'Linux/x86_64/install').
Usage: python cache_dependencies.py [pack|unpack]
"""
import platform
import subprocess
import sys
import tarfile
from pathlib import Path
@@ -17,11 +21,20 @@ CACHE_PREFIX = "cache-"
def get_install_dir() -> Path:
for data in Path.cwd().glob("*/*/install"):
if platform.system() == "Darwin":
pattern = "Darwin/*/*/install"
else:
pattern = "*/*/install"
for data in Path.cwd().glob(pattern):
return data
raise Exception("No install dir found")
def run(cmd: str) -> None:
print(f"Running command: `{cmd}`")
subprocess.check_call(cmd, shell=True)
def pack_dependencies(install_dir: Path) -> None:
# Process each install_dir
for dependency_path in install_dir.iterdir():
@@ -32,8 +45,8 @@ def pack_dependencies(install_dir: Path) -> None:
if tar_path.exists():
print(f"Skipping existing cache: '{tar_path}'")
else:
with tarfile.open(tar_path, "w:gz") as tar:
tar.add(dependency_path, arcname=dependency_path.name)
# Python's `tarfile` is 10x slower than `tar` cli, so we use `tar`.
run(f'tar -czf "{tar_path}" -C "{install_dir}" "{dependency_name}"')
print(f"Created cache: '{tar_path}'")
+9 -13
View File
@@ -1,13 +1,9 @@
diff --git a/CMakeLists.txt b/CMakeLists.txt
index fd17283f77..6cecf9dad3 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -826,6 +826,8 @@ if (EMSCRIPTEN)
list (REMOVE_ITEM BUILD_TOOLKITS ExpToCasExe)
endif()
+list (REMOVE_ITEM BUILD_TOOLKITS ExpToCasExe)
+
# bison
if (BUILD_YACCLEX)
OCCT_INCLUDE_CMAKE_FILE ("adm/cmake/bison")
--- a/adm/MODULES
+++ b/adm/MODULES
@@ -3,5 +3,5 @@ ModelingData TKG2d TKG3d TKGeomBase TKBRep
ModelingAlgorithms TKGeomAlgo TKTopAlgo TKPrim TKBO TKBool TKHLR TKFillet TKOffset TKFeat TKMesh TKXMesh TKShHealing
Visualization TKService TKV3d TKOpenGl TKOpenGles TKMeshVS TKIVtk TKD3DHost
ApplicationFramework TKCDF TKLCAF TKCAF TKBinL TKXmlL TKBin TKXml TKStdL TKStd TKTObj TKBinTObj TKXmlTObj TKVCAF
-DataExchange TKXDE TKXSBase TKSTEPBase TKSTEPAttr TKSTEP209 TKSTEP TKIGES TKXCAF TKXDEIGES TKXDESTEP TKSTL TKVRML TKXmlXCAF TKBinXCAF TKRWMesh TKXDECascade TKExpress ExpToCasExe
+DataExchange TKXDE TKXSBase TKSTEPBase TKSTEPAttr TKSTEP209 TKSTEP TKIGES TKXCAF TKXDEIGES TKXDESTEP TKSTL TKVRML TKXmlXCAF TKBinXCAF TKRWMesh TKXDECascade TKExpress
Draw TKDraw TKTopTest TKOpenGlTest TKOpenGlesTest TKD3DHostTest TKViewerTest TKXSDRAW TKDCAF TKXDEDRAW TKTObjDRAW TKQADraw TKIVtkDraw DRAWEXE
@@ -1,13 +0,0 @@
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 1bacca1a48..11f931ad39 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -820,6 +820,8 @@ else()
OCCT_CHECK_AND_UNSET ("3RDPARTY_DOT_EXECUTABLE")
endif()
+list (REMOVE_ITEM BUILD_TOOLKITS ExpToCasExe)
+
# bison
if (BUILD_YACCLEX)
OCCT_INCLUDE_CMAKE_FILE ("adm/cmake/bison")
@@ -1,13 +0,0 @@
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 86905287dc..9d0bce984c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -828,6 +828,8 @@ else()
OCCT_CHECK_AND_UNSET ("3RDPARTY_DOT_EXECUTABLE")
endif()
+list (REMOVE_ITEM BUILD_TOOLKITS ExpToCasExe)
+
# bison
if (BUILD_YACCLEX)
OCCT_INCLUDE_CMAKE_FILE ("adm/cmake/bison")
@@ -1,13 +0,0 @@
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 34300d41ad..09b2e0d45f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -721,6 +721,8 @@ else()
OCCT_CHECK_AND_UNSET ("3RDPARTY_DOT_EXECUTABLE")
endif()
+list (REMOVE_ITEM BUILD_TOOLKITS ExpToCasExe)
+
# bison
if (BUILD_YACCLEX)
list (APPEND OCCT_3RDPARTY_CMAKE_LIST "adm/cmake/bison")
+7 -2
View File
@@ -1,9 +1,12 @@
#!/usr/bin/bash
set -ex
# Script is assuming that it will be possible to execute it multiple times
# therefore we're clearing venv each time and ignoring existing 'emsdk' folder.
# Install uv.
curl -LsSf https://astral.sh/uv/install.sh | sh
uv venv --python 3.13
uv venv --python 3.13 --clear
source .venv/bin/activate
# Install pyodide cross build environment.
@@ -13,7 +16,9 @@ uv pip install pyodide-build
uv run pyodide xbuildenv install
# Emscripten doesn't come with xbuildenv.
git clone https://github.com/emscripten-core/emsdk
if [ ! -d emsdk ]; then
git clone https://github.com/emscripten-core/emsdk
fi
pushd emsdk
PYODIDE_EMSCRIPTEN_VERSION=$(pyodide config get emscripten_version)
./emsdk install ${PYODIDE_EMSCRIPTEN_VERSION}
+11 -4
View File
@@ -2,10 +2,10 @@
name = "IfcOpenShell"
version = "0.0.0"
dependencies = [
"black==26.1.0",
"ruff==0.15.0",
"black==26.3.1",
"ruff==0.15.5",
"poethepoet",
"gersemi==0.25.4",
"gersemi==0.26.0",
]
[tool.black]
@@ -15,7 +15,8 @@ include = '''
|nix/.*.pyi?$
'''
extend-exclude = '''
src/ifcopenshell-python/ifcopenshell/express/*
src/ifcopenshell-python/ifcopenshell/express/rules/*
|src/ifcopenshell-python/ifcopenshell/express/express_parser.py
|src/ifcopenshell-python/ifcopenshell/mvd/*
|src/ifcopenshell-python/ifcopenshell/simple_spf/*
|src/ifc2ca/templates/*
@@ -27,6 +28,12 @@ extend-exclude = '''
reportInvalidTypeForm = false
disableBytesTypePromotions = true
reportUnnecessaryTypeIgnoreComment = true
# Pylance doesn't respect gitignore, so we have to exclude files manually here
# to avoid VS Code slowing down.
# https://github.com/microsoft/pylance-release/issues/5169
exclude = [
"_deps",
]
# Define here general ruff settings,
# then they will be inherited by projects' .toml files.
+2 -2
View File
@@ -34,8 +34,8 @@ client_id, client_secret = "", ""
class OAuthReceiver(http.server.BaseHTTPRequestHandler):
def do_GET(self) -> None:
query = urllib.parse.parse_qs(urllib.parse.urlparse(self.path).query)
self.server.auth_code = query.get("code", [""])[0] # type:ignore
self.server.auth_state = query.get("state", [""])[0] # type:ignore
self.server.auth_code = query.get("code", [""])[0] # type: ignore
self.server.auth_state = query.get("state", [""])[0] # type: ignore
self.send_response(200)
self.send_header("Content-type", "text/plain")
self.end_headers()
+6 -25
View File
@@ -104,7 +104,7 @@ endif
endif # def PLATFORM
# Current build commit hash.
OLD:=e8eb5e4
OLD:=1c5b825
.PHONY: bump
bump:
ifndef NEW
@@ -223,19 +223,8 @@ endif
cd build/bonsai/bim/data/gantt/ && wget https://raw.githubusercontent.com/jsGanttImproved/jsgantt-improved/master/dist/jsgantt.css
# Provides IFCJSON functionality
cd build && wget -O ifc2json.zip https://github.com/IFCJSON-Team/IFC2JSON_python/archive/refs/heads/master.zip
cd build && unzip ifc2json.zip && rm ifc2json.zip
# IFCJSON doesn't have pyproject.toml, so we use python command.
cd build && . env/$(VENV_ACTIVATE) && cd IFC2JSON_python-*/file_converters && \
$(PYTHON) -c "from setuptools import setup; \
setup( \
name='ifcjson', \
version='0.0.1', \
author='Jan Brouwer', \
author_email='jan@brewsky.nl', \
packages=['ifcjson'], \
)" bdist_wheel
cp -r build/IFC2JSON_python-*/file_converters/dist/*.whl build/wheels/
# TODO: Use official repo, once https://github.com/IFCJSON-Team/IFC2JSON_python/pull/8 is merged.
cd build && . env/$(VENV_ACTIVATE) && $(PYTHON) -m pip wheel "git+https://github.com/Andrej730/IFC2JSON_python.git@pyproject_toml" --no-deps -w wheels/
# Brickschema requires pkg_resources which is provided by Blender.
# Provides Brickschema functionality
@@ -243,16 +232,8 @@ endif
cd build/bonsai/bim/data/brick/ && wget https://github.com/BrickSchema/Brick/releases/download/nightly/Brick.ttl
# Required for hipped roof generation
cd build && wget https://github.com/prochitecture/bpypolyskel/archive/refs/heads/master.zip
cd build && unzip master.zip && rm master.zip
cd build && . env/$(VENV_ACTIVATE) && cd bpypolyskel-master && \
$(PYTHON) -c "from setuptools import setup; \
setup( \
name='bpypolyskel', \
version='0.0.0', \
packages=['bpypolyskel'], \
)" bdist_wheel
cp -r build/bpypolyskel-master/dist/*.whl build/wheels/
# TODO: Use official repo once https://github.com/prochitecture/bpypolyskel/pull/22 is merged.
cd build && . env/$(VENV_ACTIVATE) && $(PYTHON) -m pip wheel "git+https://github.com/Andrej730/bpypolyskel.git@pyproject_toml" --no-deps -w wheels/
# folder for executable files
mkdir -p build/bonsai/libs/bin
@@ -371,7 +352,7 @@ test-tool:
ifndef MODULE
pytest test/tool
else
pytest test/tool/test_$(MODULE).py
pytest test/tool/test_$(MODULE).py --maxfail=1
endif
# Reregistering test is not added to the standard test suite because during unregister
+38 -37
View File
@@ -34,14 +34,12 @@ IN_PACKAGE = __package__ == "bonsai"
import platform
import re
import shutil
import traceback
import uuid
import webbrowser
from collections import deque
from collections.abc import Generator
from pathlib import Path
from typing import Any, Union
from typing import TYPE_CHECKING, Any, Union
last_commit_hash = "8888888"
last_commit_date = "9999999"
@@ -73,6 +71,21 @@ REINSTALLED_BBIM_VERSION: Union[str, None] = None
REGISTERED_BBIM_PACKAGE: str
def is_registering() -> bool:
"""
During addon registration ``bpy.context`` and ``bpy.data`` are restricted
and you can't access their properties.
"""
import bpy
if TYPE_CHECKING or bpy.app.version >= (5, 0, 0):
import _bpy_restrict_state as bpy_restrict_state
else:
import bpy_restrict_state
return isinstance(bpy.context, bpy_restrict_state._RestrictContext)
def initialize_bbim_semver():
"""Initialize `bbim_semver` dictionary.
@@ -94,9 +107,13 @@ def initialize_bbim_semver():
bbim_semver["version"] = version_str
def get_debug_info():
def get_debug_info(*, bonsai_failed_to_load: bool = False) -> dict[str, Any]:
import bpy
bbim_version = bbim_semver["version"]
# All data here should be gettable even in case of `bpy.context` and `bpy.data` being inaccessible
# and Bonsai completely failed to load.
debug_info = {
"os": platform.system(),
"os_version": platform.version(),
@@ -112,6 +129,14 @@ def get_debug_info():
"last_error": last_error,
}
# Can't access blend data or context during registration.
# If Bonsai failed to load we cannot safely access any of its properties or its tools
# as they may not be registered yet and acessing them will break Bonsai Fatal Error UI.
if is_registering() or bonsai_failed_to_load:
return debug_info
import bonsai.tool as tool
# Add .blend file save information
if bpy.data.is_saved:
debug_info["blend_file_path"] = bpy.data.filepath
@@ -132,7 +157,7 @@ def get_debug_info():
return debug_info
def format_debug_info(info: dict):
def format_debug_info(info: dict[str, Any]) -> str:
last_actions = ""
for action in info["last_actions"]:
last_actions += f"\n# {action['type']}: {action['name']}"
@@ -150,33 +175,10 @@ def get_binaries(path: Path) -> Generator[Path, None, None]:
yield from path.glob("**/*.so")
def safe_link_dlls() -> None:
# Blender 4.2+ has a problem on Windows for disabling/enabling/reinstalling extensions
# with loaded binary dependencies (on Windows you can't remove a binary if it's loaded by some program).
# To avoid this issue we temporary hard link dlls to our temp directory on unregister()
# (unregister is executed before Blender will try to uninstall dependencies and the issue will arise).
# Then, Blender won't have a problem unlinking unloaded dlls as they are still linked somewhere.
# On register() we clean up our temp directory with binaries.
#
# TODO: If user uninstalls Bonsai to never use it again, temporary directory won't be cleared.
#
# See: https://projects.blender.org/blender/blender/issues/125049
import bpy
ext_path = Path(bpy.utils.user_resource("EXTENSIONS"))
local_path = ext_path / ".local"
# We use random hash subfolder as user may try to enable/disable addon multiple times.
random_hash = uuid.uuid4().hex[:8]
temp_local = ext_path / ".local_temp" / random_hash
temp_local.mkdir(parents=True)
for filepath in get_binaries(local_path):
dest_path = temp_local / filepath.relative_to(local_path)
dest_path.parent.mkdir(exist_ok=True, parents=True)
os.link(filepath, dest_path)
# TODO: remove before 0.8.6 release.
# On Windows issues with removing extensions were resolved in Blender 4.3,
# but we removed our workaround that was producing some junk only in 0.8.5 release.
# So we're temporarily keeping the part that's cleaning up outputs from previous releases.
def clean_up_dlls_safe_links() -> None:
import bpy
@@ -206,6 +208,8 @@ def clean_up_dlls_safe_links() -> None:
if IN_BLENDER:
import bpy
initialize_bbim_semver()
def get_binary_info() -> dict[str, Any]:
@@ -297,9 +301,6 @@ if IN_BLENDER:
purge_cache()
def unregister():
if platform.system() == "Windows":
safe_link_dlls()
import bonsai.bim
bonsai.bim.unregister()
@@ -334,7 +335,7 @@ if IN_BLENDER:
bl_context = "scene"
def draw(self, context):
info = get_debug_info()
info = get_debug_info(bonsai_failed_to_load=True)
layout = self.layout
layout.alert = True
@@ -410,7 +411,7 @@ if IN_BLENDER:
bl_description = "Copies debugging information to your clipboard for use in bugreports"
def execute(self, context):
info = get_debug_info()
info = get_debug_info(bonsai_failed_to_load=True)
info.update(get_binary_info())
info = format_debug_info(info)
context.window_manager.clipboard = info
-8
View File
@@ -24,21 +24,14 @@ import os
import tempfile
import zipfile
from logging import Logger
from math import radians
from typing import Union
import bpy
import ifcopenshell
import ifcopenshell.api
import ifcopenshell.util.element
import ifcopenshell.util.placement
import ifcopenshell.util.unit
from mathutils import Vector
import bonsai.core.aggregate
import bonsai.core.geometry
import bonsai.core.spatial
import bonsai.core.style
import bonsai.tool as tool
from bonsai.bim.ifc import IfcStore
@@ -52,7 +45,6 @@ class IfcExporter:
self.set_header()
IfcStore.update_cache()
self.sync_all_objects()
tool.Project.save_linked_models_to_ifc()
extension = self.ifc_export_settings.output_file.split(".")[-1].lower()
if extension == "ifczip":
with tempfile.TemporaryDirectory() as unzipped_path:
-1
View File
@@ -28,7 +28,6 @@ import bpy
import ifcopenshell
import ifcopenshell.ifcopenshell_wrapper as W
import ifcopenshell.util.attribute
import ifcopenshell.util.element
import ifcopenshell.util.unit
from ifcopenshell.util.doc import (
get_attribute_doc,
+8 -46
View File
@@ -32,7 +32,6 @@ import ifcopenshell.api.pset
import ifcopenshell.geom
import ifcopenshell.ifcopenshell_wrapper as W
import ifcopenshell.util.element
import ifcopenshell.util.geolocation
import ifcopenshell.util.placement
import ifcopenshell.util.representation
import ifcopenshell.util.shape
@@ -85,7 +84,7 @@ class MaterialCreator:
if element.is_a("IfcTypeProduct"):
self.parse_element_type_material_styles(element)
self.parsed_meshes.add(self.mesh.name)
if not self.ifc_import_settings.load_indexed_maps:
if self.ifc_import_settings.load_indexed_maps:
self.load_texture_maps(shape_has_openings)
self.assign_material_slots_to_faces()
tool.Geometry.record_object_materials(obj)
@@ -117,7 +116,6 @@ class MaterialCreator:
for texture in texture_style.Textures or []:
if coords := getattr(texture, "IsMappedBy", None):
coords = coords[0]
# IfcTextureCoordinateGenerator handled in the style shader graph
if coords.is_a("IfcIndexedTextureMap"):
return coords
# TODO: support IfcTextureMap
@@ -135,6 +133,10 @@ class MaterialCreator:
if shape_has_openings and coords.is_a("IfcIndexedTextureMap"):
continue
tool.Loader.load_indexed_map(coords, self.mesh)
elif tool.Style.get_texture_style(material):
# No explicit coordinate mapping (e.g. IFC2X3 has no IsMappedBy,
# and IFC4 COORD uses generated UVs). Bake XY→UV as fallback.
tool.Loader.load_generated_uv_map(self.mesh)
def assign_material_slots_to_faces(self) -> None:
if not self.mesh["ios_materials"]:
@@ -745,6 +747,7 @@ class IfcImporter:
self.update_progress((percent_average / 100 * progress_range) + start_progress)
shape = iterator.get()
if shape:
assert isinstance(shape, W.TriangulationElement)
product = self.file.by_id(shape.id)
self.create_product(product, shape)
results.add(product)
@@ -892,48 +895,6 @@ class IfcImporter:
obj, tool.Loader.apply_blender_offset_to_matrix_world(obj, self.get_element_matrix(element))
)
if element.is_a("IfcAnnotation") and getattr(element, "ObjectType", None) == "IMAGE":
image = None
if obj.data and obj.data.materials and obj.data.materials[0]:
material = obj.data.materials[0]
if material.use_nodes and material.node_tree:
for node in material.node_tree.nodes:
if node.type == "TEX_IMAGE" and node.image:
image = node.image
break
if image:
import bmesh
bm = bmesh.new()
bm.from_mesh(obj.data)
if not bm.loops.layers.uv:
uv_layer = bm.loops.layers.uv.new()
else:
uv_layer = bm.loops.layers.uv.active
if bm.verts:
min_x = min(v.co.x for v in bm.verts)
max_x = max(v.co.x for v in bm.verts)
min_y = min(v.co.y for v in bm.verts)
max_y = max(v.co.y for v in bm.verts)
width = max_x - min_x
height = max_y - min_y
for face in bm.faces:
for loop in face.loops:
vert = loop.vert
u = (vert.co.x - min_x) / width if width > 0 else 0.5
v = (vert.co.y - min_y) / height if height > 0 else 0.5
u = max(0.0, min(1.0, u))
v = max(0.0, min(1.0, v))
loop[uv_layer].uv = (u, v)
bm.to_mesh(obj.data)
bm.free()
obj.data.update()
return obj
def load_existing_meshes(self) -> None:
@@ -1060,7 +1021,8 @@ class IfcImporter:
obj.hide_select = True
obj.hide_viewport = True
self.project["blender"].objects.link(obj)
self.project["blender"].BIMCollectionProperties.obj = obj
collection_props = tool.Blender.get_collection_props(self.project["blender"])
collection_props.obj = obj
props = tool.Blender.get_object_bim_props(obj)
props.collection = self.collections[project.GlobalId] = self.project["blender"]
@@ -19,7 +19,6 @@
import blf
import bpy
import gpu
import ifcopenshell
import ifcopenshell.util.element
from bpy.types import SpaceView3D
from bpy_extras import view3d_utils
@@ -27,7 +26,6 @@ from gpu_extras.batch import batch_for_shader
from mathutils import Vector
import bonsai.tool as tool
from bonsai.bim.module.geometry.decorator import ItemDecorator
def transparent_color(color, alpha=0.1):
@@ -19,8 +19,6 @@
from typing import TYPE_CHECKING
import bpy
import ifcopenshell
import ifcopenshell.api
import ifcopenshell.api.group
import ifcopenshell.api.pset
import ifcopenshell.api.root
@@ -23,12 +23,7 @@ import ifcopenshell.util.element
from bpy.props import (
BoolProperty,
CollectionProperty,
EnumProperty,
FloatProperty,
FloatVectorProperty,
IntProperty,
PointerProperty,
StringProperty,
)
from bpy.types import PropertyGroup
@@ -37,8 +32,6 @@ from bonsai.bim.module.aggregate.decorator import (
AggregateDecorator,
AggregateModeDecorator,
)
from bonsai.bim.module.spatial.data import SpatialData
from bonsai.bim.prop import Attribute, StrProperty
def can_aggregate(relating_obj: bpy.types.Object, related_obj: bpy.types.Object) -> bool:
@@ -21,7 +21,6 @@ from bpy.types import Panel
import bonsai.tool as tool
from bonsai.bim.ifc import IfcStore
from bonsai.bim.module.aggregate.data import AggregateData
from bonsai.bim.module.group.data import GroupsData, ObjectGroupsData
class BIM_PT_aggregate(Panel):
@@ -18,24 +18,14 @@
# pyright: reportUnnecessaryTypeIgnoreComment=error
import calendar
import json
import os
import time
from datetime import datetime
import bpy
import ifcopenshell.api.alignment
import ifcopenshell.api.spatial
import ifcopenshell.geom
import ifcopenshell.util.selector
import ifcopenshell.util.sequence
import isodate
from bpy_extras.io_utils import ImportHelper
from dateutil import parser, relativedelta
import bonsai.bim.module.sequence.helper as helper
import bonsai.core.sequence as core
import bonsai.tool as tool
@@ -23,16 +23,12 @@ from bpy.props import (
BoolProperty,
CollectionProperty,
EnumProperty,
FloatProperty,
FloatVectorProperty,
IntProperty,
PointerProperty,
StringProperty,
)
from bpy.types import PropertyGroup
import bonsai.tool as tool
from bonsai.bim.prop import Attribute, StrProperty
from bonsai.bim.prop import Attribute
class BIMAttributeProperties(PropertyGroup):
+11 -2
View File
@@ -16,8 +16,9 @@
# You should have received a copy of the GNU General Public License
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
import bpy.props
import bpy.types
from typing import TYPE_CHECKING
import bpy
class AuginProperties(bpy.types.PropertyGroup):
@@ -27,3 +28,11 @@ class AuginProperties(bpy.types.PropertyGroup):
project_name: bpy.props.StringProperty(name="Project Name")
project_filename: bpy.props.StringProperty(name="IFC Filename")
is_success: bpy.props.BoolProperty(name="Is Successful Upload", default=False)
if TYPE_CHECKING:
username: str
password: str
token: str
project_name: str
project_filename: str
is_success: bool
@@ -19,9 +19,7 @@
import os
from typing import Union
import bcf
import bcf.bcfxml
import bcf.v2.bcfxml
import bpy
import bonsai.tool as tool
+4 -9
View File
@@ -16,22 +16,18 @@
# You should have received a copy of the GNU General Public License
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
import os
import tempfile
import uuid
import webbrowser
from math import atan, cos, degrees, radians, sin, tan
from math import atan, degrees, radians, tan
from pathlib import Path
import bcf
import bcf.agnostic.topic
import bcf.agnostic.visinfo
import bcf.bcfxml
import bcf.v2.bcfxml
import bcf.v2.model
import bcf.v2.topic
import bcf.v2.visinfo
import bcf.v3
import bcf.v3.bcfxml
import bcf.v3.document
import bcf.v3.model
@@ -43,11 +39,10 @@ import ifcopenshell.util.geolocation
import ifcopenshell.util.unit
import numpy as np
from bpy_extras.io_utils import ExportHelper, ImportHelper
from mathutils import Euler, Matrix, Vector, geometry
from mathutils import Matrix, Vector
from xsdata.models.datatype import XmlDateTime
import bonsai.bim.module.bcf.bcfstore as bcfstore
import bonsai.bim.module.bcf.prop as bcf_prop
import bonsai.tool as tool
@@ -1258,8 +1253,8 @@ class ActivateBcfViewpoint(bpy.types.Operator):
else:
obj.data.show_background_images = False
area = next(area for area in context.screen.areas if area.type == "VIEW_3D")
area.spaces[0].region_3d.view_perspective = "CAMERA"
assert (space := tool.Blender.get_view3d_space())
space.region_3d.view_perspective = "CAMERA"
if self.file:
self.set_viewpoint_components(viewpoint, context)
-2
View File
@@ -24,8 +24,6 @@ from bpy.props import (
BoolProperty,
CollectionProperty,
EnumProperty,
FloatProperty,
FloatVectorProperty,
IntProperty,
PointerProperty,
StringProperty,
-1
View File
@@ -18,7 +18,6 @@
from __future__ import annotations
import os
from typing import TYPE_CHECKING
import bpy
@@ -20,7 +20,6 @@ import bmesh
import gpu
from bpy.types import SpaceView3D
from gpu_extras.batch import batch_for_shader
from mathutils import Vector
import bonsai.tool as tool
@@ -27,20 +27,18 @@ import ifcopenshell.api
import ifcopenshell.api.boundary
import ifcopenshell.api.root
import ifcopenshell.geom
import ifcopenshell.ifcopenshell_wrapper as W
import ifcopenshell.util.element
import ifcopenshell.util.placement
import ifcopenshell.util.representation
import ifcopenshell.util.shape
import ifcopenshell.util.unit
import mathutils
import numpy as np
import shapely
import shapely.ops
from ifcopenshell.util.shape_builder import ShapeBuilder
from mathutils import Matrix, Vector
import bonsai.bim.import_ifc as import_ifc
import bonsai.core
import bonsai.core.geometry
import bonsai.tool as tool
from bonsai.bim.ifc import IfcStore
@@ -704,6 +702,7 @@ class AddBoundary(bpy.types.Operator, tool.Ifc.Operator):
while True:
tree.add_element(iterator.get_native())
shape = iterator.get()
assert isinstance(shape, W.TriangulationElement)
shapes[shape.id] = {
"verts": ifcopenshell.util.shape.get_vertices(shape.geometry),
"faces": ifcopenshell.util.shape.get_faces(shape.geometry),
@@ -21,13 +21,7 @@ from typing import TYPE_CHECKING, Union
import bpy
from bpy.props import (
BoolProperty,
CollectionProperty,
EnumProperty,
FloatProperty,
FloatVectorProperty,
IntProperty,
PointerProperty,
StringProperty,
)
from bpy.types import PropertyGroup
+1 -2
View File
@@ -16,8 +16,7 @@
# You should have received a copy of the GNU General Public License
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
import bpy
from bpy.types import Panel, UIList
from bpy.types import Panel
import bonsai.tool as tool
from bonsai.bim.module.boundary.data import SpaceBoundariesData
+2 -6
View File
@@ -63,8 +63,7 @@ class BrickschemaData:
if namespace == "https://brickschema.org/schema/Brick":
return []
results = []
query = BrickStore.graph.query(
"""
query = BrickStore.graph.query("""
PREFIX brick: <https://brickschema.org/schema/Brick#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
@@ -81,10 +80,7 @@ class BrickschemaData:
}
}
GROUP BY ?object
""".replace(
"{uri}", uri
)
)
""".replace("{uri}", uri))
for row in query:
predicate_uri = row.get("predicate")
predicate_name = predicate_uri.toPython().split("#")[-1]
@@ -19,7 +19,6 @@
import os
import bpy
import ifcopenshell.api
from bpy_extras.io_utils import ExportHelper, ImportHelper
import bonsai.bim.handler
+1 -4
View File
@@ -23,10 +23,7 @@ from bpy.props import (
BoolProperty,
CollectionProperty,
EnumProperty,
FloatProperty,
FloatVectorProperty,
IntProperty,
PointerProperty,
StringProperty,
)
from bpy.types import PropertyGroup
@@ -34,7 +31,7 @@ from bpy.types import PropertyGroup
import bonsai.core.brick as core
import bonsai.tool.brick as tool
from bonsai.bim.module.brick.data import BrickschemaData, BrickschemaReferencesData
from bonsai.bim.prop import Attribute, StrProperty
from bonsai.bim.prop import StrProperty
from bonsai.tool.brick import BrickStore
+12 -1
View File
@@ -16,9 +16,18 @@
# You should have received a copy of the GNU General Public License
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
from __future__ import annotations
from typing import TYPE_CHECKING
import bpy
from bpy.types import Panel, UIList
import bonsai.tool as tool
if TYPE_CHECKING:
from bonsai.bim.module.brick.prop import Brick
from bonsai.bim.helper import prop_with_search
from bonsai.bim.module.brick.data import BrickschemaData, BrickschemaReferencesData
from bonsai.tool.brick import BrickStore
@@ -274,7 +283,9 @@ class BIM_PT_brickschema_viewport(Panel):
class BIM_UL_bricks(UIList):
split_screen = False
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
def draw_item(
self, context, layout: bpy.types.UILayout, data, item: Brick, icon, active_data, active_propname
) -> None:
if item:
split = layout.split(factor=0.85, align=True)
row = split.row()
@@ -16,13 +16,8 @@
# You should have received a copy of the GNU General Public License
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
import bpy
import ifcopenshell
import ifcopenshell.util.classification
import ifcopenshell.util.date
import bonsai.tool as tool
from bonsai.bim.ifc import IfcStore
def refresh():
@@ -19,7 +19,6 @@ import textwrap
from typing import Any
import bpy
import bsdd
import ifcopenshell.api.pset
import ifcopenshell.util.element
+1 -4
View File
@@ -23,10 +23,7 @@ from bpy.props import (
BoolProperty,
CollectionProperty,
EnumProperty,
FloatProperty,
FloatVectorProperty,
IntProperty,
PointerProperty,
StringProperty,
)
from bpy.types import PropertyGroup
@@ -34,7 +31,7 @@ from bpy.types import PropertyGroup
import bonsai.tool as tool
from bonsai.bim.module.bsdd.data import BSDDData
from bonsai.bim.module.classification.data import ClassificationsData
from bonsai.bim.prop import Attribute, StrProperty
from bonsai.bim.prop import Attribute
def get_active_dictionary(self: "BIMBSDDProperties", context: object) -> tool.Blender.BLENDER_ENUM_ITEMS:
+1 -3
View File
@@ -17,13 +17,11 @@
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
import math
from math import cos, pi, radians, sin, sqrt
from typing import Union
from math import pi, sqrt
import bmesh
import bpy
import bpy_extras
import ifcopenshell.util.unit
import mathutils
from mathutils import Matrix, Vector
-2
View File
@@ -22,8 +22,6 @@ from typing import TYPE_CHECKING
import bpy
from bpy.types import PropertyGroup
from bonsai.bim.module.model.data import AuthoringData
class BIMCadProperties(PropertyGroup):
resolution: bpy.props.IntProperty(name="Arc Resolution", min=1, default=1)
@@ -20,12 +20,10 @@ import os
from functools import partial
import bpy
import ifcopenshell.util.unit
from bpy.types import WorkSpaceTool
import bonsai.bim.module.type.prop as type_prop
import bonsai.tool as tool
from bonsai.bim.module.model.data import AuthoringData, RailingData, RoofData
from bonsai.bim.module.model.data import RailingData, RoofData
def load_custom_icons():
@@ -18,9 +18,6 @@
import json
import bpy
import ifcopenshell.util.element
import bonsai.tool as tool
@@ -17,7 +17,6 @@
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
import blf
import bmesh
import gpu
from bpy.types import SpaceView3D
from bpy_extras.view3d_utils import location_3d_to_region_2d
@@ -18,16 +18,13 @@
import json
import logging
import os
import tempfile
from math import radians
from pathlib import Path
from typing import TYPE_CHECKING
import bmesh
import bpy
import ifcopenshell
import numpy as np
from bpy_extras.io_utils import ExportHelper, ImportHelper
from mathutils import Matrix, Vector
@@ -460,9 +457,7 @@ class HideClash(bpy.types.Operator):
def execute(self, context):
ClashDecorator.uninstall()
for area in context.screen.areas:
if area.type == "VIEW_3D":
area.tag_redraw()
tool.Blender.update_all_viewports(context)
return {"FINISHED"}
+1 -2
View File
@@ -26,7 +26,6 @@ from bpy.props import (
FloatProperty,
FloatVectorProperty,
IntProperty,
PointerProperty,
StringProperty,
)
from bpy.types import PropertyGroup
@@ -34,7 +33,7 @@ from ifcopenshell.geom.main import CLASH_TYPE_ITEMS, ClashType
from mathutils import Vector
import bonsai.tool as tool
from bonsai.bim.prop import Attribute, BIMFilterGroup, StrProperty
from bonsai.bim.prop import BIMFilterGroup, StrProperty
class ClashSource(PropertyGroup):
@@ -18,7 +18,6 @@
import bpy
import ifcopenshell
import ifcopenshell.api
import ifcopenshell.api.classification
import ifcopenshell.api.pset
import ifcopenshell.util.classification
@@ -23,10 +23,7 @@ from bpy.props import (
BoolProperty,
CollectionProperty,
EnumProperty,
FloatProperty,
FloatVectorProperty,
IntProperty,
PointerProperty,
StringProperty,
)
from bpy.types import PropertyGroup
@@ -25,7 +25,6 @@ import ifcopenshell.util.classification
from bpy.types import Panel, UIList
import bonsai.bim.helper
import bonsai.bim.module.classification.prop as classification_prop
import bonsai.tool as tool
from bonsai.bim.module.classification.data import (
ClassificationsData,
@@ -19,7 +19,6 @@
from typing import TYPE_CHECKING
import bpy
import ifcopenshell.api
import ifcopenshell.api.constraint
import bonsai.bim.helper
@@ -20,19 +20,13 @@ from typing import TYPE_CHECKING, Literal
import bpy
from bpy.props import (
BoolProperty,
CollectionProperty,
EnumProperty,
FloatProperty,
FloatVectorProperty,
IntProperty,
PointerProperty,
StringProperty,
)
from bpy.types import PropertyGroup
from ifcopenshell.util.doc import get_entity_doc
import bonsai.tool as tool
from bonsai.bim.module.constraint.data import ConstraintsData
from bonsai.bim.prop import Attribute
@@ -18,7 +18,6 @@
from typing import Any
import bpy
import ifcopenshell
import bonsai.tool as tool
+1 -7
View File
@@ -20,19 +20,13 @@ from typing import TYPE_CHECKING
import bpy
from bpy.props import (
BoolProperty,
CollectionProperty,
EnumProperty,
FloatProperty,
FloatVectorProperty,
IntProperty,
PointerProperty,
StringProperty,
)
from bpy.types import PropertyGroup
from bonsai.bim.module.context.data import ContextData
from bonsai.bim.prop import Attribute, StrProperty
from bonsai.bim.prop import Attribute
class BIMContextProperties(PropertyGroup):
@@ -18,13 +18,11 @@
from typing import Any, Union
import bpy
import ifcopenshell
import ifcopenshell.util.cost
import ifcopenshell.util.date
import ifcopenshell.util.element
import ifcopenshell.util.unit
from ifcopenshell.util.doc import get_entity_doc, get_predefined_type_doc
import bonsai.tool as tool
@@ -987,10 +987,10 @@ class ExportCostSchedulesToPDF(bpy.types.Operator, ExportHelper):
@classmethod
def poll(cls, context):
try:
import typst
import typst # noqa: F401
return True
except:
except ModuleNotFoundError:
cls.poll_message_set(
"Typst not available.\nIt can be installed from Quality and\nControl -> Debug and using 'typst' with Pip Install.\n(Run Blender as Administrator)"
)
@@ -19,16 +19,13 @@
from typing import TYPE_CHECKING, Literal, Union
import bpy
import ifcopenshell.api
import ifcopenshell.api.cost
from bpy.props import (
BoolProperty,
CollectionProperty,
EnumProperty,
FloatProperty,
FloatVectorProperty,
IntProperty,
PointerProperty,
StringProperty,
)
from bpy.types import PropertyGroup
+44 -15
View File
@@ -26,10 +26,11 @@ from bpy.types import Panel, UIList
import bonsai.bim.helper
import bonsai.bim.module.cost.prop as CostProp
import bonsai.tool as tool
from bonsai.bim.module.cost.data import CostSchedulesData
from bonsai.bim.module.cost.data import CostItem, CostSchedulesData
if TYPE_CHECKING:
from bonsai.bim.module.cost.prop import BIMCostProperties, CostItemQuantity
from bonsai.bim.prop import StrProperty
class BIM_PT_cost_schedules(Panel):
@@ -398,8 +399,8 @@ class BIM_PT_cost_item_types(Panel):
op = row2.operator("bim.calculate_cost_item_resource_value", text="", icon="DISC")
op.cost_item = cost_item.ifc_definition_id
rtprops = context.scene.BIMResourceTreeProperties
rprops = tool.Resource.get_resource_props()
rtprops = rprops.tree
if rtprops.resources and rprops.active_resource_index < len(rtprops.resources):
if has_quantity_names:
op = row2.operator("bim.assign_cost_item_quantity", text="", icon="PROPERTIES")
@@ -661,9 +662,18 @@ class BIM_UL_cost_items_trait:
split2.alignment = "LEFT"
split2.label(text="Rate")
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
def draw_item(
self,
context,
layout: bpy.types.UILayout,
data: BIMCostProperties,
item: CostProp.CostItem,
icon,
active_data,
active_propname,
) -> None:
if item:
self.props = tool.Cost.get_cost_props()
self.props = data
cost_item = CostSchedulesData.data["cost_items"][item.ifc_definition_id]
row = layout.row(align=True)
@@ -694,7 +704,7 @@ class BIM_UL_cost_items_trait:
# TODO: reimplement "bim.copy_cost_item_values" somewhere with better UX
def draw_parent_operator(self, row, cost_item_id):
def draw_parent_operator(self, row: bpy.types.UILayout, cost_item_id: int) -> None:
if self.props.active_cost_item_id:
if self.props.active_cost_item_id != cost_item_id:
op = row.operator("bim.change_parent_cost_item", text="", icon="LINKED", emboss=False).new_parent = (
@@ -703,7 +713,7 @@ class BIM_UL_cost_items_trait:
else:
row.label(text="", icon="BLANK1")
def draw_hierarchy(self, row, item):
def draw_hierarchy(self, row: bpy.types.UILayout, item: CostProp.CostItem) -> None:
for i in range(0, item.level_index):
row.label(text="", icon="BLANK1")
if item.has_children:
@@ -749,7 +759,7 @@ class BIM_UL_cost_items_trait:
else:
row.label(text="-")
def draw_value_column(self, layout, cost_item):
def draw_value_column(self, layout: bpy.types.UILayout, cost_item: CostItem) -> None:
if cost_item["TotalAppliedValue"]:
text = "{0:,.2f}".format(cost_item["TotalAppliedValue"]).replace(",", " ")
if cost_item["UnitBasisValueComponent"] not in [None, 1]:
@@ -760,13 +770,13 @@ class BIM_UL_cost_items_trait:
else:
layout.label(text="-")
def draw_total_cost_column(self, layout, cost_item):
def draw_total_cost_column(self, layout: bpy.types.UILayout, cost_item: CostItem) -> None:
format_numbers = "{0:,.2f}".format(cost_item["TotalCost"]).replace(",", " ")
currency = CostSchedulesData.data["currency"]
text = "{} {}".format(format_numbers, currency["name"]) if currency else format_numbers
layout.label(text=text)
def draw_order_operator(self, row, ifc_definition_id, cost_item):
def draw_order_operator(self, row: bpy.types.UILayout, ifc_definition_id: int, cost_item: CostItem) -> None:
if cost_item["NestingIndex"] is not None:
if cost_item["NestingIndex"] == 0:
op = row.operator("bim.reorder_cost_item_nesting", icon="TRIA_DOWN", text="")
@@ -793,12 +803,14 @@ class BIM_UL_cost_item_rates(BIM_UL_cost_items_trait, UIList):
def draw_quantity_column(self, layout, cost_item):
self.draw_uom_column(layout, cost_item)
def draw_total_cost_column(self, layout, cost_item):
def draw_total_cost_column(self, layout: bpy.types.UILayout, cost_item: CostItem) -> None:
pass # No such thing as a total cost in a schedule of rates
class BIM_UL_cost_columns(UIList):
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
def draw_item(
self, context, layout: bpy.types.UILayout, data, item: StrProperty, icon, active_data, active_propname
) -> None:
if item:
row = layout.row(align=True)
row.prop(item, "name", emboss=False, text="")
@@ -806,9 +818,17 @@ class BIM_UL_cost_columns(UIList):
class BIM_UL_cost_item_types(UIList):
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
props = tool.Cost.get_cost_props()
cost_item = props.cost_items[props.active_cost_item_index]
def draw_item(
self,
context,
layout: bpy.types.UILayout,
data: BIMCostProperties,
item: CostProp.CostItemType,
icon,
active_data,
active_propname,
) -> None:
cost_item = data.cost_items[data.active_cost_item_index]
if item:
row = layout.row(align=True)
@@ -844,7 +864,16 @@ class BIM_UL_cost_item_quantities(UIList):
class BIM_UL_product_cost_items(UIList):
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
def draw_item(
self,
context,
layout: bpy.types.UILayout,
data,
item: CostItemQuantity,
icon,
active_data,
active_propname,
) -> None:
if item:
row = layout.row(align=True)
op = row.operator("bim.highlight_product_cost_item", text="", icon="STYLUS_PRESSURE")
@@ -21,7 +21,6 @@ import os
from functools import partial
import bpy
import ifcopenshell
from bpy.types import WorkSpaceTool
import bonsai.tool as tool
@@ -20,7 +20,6 @@ import json
from math import atan2, degrees
import bpy
import ifcopenshell
import ifcopenshell.util.element
import bonsai.tool as tool
@@ -19,14 +19,10 @@
from __future__ import annotations
import json
import logging
import os
import tempfile
from collections import Counter
from typing import TYPE_CHECKING
import bpy
import ifccsv
import ifcopenshell
import ifcopenshell.util.selector
from bpy_extras.io_utils import ExportHelper, ImportHelper
+1 -5
View File
@@ -23,15 +23,11 @@ from bpy.props import (
BoolProperty,
CollectionProperty,
EnumProperty,
FloatProperty,
FloatVectorProperty,
IntProperty,
PointerProperty,
StringProperty,
)
from bpy.types import PropertyGroup
from bonsai.bim.prop import BIMFilterGroup, StrProperty
from bonsai.bim.prop import BIMFilterGroup
class CsvAttribute(PropertyGroup):
@@ -29,7 +29,6 @@ from typing import TYPE_CHECKING, Any, Literal, Union, assert_never, get_args
import bpy
import ifcopenshell
import ifcopenshell.api
import ifcopenshell.api.pset
import ifcopenshell.geom
import ifcopenshell.ifcopenshell_wrapper as W
@@ -20,13 +20,9 @@ from typing import TYPE_CHECKING, Literal, get_args
import bpy
from bpy.props import (
BoolProperty,
CollectionProperty,
EnumProperty,
FloatProperty,
FloatVectorProperty,
IntProperty,
PointerProperty,
StringProperty,
)
from bpy.types import PropertyGroup
@@ -32,18 +32,10 @@
from typing import TYPE_CHECKING
import bpy
# Properties have many different data types. We won't use all of them in this
# demo module, but this is a list for your reference.
from bpy.props import (
BoolProperty,
CollectionProperty,
EnumProperty,
FloatProperty,
FloatVectorProperty,
IntProperty,
PointerProperty,
StringProperty,
)
from bpy.types import PropertyGroup
@@ -98,8 +98,8 @@ class VisualiseDiff(bpy.types.Operator):
obj.color = (0.0, 1.0, 0.0, 1.0)
elif global_id in diff["changed"]:
obj.color = (0.0, 0.0, 1.0, 1.0)
area = next(area for area in context.screen.areas if area.type == "VIEW_3D")
area.spaces[0].shading.color_type = "OBJECT"
assert (space := tool.Blender.get_view3d_space())
space.shading.color_type = "OBJECT"
return {"FINISHED"}
+1 -5
View File
@@ -23,16 +23,12 @@ from bpy.props import (
BoolProperty,
CollectionProperty,
EnumProperty,
FloatProperty,
FloatVectorProperty,
IntProperty,
PointerProperty,
StringProperty,
)
from bpy.types import PropertyGroup
from bonsai.bim.module.diff.data import DiffData
from bonsai.bim.prop import BIMFilterGroup, StrProperty
from bonsai.bim.prop import BIMFilterGroup
def update_diff_json_file(self: "DiffProperties", context: bpy.types.Context) -> None:
@@ -19,8 +19,6 @@
import os
import bpy
import ifcopenshell
import ifcopenshell.util.schema
from natsort import natsorted
import bonsai.tool as tool
@@ -19,11 +19,11 @@
import json
import bpy
import ifcopenshell.util.element
import bonsai.bim.handler
import bonsai.core.document as core
import bonsai.tool as tool
from bonsai.bim.module.document.data import DocumentData, ObjectDocumentData
from bonsai.bim.module.document.data import ObjectDocumentData
class LoadProjectDocuments(bpy.types.Operator):
@@ -1,21 +1,18 @@
from typing import TYPE_CHECKING, Union
from typing import TYPE_CHECKING, Literal, Union
import bpy
from bpy.props import (
BoolProperty,
CollectionProperty,
EnumProperty,
FloatProperty,
FloatVectorProperty,
IntProperty,
PointerProperty,
StringProperty,
)
from bpy.types import PropertyGroup
import bonsai.tool as tool
from bonsai.bim.module.document.data import DocumentData, refresh
from bonsai.bim.prop import Attribute, StrProperty
from bonsai.bim.prop import Attribute
def update_document_name(self: "Document", context: bpy.types.Context) -> None:
@@ -69,7 +66,7 @@ class Document(PropertyGroup):
tree_depth: int
has_children: bool
is_expanded: bool
document_type: str
document_type: Literal["PROJECT", "INFORMATION", "REFERENCE"]
class DocumentObject(PropertyGroup):
+33 -6
View File
@@ -16,10 +16,22 @@
# You should have received a copy of the GNU General Public License
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
from __future__ import annotations
from typing import TYPE_CHECKING
import bpy
from bpy.types import Panel, UIList
import bonsai.tool as tool
if TYPE_CHECKING:
from bonsai.bim.module.document.prop import (
BIMDocumentProperties,
Document,
DocumentObject,
)
from bonsai.bim.helper import draw_attributes
from bonsai.bim.module.document.data import DocumentData, ObjectDocumentData
@@ -208,7 +220,16 @@ class BIM_PT_object_documents(Panel):
class BIM_UL_documents(UIList):
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
def draw_item(
self,
context,
layout: bpy.types.UILayout,
data: BIMDocumentProperties,
item: Document,
icon,
active_data,
active_propname,
) -> None:
if item:
row = layout.row(align=True)
indent_depth = 0
@@ -253,16 +274,22 @@ class BIM_UL_documents(UIList):
class BIM_UL_document_objects(UIList):
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
def draw_item(
self,
context,
layout: bpy.types.UILayout,
data: BIMDocumentProperties,
item: DocumentObject,
icon,
active_data,
active_propname,
) -> None:
if item:
row = layout.row(align=True)
row.prop(item, "name", text="", emboss=False, icon="OBJECT_DATA")
row.operator("bim.select_object", text="", icon="RESTRICT_SELECT_OFF").obj_name = item.name
props = tool.Document.get_document_props()
if props.active_document:
document = props.active_document
if document := data.active_document:
op = row.operator("bim.unassign_document", text="", icon="X")
op.document = document.ifc_definition_id
op.obj = item.name
@@ -18,15 +18,12 @@
from __future__ import annotations
import math
import os
from pathlib import Path
from typing import Optional
import bmesh
import bpy
import ifcopenshell.util.element
from mathutils import Matrix, Vector
from mathutils import Vector
import bonsai.tool as tool
+2 -2
View File
@@ -22,9 +22,9 @@ from pathlib import Path
from typing import Any, Union
import bpy
import ifcopenshell.util.classification
import ifcopenshell.util.element
import ifcopenshell.util.representation
import ifcopenshell.util.selector
import ifcopenshell.util.placement
import ifcopenshell.util.unit
from natsort import natsorted
@@ -23,7 +23,7 @@ from functools import cache
from math import acos, atan, cos, degrees, pi, radians, sin
from pathlib import Path
from timeit import default_timer as timer
from typing import Optional, Union
from typing import Optional
import blf
import bmesh
@@ -34,7 +34,6 @@ import ifcopenshell.util.element
import ifcopenshell.util.representation
import ifcopenshell.util.unit
import numpy as np
import shapely
from bpy.types import SpaceView3D
from bpy_extras.view3d_utils import location_3d_to_region_2d
from gpu_extras.batch import batch_for_shader
@@ -71,9 +70,9 @@ class profile_consequential:
cls.start_time = None
lines = "\n".join(cls.lines)
print(lines)
import pyperclip
pyperclip.copy(lines)
assert (wm := bpy.context.window_manager)
wm.clipboard = lines
cls.lines = []
@@ -151,7 +151,7 @@ from bpy_extras.view3d_utils import (
)
from gpu_extras.batch import batch_for_shader
from ifcopenshell.util.unit import si_conversions
from mathutils import Matrix, Vector
from mathutils import Matrix, Vector, geometry
from mathutils.geometry import intersect_line_line
from mathutils.kdtree import KDTree
@@ -1243,9 +1243,7 @@ class SnapManager:
@staticmethod
def _redraw_viewport() -> None:
"""Force 3D viewport redraw."""
for area in bpy.context.screen.areas:
if area.type == "VIEW_3D":
area.tag_redraw()
tool.Blender.update_all_viewports()
def build_snap_cache(
self, context: bpy.types.Context, active_obj: bpy.types.Object, include_active: bool = False
@@ -17,10 +17,8 @@
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
import math
from typing import Union
import bpy
import ifcopenshell
import ifcopenshell.util.element
import ifcopenshell.util.unit
import mathutils.geometry
+105 -189
View File
@@ -18,9 +18,9 @@
import hashlib
import json
import logging
import multiprocessing
import os
import re
import shutil
import subprocess
import time
@@ -41,8 +41,8 @@ from typing import (
import bmesh
import bpy
import ifcopenshell
import ifcopenshell.api
import ifcopenshell.api.document
import ifcopenshell.api.geometry
import ifcopenshell.api.pset
import ifcopenshell.api.style
import ifcopenshell.geom
@@ -50,19 +50,18 @@ import ifcopenshell.ifcopenshell_wrapper
import ifcopenshell.util.element
import ifcopenshell.util.representation
import ifcopenshell.util.selector
import ifcopenshell.util.shape_builder
import ifcopenshell.util.unit
import numpy as np
import shapely
import shapely.ops
from bpy_extras.image_utils import load_image
from bpy_extras.io_utils import ImportHelper
from lxml import etree
from mathutils import Color, Matrix, Vector
from mathutils import Color, Vector
import bonsai.bim.export_ifc
import bonsai.bim.handler
import bonsai.bim.helper
import bonsai.bim.module.drawing.annotation as annotation
import bonsai.bim.import_ifc
import bonsai.bim.module.drawing.sheeter as sheeter
import bonsai.bim.module.drawing.svgwriter as svgwriter
import bonsai.core.drawing as core
@@ -138,7 +137,7 @@ class AddAnnotationType(bpy.types.Operator, tool.Ifc.Operator):
element.ApplicableOccurrence = f"IfcAnnotation/{object_type}"
if props.create_representation_for_type and object_type == "IMAGE":
bpy.ops.bim.add_reference_image("INVOKE_DEFAULT", use_existing_object_by_name=obj.name)
bpy.ops.bim.add_reference_image("INVOKE_DEFAULT", existing_object_by_name=obj.name)
class EnableAddAnnotationType(bpy.types.Operator):
@@ -928,7 +927,7 @@ class CreateDrawing(bpy.types.Operator):
props = tool.Project.get_project_props()
for link in props.get_loaded_links_for_drawings():
files[link.name] = self.get_linked_file(link)
files[link.filepath] = self.get_linked_file(link)
target_view = ifcopenshell.util.element.get_psets(self.camera_element)["EPset_Drawing"]["TargetView"]
self.setup_serialiser(target_view)
@@ -1374,7 +1373,7 @@ class CreateDrawing(bpy.types.Operator):
return True
def get_linked_file(self, link: "Link") -> ifcopenshell.file:
link_path = link.name
link_path = link.filepath
ifc_file = IfcStore.session_files.get(link_path, None)
if ifc_file is not None:
return ifc_file
@@ -1759,7 +1758,7 @@ class AddAnnotation(bpy.types.Operator, tool.Ifc.Operator):
enable_editing=True,
)
if props.object_type == "IMAGE":
bpy.ops.bim.add_reference_image("INVOKE_DEFAULT", use_existing_object_by_name=obj.name)
bpy.ops.bim.add_reference_image("INVOKE_DEFAULT", existing_object_by_name=obj.name)
class AddSheet(bpy.types.Operator, tool.Ifc.Operator):
@@ -2896,12 +2895,16 @@ class AddSchedule(bpy.types.Operator, tool.Ifc.Operator, ImportHelper):
bl_options = {"REGISTER", "UNDO"}
bl_description = "Add an .ods, .xls or .xlsx file as a schedule"
files: bpy.props.CollectionProperty(name="Files", type=bpy.types.OperatorFileListElement)
directory: bpy.props.StringProperty(subtype="DIR_PATH")
filter_glob: bpy.props.StringProperty(default="*.ods;*.xls;*.xlsx", options={"HIDDEN"})
use_relative_path: bpy.props.BoolProperty(name="Use Relative Path", default=True)
def _execute(self, context):
filepath = tool.Ifc.get_uri(self.filepath, use_relative_path=self.use_relative_path)
core.add_document(tool.Ifc, tool.Drawing, "SCHEDULE", uri=filepath)
for filepath in tool.Blender.get_selected_files(
self.directory, self.files, use_relative_path=self.use_relative_path
):
core.add_document(tool.Ifc, tool.Drawing, "SCHEDULE", uri=filepath)
class RemoveSchedule(bpy.types.Operator, tool.Ifc.Operator):
@@ -3090,23 +3093,16 @@ class AddReference(bpy.types.Operator, tool.Ifc.Operator, ImportHelper):
bl_description = "Import a .svg file to the project as a reference"
bl_options = {"REGISTER", "UNDO"}
files: bpy.props.CollectionProperty(name="Files", type=bpy.types.OperatorFileListElement)
directory: bpy.props.StringProperty(subtype="DIR_PATH")
filter_glob: bpy.props.StringProperty(default="*.svg", options={"HIDDEN"})
use_relative_path: bpy.props.BoolProperty(name="Use Relative Path", default=True)
filename_ext = ".svg"
files: bpy.props.CollectionProperty(type=bpy.types.OperatorFileListElement)
directory: bpy.props.StringProperty(subtype="DIR_PATH")
def _execute(self, context):
# Handle both single and multiple file selection
if self.files:
for file_elem in self.files:
filepath = os.path.join(self.directory, file_elem.name)
uri = tool.Ifc.get_uri(filepath, use_relative_path=self.use_relative_path)
core.add_document(tool.Ifc, tool.Drawing, "REFERENCE", uri=uri)
else:
# Fallback for single file (backward compatibility)
filepath = tool.Ifc.get_uri(self.filepath, use_relative_path=self.use_relative_path)
for filepath in tool.Blender.get_selected_files(
self.directory, self.files, use_relative_path=self.use_relative_path
):
core.add_document(tool.Ifc, tool.Drawing, "REFERENCE", uri=filepath)
@@ -3165,6 +3161,7 @@ class EditTextPopup(bpy.types.Operator):
bpy.ops.bim.disable_editing_text()
def execute(self, context):
# TODO: check for possible subtle undo bug here
# can't use invoke() because this operator
# will be run indirectly by hotkey
# so we use execute() and track whether it's the first run of the operator
@@ -3804,83 +3801,51 @@ class AddReferenceImage(bpy.types.Operator, tool.Ifc.Operator, ImportHelper):
use_relative_path: bpy.props.BoolProperty(name="Use Relative Path", default=True)
filter_image: bpy.props.BoolProperty(default=True, options={"HIDDEN", "SKIP_SAVE"})
filter_folder: bpy.props.BoolProperty(default=True, options={"HIDDEN", "SKIP_SAVE"})
override_existing_image: bpy.props.BoolProperty(
name="Override Existing Image",
default=True,
description=(
"Override image if it was previously loaded to Blender. If disabled, will always create a new image"
),
)
use_existing_object_by_name: bpy.props.StringProperty(
name="Use Existing Object By Name",
description="Existing object name to add a style with reference image to. If not provided will create a new object.",
options={"SKIP_SAVE"},
)
x_length: bpy.props.FloatProperty(
name="X Length",
description="Width of the reference image in project units",
description="Width of the reference image",
default=1.0,
min=0.001,
soft_min=0.01,
precision=3,
unit="LENGTH",
)
y_length: bpy.props.FloatProperty(
name="Y Length",
description="Height of the reference image in project units",
description="Height of the reference image",
default=1.0,
min=0.001,
soft_min=0.01,
precision=3,
unit="LENGTH",
)
show_texture_solid_mode: bpy.props.BoolProperty(
name="Show Texture in Solid mode (slow)",
description="Show Texture in Solid mode (slow)",
default=False,
)
show_dimensions_dialog: bpy.props.BoolProperty(default=False, options={"HIDDEN", "SKIP_SAVE"})
def draw(self, context):
layout = self.layout
if getattr(self, "show_dimensions_dialog", False):
if tool.Ifc.get():
length_unit = ifcopenshell.util.unit.get_project_unit(tool.Ifc.get(), "LENGTHUNIT")
if length_unit:
unit_name = ifcopenshell.util.unit.get_full_unit_name(length_unit).lower()
else:
unit_name = "project units"
layout.label(text=f"Set Reference Image Dimensions (in {unit_name}):")
else:
layout.label(text="Set Reference Image Dimensions (in project units):")
layout.separator()
layout.prop(self, "x_length")
layout.prop(self, "y_length")
else:
if Path(tool.Ifc.get_path()).is_file():
layout.prop(self, "use_relative_path")
else:
self.use_relative_path = False
layout.label(text="Save the .ifc file first ")
layout.label(text="to use relative paths.")
layout.prop(self, "override_existing_image")
layout.prop(self, "use_existing_object_by_name")
@classmethod
def poll(cls, context):
if not tool.Ifc.get():
cls.poll_message_set("No IFC project is loaded.")
return False
return True
def invoke(self, context, event):
if not getattr(self, "show_dimensions_dialog", False):
context.window_manager.fileselect_add(self)
return {"RUNNING_MODAL"}
else:
return context.window_manager.invoke_props_dialog(self)
self._last_filepath = ""
return super().invoke(context, event)
def check(self, context):
if not hasattr(self, "_last_filepath"):
self._last_filepath = ""
if self.filepath and self.filepath != self._last_filepath:
self._last_filepath = self.filepath
def execute(self, context):
if not getattr(self, "show_dimensions_dialog", False):
abs_path = Path(self.filepath).absolute().resolve()
if self.override_existing_image:
params = {"check_existing": True, "force_reload": True}
else:
params = {"check_existing": False}
try:
image = load_image(abs_path.name, str(abs_path.parent), **params)
if abs_path.exists() and abs_path.is_file():
image = load_image(abs_path.name, str(abs_path.parent), check_existing=False)
image_width_px = image.size[0]
image_height_px = image.size[1]
aspect_ratio = image_width_px / image_height_px
@@ -3893,17 +3858,23 @@ class AddReferenceImage(bpy.types.Operator, tool.Ifc.Operator, ImportHelper):
self.y_length = 1.0
bpy.data.images.remove(image)
return True
except Exception as e:
self.report({"ERROR"}, f"Failed to load image: {str(e)}")
return {"CANCELLED"}
return False
self.show_dimensions_dialog = True
return context.window_manager.invoke_props_dialog(self)
return self._execute(context)
def draw(self, context):
layout = self.layout
if Path(tool.Ifc.get_path()).is_file():
layout.prop(self, "use_relative_path")
else:
self.use_relative_path = False
layout.prop(self, "show_texture_solid_mode")
layout.prop(self, "x_length")
layout.prop(self, "y_length")
def _execute(self, context):
project_props = tool.Project.get_project_props()
project_props.load_indexed_maps = self.show_texture_solid_mode
space = tool.Blender.get_view3d_space()
if space.shading.color_type != "TEXTURE":
space.shading.color_type = "TEXTURE"
@@ -3916,121 +3887,66 @@ class AddReferenceImage(bpy.types.Operator, tool.Ifc.Operator, ImportHelper):
image_filepath = Path(tool.Ifc.get_uri(self.filepath, use_relative_path=self.use_relative_path))
ifc_file = tool.Ifc.get()
if self.override_existing_image:
params = {"check_existing": True, "force_reload": True}
else:
params = {"check_existing": False}
params = {"check_existing": False}
image = load_image(abs_path.name, str(abs_path.parent), **params)
def bm_add_image_plane(mesh):
bm = tool.Blender.get_bmesh_for_mesh(mesh, clean=True)
mesh = bpy.data.meshes.new(image_filepath.stem)
obj = bpy.data.objects.new(image_filepath.stem, mesh)
element = tool.Drawing.run_root_assign_class(
obj=obj, ifc_class="IfcAnnotation", predefined_type="IMAGE", should_add_representation=False
)
unit_scale = ifcopenshell.util.unit.calculate_unit_scale(ifc_file)
plane_scale = Vector((self.x_length * unit_scale / 2.0, self.y_length * unit_scale / 2.0, 1.0))
matrix = Matrix.LocRotScale(None, None, plane_scale)
bmesh.ops.create_grid(bm, x_segments=1, y_segments=1, size=1, matrix=matrix, calc_uvs=False)
builder = ifcopenshell.util.shape_builder.ShapeBuilder(ifc_file)
unit_scale = ifcopenshell.util.unit.calculate_unit_scale(ifc_file)
hx = self.x_length * 0.5 / unit_scale
hy = self.y_length * 0.5 / unit_scale
verts = [(-hx, -hy, 0.0), (hx, -hy, 0.0), (hx, hy, 0.0), (-hx, hy, 0.0)]
item = builder.mesh(verts, [[0, 1, 2, 3]])
if not bm.loops.layers.uv:
uv_layer = bm.loops.layers.uv.new()
else:
uv_layer = bm.loops.layers.uv.active
ifc_context = ifcopenshell.util.representation.get_context(ifc_file, "Model", "Body", "MODEL_VIEW")
representation = builder.get_representation(ifc_context, [item])
ifcopenshell.api.geometry.assign_representation(ifc_file, element, representation)
min_x = min(v.co.x for v in bm.verts)
max_x = max(v.co.x for v in bm.verts)
min_y = min(v.co.y for v in bm.verts)
max_y = max(v.co.y for v in bm.verts)
width = max_x - min_x
height = max_y - min_y
for face in bm.faces:
for loop in face.loops:
vert = loop.vert
u = (vert.co.x - min_x) / width if width > 0 else 0.5
v = (vert.co.y - min_y) / height if height > 0 else 0.5
u = max(0.0, min(1.0, u))
v = max(0.0, min(1.0, v))
loop[uv_layer].uv = (u, v)
tool.Blender.apply_bmesh(mesh, bm)
if self.use_existing_object_by_name:
obj = bpy.data.objects[self.use_existing_object_by_name]
bm_add_image_plane(obj.data)
bpy.ops.bim.update_representation(obj=obj.name, ifc_representation_class="")
else:
temp_mesh = bpy.data.meshes.new("temp_mesh")
bm_add_image_plane(temp_mesh)
obj = bpy.data.objects.new(image_filepath.stem, temp_mesh)
tool.Drawing.run_root_assign_class(
obj=obj,
ifc_class="IfcAnnotation",
predefined_type="IMAGE",
should_add_representation=True,
context=ifcopenshell.util.representation.get_context(ifc_file, "Model", "Body", "MODEL_VIEW"),
ifc_representation_class=None,
)
tool.Blender.remove_data_block(temp_mesh)
element = tool.Ifc.get_entity(obj)
if element and isinstance(obj.data, bpy.types.Mesh):
representation = ifcopenshell.util.representation.get_representation(element, "Model", "Body", "MODEL_VIEW")
if representation and representation.Items:
item_id = representation.Items[0].id()
num_faces = len(obj.data.polygons)
obj.data["ios_item_ids"] = [item_id] * num_faces
tool.Blender.Attribute.fill_attribute(obj.data, "ios_item_ids", "FACE", "INT", [item_id] * num_faces)
for item in representation.Items:
if item.is_a("IfcPolygonalFaceSet") and item.Coordinates:
new_coords = []
for vertex in obj.data.vertices:
co = obj.matrix_world @ vertex.co
new_coords.append([co.x, co.y, co.z])
item.Coordinates.CoordList = new_coords
tool.Blender.set_active_object(obj)
material = bpy.data.materials.new(name=image_filepath.stem)
obj.data.materials.append(None) # new slot
obj.material_slots[0].material = material
bpy.ops.bim.add_style()
style = tool.Ifc.get_entity(material)
assert style
tool.Style.assign_style_to_object(style, obj)
style = ifcopenshell.api.style.add_style(tool.Ifc.get(), name=image_filepath.stem)
ifcopenshell.api.style.assign_representation_styles(
ifc_file, shape_representation=representation, styles=[style]
)
# TODO: IfcSurfaceStyleRendering is unnecessary here, added it only because
# we don't support IfcSurfaceStyleWithTextures without Rendering yet
shading_attributes = {
"SurfaceColour": {
"Red": 1.0,
"Green": 1.0,
"Blue": 1.0,
},
"SurfaceColour": {"Red": 1.0, "Green": 1.0, "Blue": 1.0},
"Transparency": 0.0,
"ReflectanceMethod": "NOTDEFINED",
}
ifcopenshell.api.style.add_surface_style(
tool.Ifc.get(),
style=style,
ifc_class="IfcSurfaceStyleRendering",
attributes=shading_attributes,
tool.Ifc.get(), style=style, ifc_class="IfcSurfaceStyleRendering", attributes=shading_attributes
)
texture = ifc_file.create_entity("IfcImageTexture", Mode="DIFFUSE", URLReference=image_filepath.as_posix())
textures = [texture]
ifc_file.create_entity("IfcTextureCoordinateGenerator", Maps=textures, Mode="COORD") # UV map
ifcopenshell.api.style.add_surface_style(
ifc_file,
style=style,
ifc_class="IfcSurfaceStyleWithTextures",
attributes={"Textures": textures},
)
tool.Style.reload_material_from_ifc(material)
tool.Geometry.record_object_materials(obj)
return {"FINISHED"}
if tool.Ifc.get_schema() == "IFC2X3":
texture = ifc_file.create_entity(
"IfcImageTexture",
RepeatS=True,
RepeatT=True,
TextureType="TEXTURE",
UrlReference=image_filepath.as_posix(),
)
else:
texture = ifc_file.create_entity("IfcImageTexture", Mode="DIFFUSE", URLReference=image_filepath.as_posix())
ifc_file.create_entity("IfcTextureCoordinateGenerator", Maps=[texture], Mode="COORD")
textures = [texture]
ifcopenshell.api.style.add_surface_style(
ifc_file, style=style, ifc_class="IfcSurfaceStyleWithTextures", attributes={"Textures": textures}
)
logger = logging.getLogger("ImportIFC")
ifc_import_settings = bonsai.bim.import_ifc.IfcImportSettings.factory(bpy.context, None, logger)
ifc_importer = bonsai.bim.import_ifc.IfcImporter(ifc_import_settings)
ifc_importer.file = tool.Ifc.get()
ifc_importer.create_style(style)
bonsai.core.geometry.switch_representation(tool.Ifc, tool.Geometry, obj=obj, representation=representation)
class ConvertSVGToDXF(bpy.types.Operator):
+2 -8
View File
@@ -18,14 +18,11 @@
import enum
import json
import os
from collections.abc import Callable
from pathlib import Path
from typing import TYPE_CHECKING, Any, Literal, Union, get_args
from typing import TYPE_CHECKING, Any, Literal, Union
import bpy
import ifcopenshell
import ifcopenshell.api
import ifcopenshell.api.pset
import ifcopenshell.util.element
from bpy.props import (
@@ -34,7 +31,6 @@ from bpy.props import (
CollectionProperty,
EnumProperty,
FloatProperty,
FloatVectorProperty,
IntProperty,
PointerProperty,
StringProperty,
@@ -42,19 +38,17 @@ from bpy.props import (
from bpy.types import PropertyGroup
from mathutils import Matrix
import bonsai.bim.module.drawing.annotation as annotation
import bonsai.bim.module.drawing.decoration as decoration
import bonsai.core.drawing as core
import bonsai.tool as tool
from bonsai.bim.module.drawing.data import (
AnnotationData,
DecoratorData,
DrawingsData,
ElementValuesData,
SheetsData,
)
from bonsai.bim.module.drawing.data import refresh as refresh_drawing_data
from bonsai.bim.prop import Attribute, BIMFilterGroup, StrProperty
from bonsai.bim.prop import Attribute, BIMFilterGroup
diagram_scales_enum = []
@@ -22,7 +22,6 @@ import string
from pathlib import Path
from textwrap import wrap
import bpy
import openpyxl
import openpyxl.cell # Unnecessary, bug in typeshed.
import openpyxl.utils # Unnecessary, bug in typeshed.
@@ -33,7 +32,6 @@ from odf.table import Table, TableCell, TableColumn, TableRow
from odf.text import P
import bonsai.tool as tool
from bonsai.bim.ifc import IfcStore
from bonsai.bim.module.drawing.svgwriter import SvgWriter
DEBUG = False
@@ -335,12 +335,9 @@ class BaseLinesShader(BaseShader):
TYPE = "LINES"
DEF_GLSL = (
BaseShader.DEF_GLSL
+ """
DEF_GLSL = BaseShader.DEF_GLSL + """
#define GAP_SIZE {gap_size}
"""
)
GEOM_GLSL = """
layout(lines) in;
@@ -401,13 +398,10 @@ class DotsGizmoShader(GizmoShader):
TYPE = "POINTS"
DEF_GLSL = (
BaseShader.DEF_GLSL
+ """
DEF_GLSL = BaseShader.DEF_GLSL + """
#define CIRCLE_SEGMENTS 12
#define CIRCLE_RADIUS 8
"""
)
GEOM_GLSL = """
layout(points) in;
@@ -26,7 +26,6 @@ import xml.etree.ElementTree as ET
from pathlib import Path
from xml.dom import minidom
import bpy
import ifcopenshell.util.geolocation
import pystache
from mathutils import Vector
@@ -18,7 +18,6 @@
import math
import os
import re
import shutil
import xml.etree.ElementTree as ET
from collections.abc import Callable, Sequence
@@ -30,10 +29,8 @@ import bmesh
import bpy
import ifcopenshell
import ifcopenshell.util.element
import ifcopenshell.util.representation
import ifcopenshell.util.selector
import ifcopenshell.util.unit
import mathutils
import svgwrite
import svgwrite.container
import svgwrite.text
@@ -1026,7 +1023,8 @@ class SvgWriter:
for text_literal in text_literals:
text = tool.Drawing.replace_text_literal_variables(text_literal.Literal, product or element)
if newline_at:
text = helper.add_newline_between_words(text, newline_at)
text_segments = parse_markdown_it(text)
if len(text_segments) == 1 and text_segments[0]["url"] is None and not text_segments[0].get("break", False):
+1 -2
View File
@@ -30,7 +30,6 @@ from bonsai.bim.module.drawing.data import (
DocumentsData,
DrawingsData,
ElementFiltersData,
ElementValuesData,
ProductAssignmentsData,
SheetsData,
)
@@ -89,7 +88,7 @@ class BIM_PT_camera(Panel):
for link in links:
row = panel.row(align=True)
split = row.split(factor=0.9)
split.label(text=link.name, icon="FILE")
split.label(text=link.filepath, icon="FILE")
split.prop(link, "include_in_drawings", text="")
else:
panel.label(text="No IFC projects linked and loaded.")
-2
View File
@@ -16,8 +16,6 @@
# You should have received a copy of the GNU General Public License
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
import importlib
import os
import ifcfm
@@ -16,10 +16,7 @@
# You should have received a copy of the GNU General Public License
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
import json
import logging
import os
import tempfile
import bpy
import ifcfm
-4
View File
@@ -23,11 +23,7 @@ from bpy.props import (
BoolProperty,
CollectionProperty,
EnumProperty,
FloatProperty,
FloatVectorProperty,
IntProperty,
PointerProperty,
StringProperty,
)
from bpy.types import PropertyGroup
@@ -16,8 +16,6 @@
# You should have received a copy of the GNU General Public License
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
import math
import bpy
import ifcopenshell.util.element
from bpy.app.handlers import persistent
@@ -19,7 +19,6 @@
from collections.abc import Sequence
import blf
import bmesh
import bpy
import gpu
import ifcopenshell
@@ -16,22 +16,17 @@
# You should have received a copy of the GNU General Public License
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
from math import pi, pow
from math import pi
from typing import Any, Optional, TypeVar, Union
import bmesh
import bpy
import ifcopenshell
import ifcopenshell.util.shape
import ifcopenshell.util.unit
import mathutils
import numpy as np
import shapely
from ifcopenshell.util.shape_builder import ShapeBuilder
from mathutils import Matrix, Vector, geometry
import bonsai.tool as tool
T = TypeVar("T")
@@ -16,7 +16,6 @@
# You should have received a copy of the GNU General Public License
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
import re
from collections.abc import Sequence
from time import time
from typing import (
@@ -32,11 +31,9 @@ from typing import (
import bmesh
import bpy
import ifcopenshell
import ifcopenshell.api
import ifcopenshell.api.boundary
import ifcopenshell.api.drawing
import ifcopenshell.api.geometry
import ifcopenshell.api.grid
import ifcopenshell.api.group
import ifcopenshell.api.layer
import ifcopenshell.api.material
@@ -61,10 +58,8 @@ import bonsai.core.geometry as core
import bonsai.core.nest
import bonsai.core.root
import bonsai.core.spatial
import bonsai.core.style
import bonsai.tool as tool
from bonsai.bim.ifc import IfcStore
from bonsai.bim.module.model.data import AuthoringData
from bonsai.bim.module.model.decorator import ProfileDecorator
if TYPE_CHECKING:
@@ -902,6 +897,7 @@ class OverrideDelete(bpy.types.Operator):
if not is_valid_data_block:
continue
element = tool.Ifc.get_entity(obj)
if element:
if tool.Geometry.is_locked(element):
@@ -912,6 +908,9 @@ class OverrideDelete(bpy.types.Operator):
if ifcopenshell.util.element.get_pset(element, "BBIM_Array"):
self.report({"INFO"}, "Elements that are part of an array cannot be deleted.")
continue
if element.is_a("IfcDocumentReference"):
self.report({"INFO"}, "Linked models cannot be deleted.")
continue
if element.is_a("IfcGridAxis"):
# Deleting the last W axis is OK
if ((grid := element.PartOfU) and len(grid[0].UAxes) == 1) or (
@@ -1208,6 +1207,11 @@ class OverrideDuplicateMove(bpy.types.Operator):
operator.report({"ERROR"}, f"Drawing '{obj.name}' not duplicated.")
continue
if element.is_a("IfcDocumentReference"):
objects_to_remove.add(obj)
operator.report({"ERROR"}, f"Linked model '{obj.name}' not duplicated.")
continue
if tool.Geometry.is_locked(element):
objects_to_remove.add(obj)
operator.report({"ERROR"}, lock_error_message(obj.name))
@@ -24,8 +24,6 @@ from bpy.props import (
BoolProperty,
CollectionProperty,
EnumProperty,
FloatProperty,
FloatVectorProperty,
IntProperty,
PointerProperty,
StringProperty,
@@ -34,7 +32,6 @@ from bpy.types import PropertyGroup
import bonsai.tool as tool
from bonsai.bim.module.geometry.data import RepresentationsData, ViewportData
from bonsai.bim.prop import Attribute, ObjProperty, StrProperty
def get_contexts(self: "BIMObjectGeometryProperties", context: bpy.types.Context) -> list[tuple[str, str, str]]:

Some files were not shown because too many files have changed in this diff Show More