Compare commits

...

1194 Commits

Author SHA1 Message Date
Andrej730 e9d003c22f clear cgal cache 2025-10-30 19:20:37 +05:00
Andrej730 2e71e002fc try out just intel 2025-10-30 18:54:31 +05:00
Andrej730 40ed2fe3ab build-all.py - remove unused wasm flags
`-Wl,-undefined,suppress` have no meaning in emscripten and they are just ignored. And emscripten is ignoring undefined symbols by default without any flags.
2025-10-30 18:53:56 +05:00
Andrej730 379fe632a3 build-all.py - switch to dynamic_lookup
1) `-undefined,suppress` is deprecated and linking is sending warnings about it and it seems to be superseded by `dynamic_lookup`
2) `-flat_namespace` is not compatible with GMP when building for intel, for some reason and results in horrible errors during linking:

Example error:
```
ld: branch8 out of range 366651 in ___gmpn_add_nc
final section layout:
    __TEXT               addr=0x00000000, size=0x02d09000, fileOffset=0x00000000
        __text           addr=0x00001400, size=0x0264a5e4, fileOffset=0x00001400
        __stubs          addr=0x0264b9e4, size=0x0000423c, fileOffset=0x0264b9e4
        __stub_helper    addr=0x0264fc20, size=0x00006c58, fileOffset=0x0264fc20
        __gcc_except_tab addr=0x02656878, size=0x002efc04, fileOffset=0x02656878
        __const          addr=0x02946480, size=0x001cdc18, fileOffset=0x02946480
        __cstring        addr=0x02b140a0, size=0x0014324b, fileOffset=0x02b140a0
        __unwind_info    addr=0x02c572ec, size=0x0008d2d0, fileOffset=0x02c572ec
        __eh_frame       addr=0x02ce45c0, size=0x00024a30, fileOffset=0x02ce45c0
    __DATA_CONST         addr=0x02d09000, size=0x0022b000, fileOffset=0x02d09000
        __got            addr=0x02d09000, size=0x00001dc8, fileOffset=0x02d09000
        __mod_init_func  addr=0x02d0adc8, size=0x00000690, fileOffset=0x02d0adc8
        __const          addr=0x02d0b460, size=0x00227fd0, fileOffset=0x02d0b460
    __DATA               addr=0x02f34000, size=0x000c3000, fileOffset=0x02f34000
        __la_symbol_ptr  addr=0x02f34000, size=0x000056a0, fileOffset=0x02f34000
        __data           addr=0x02f396a0, size=0x0005f7b8, fileOffset=0x02f396a0
        __thread_vars    addr=0x02f98e58, size=0x000006d8, fileOffset=0x02f98e58
        __thread_ptrs    addr=0x02f99530, size=0x00000178, fileOffset=0x02f99530
        __thread_data    addr=0x02f996b0, size=0x000000d8, fileOffset=0x02f996b0
        __thread_bss     addr=0x02f99790, size=0x00018850, fileOffset=0x02f99790
        __bss            addr=0x02fb1fe0, size=0x0003b0c0, fileOffset=0x00000000
        __common         addr=0x02fed0a0, size=0x00009098, fileOffset=0x00000000
    __LINKEDIT           addr=0x02ff7000, size=0x0148e000, fileOffset=0x02fb2000
clang: error: linker command failed with exit code 1 (use -v to see invocation)
```
2025-10-30 18:53:55 +05:00
Andrej730 2ecaee9024 build-all.py - add VERBOSE=1 to the wrapper make command 2025-10-30 18:53:55 +05:00
Andrej730 f9a3c9a994 build-all.py - fix missing mac cross compilation host args in gmp
I guess something has changed in gmp 6.3.0 and this issue become more apparent.

Example error:
```
tmp-cnd_sub_n.s:133:14: error: tmp-cnd_add_n.sbrackets expression not supported on this target:
130 stp x8, x9, [x1,#16]
             ^
:2tmp-cnd_sub_n.s: :error: 134invalid instruction mnemonic 'bic':
6 bic x7, x13, x0:
error:  invalid instruction mnemonic 'cset'^
~Lrt: cset x0, cc~

     ^~~tmp-cnd_add_n.s~:
131:2: error: invalid instruction mnemonic 'adcs'
 adcs x8, x10, x6
 ^~~~
tmp-cnd_add_n.s:132:2: error: invalid instruction mnemonic 'adcs'
 adcs x9, x11, x7
 ^~~~
tmp-cnd_add_n.s:133:14: error: brackets expression not supported on this target
 stp x8, x9, [x1,#16]
             ^
tmp-cnd_add_n.s:134:6: error: invalid instruction mnemonic 'cset'
Lrt: cset x0, cs
     ^~~~
```
2025-10-29 14:38:24 +05:00
Andrej730 77acbff50b black . 2025-10-29 13:25:26 +05:00
Ryan Schultz 3f2cad0490 Add suppress_zero_inches parameter to imperial_length formatting function 2025-10-28 22:24:40 -05:00
Andrej730 5ec974ff94 Exclude build-all.py from main ruff check 2025-10-28 18:20:43 +05:00
Andrej730 2c585b649a Fix RUFF037 (redundant quotes) 2025-10-28 18:20:14 +05:00
Andrej730 36c28f3953 Mention in docs wasm-wheels as the main wheels source for pyodide builds 2025-10-28 18:20:13 +05:00
Andrej730 d1763237d2 ifcopenshell docs make - add server target 2025-10-28 18:20:13 +05:00
Andrej730 e8544d78ee ci.yml - note on rtti in rocksdb 2025-10-28 17:17:20 +05:00
Andrej730 e715a9467d ci.yml - exclude PYTHON_LIBRARY as redundant 2025-10-28 17:17:20 +05:00
Andrej730 1f8c12a4c8 build_pyodide - test wasm wheel working 2025-10-28 17:17:20 +05:00
Andrej730 89a6eac535 build-all.py - access pyodide for necessary variables, simplify debug build env 2025-10-28 17:17:20 +05:00
Andrej730 d1ffb329c8 pyodide/setup.py - fix missing ifcopenshell subpackages 2025-10-28 17:17:20 +05:00
Andrej730 4396126a43 build-all.py - fix for upcoming pyodide changes (cmake INIT flags) 2025-10-28 17:17:20 +05:00
Andrej730 7448feed44 build-all.py - reinitialize wasm cxx flags from cflags to accomodate issue upstream 2025-10-28 17:17:19 +05:00
Andrej730 6bc4046b17 ifcwrap cmake - fix issue with debug build after migration to FindPython
In FindPython variable was renamed to Python_LIBRARY_DEBUG
2025-10-28 17:17:19 +05:00
Andrej730 1a83e52935 ifcwrap cmake - avoid using deprecated swig_link_libraries 2025-10-28 17:17:19 +05:00
Andrej730 f16d42ba14 ifcwrap cmake - use usual name for wrapper target 2025-10-28 17:17:19 +05:00
Andrej730 75135fe45d cache_dependencies.py - fix tarfile deprecation warnings in 3.12-3.13 2025-10-28 17:17:19 +05:00
Andrej730 de89ab31cf ifcwrap cmake - move DEBUG_POSTFIX logic to one place 2025-10-28 17:17:19 +05:00
Andrej730 c8a4f1bbd2 cmake - build without Python libraries on Unix 2025-10-28 17:17:19 +05:00
Andrej730 5be1858767 ifcwrap cmake - accomodate bug in cmake makefiles generator 2025-10-28 17:17:19 +05:00
Andrej730 ace1db739f build-all - use shutil.which instead of custom function
To make it more idiomatic and custom function also was misinterpreting folders with the same name as existing executables.
2025-10-28 17:17:19 +05:00
Andrej730 80504310b6 build_pyodide - use ccache 2025-10-28 17:17:19 +05:00
Andrej730 a4dae9650f build_rocky - switch to main branch ccache 2025-10-28 17:17:18 +05:00
Andrej730 c27a995480 build_pyodide - use prebuilt pyodide build env 2025-10-28 17:17:18 +05:00
Andrej730 5b4c54abd2 build-all.py - switch to gmp ftpmirror
previous url is inaccessible
2025-10-28 17:17:18 +05:00
Andrej730 57d0beedee build_pyodide - display logs in github action output 2025-10-28 17:17:18 +05:00
Andrej730 d0ba675b1b build_pyodide - upload build logs for debugging 2025-10-28 17:17:18 +05:00
Andrej730 f4f2fa9535 build_pyodide - pack cached dependencies 2025-10-28 17:17:18 +05:00
Andrej730 67707914b9 build_osx - remove setup-python
as it's already preinstalled on the image
2025-10-28 17:17:18 +05:00
Andrej730 12766d61d4 build-all.py - print BUILD_DIR 2025-10-28 17:17:18 +05:00
Andrej730 34374cba41 build_pyodide - no need to adjust version
since it's now inferred automatically
2025-10-28 17:17:18 +05:00
Andrej730 f8bb04eae3 build-all.py - accomodate pyodide build system automatically
as it's the main way to build the wasm package
2025-10-28 17:17:18 +05:00
Andrej730 aee8cbe479 build_pyodide.yaml - move build_pyodide to a separate script 2025-10-28 17:17:18 +05:00
Andrej730 cb36e10279 Add notes for pyodide building process 2025-10-28 17:17:18 +05:00
Andrej730 7ca44b5677 build-all.py wasm - move SIDE_MODULE=2 to cmake
Next to `EXPORTED_FUNCTIONS` and avoid possible issues with pyodide in the future (pyodide is using `SIDE_MODULE=1`, but currently not providing it libraries of type `MODULE`, only for shared ones).
2025-10-28 17:17:17 +05:00
Andrej730 a6921b83a1 ifcwrap cmake - provide correct suffix for wasm python extension 2025-10-28 17:17:17 +05:00
Andrej730 c3c94b9c59 pyodide setup.py - add dependencies
so micropip would be able to gather them automatically
2025-10-28 17:17:17 +05:00
Andrej730 576ef336fc pyodide setup.py - add a note on not switching to pyproject.toml 2025-10-28 17:17:17 +05:00
Andrej730 b1fb541912 pyodide setup.py - ensure we have correct pyodide_2025_0_wasm32 suffix
Adding extension, but avoiding adding sources as we're not actually building.
As a result build will have a correct suffix `pyodide_2025_0_wasm32.whl` that's pyodide is currently using and this is pyodide is plan to use when it's going to release to PyPI, see https://peps.python.org/pep-0783/
2025-10-28 17:17:17 +05:00
Andrej730 6345b052da build-all.py - add a note about alternative gmp mirror 2025-10-28 17:17:17 +05:00
Andrej730 061554d921 cmake - deduplicate ccache set_property code 2025-10-28 17:17:17 +05:00
Andrej730 bcaa412f4b build-all.py - don't pass side module flags as usual flags
As they're parsed by emcmake automatically https://github.com/pyodide/pyodide-build/blob/bdd0b1422064de6d92264a08c599e85001a28567/pyodide_build/tools/cmake/Modules/Platform/Emscripten.cmake#L105-L107
2025-10-28 17:17:17 +05:00
Andrej730 9f6536b263 build-all.py - option to build wasm outside pyodide for debugging 2025-10-28 17:17:17 +05:00
Andrej730 226581f76e build-all.py - provide exported functions to target explicitly
Otherwise it broke compilation in some cases when cmake would try to test that linker is working.
2025-10-28 17:17:17 +05:00
Andrej730 e833d0cd13 build-all - wasm to use packages instead of providing includes/libs paths explicitly
More complicated than I anticipated😅

Details
https://discourse.cmake.org/t/provide-absolute-paths-to-dependencies-with-cmake-find-root-path-search-during-cross-compilation-wasm/15241
2025-10-28 17:17:16 +05:00
Andrej730 ed3c95d9d7 build-all.py - move unsupported dependencies to script 2025-10-28 17:17:16 +05:00
Andrej730 7a4823a1bc build-deps - use nuget to download ccache 2025-10-28 17:17:16 +05:00
Andrej730 80c0932174 build-all.py - print IFCOS_SCHEMAS 2025-10-28 17:17:16 +05:00
Andrej730 73a238e7b0 build-all.py - document required wasm variables 2025-10-28 17:17:16 +05:00
Andrej730 b95900f154 build-all.py - fix issue building wasm on apple device 2025-10-28 17:17:16 +05:00
Andrej730 da66e3c908 build-all.py - remove --host none from wasm args
As it's now obsolete and producing warnings `configure: WARNING: the "none" host is obsolete, use --disable-assembly`.
2025-10-28 17:17:16 +05:00
Andrej730 e04cc47022 build-all.py - bump freetype to avoid issues on cmake 4+ 2025-10-28 17:17:16 +05:00
Andrej730 ce427698d9 build-all.py - add note on --without-xxx option 2025-10-28 17:17:16 +05:00
Andrej730 d3beae1374 Add Python 3.14 builds 2025-10-28 17:17:16 +05:00
Andrej730 389d481364 build-deps - set NUGET_EXE from PATH if it's available 2025-10-28 17:17:15 +05:00
Andrej730 3efd88b0d6 build-all - deduce python components from python path 2025-10-28 17:17:15 +05:00
Andrej730 0a5388f386 ifcwrap cmake - migrate to FindPython
Also simplify run-cmake to just prefix the path, instead of providing 3 paths explicitly.
2025-10-28 17:17:15 +05:00
Andrej730 71fa002707 build-deps - support overriding PYTHON_VERSION 2025-10-28 17:17:15 +05:00
Andrej730 dd80115aa2 build-deps - download Python using nuget 2025-10-28 17:17:15 +05:00
Andrej730 bc66710fec build-deps - download nuget
to later download python using it
2025-10-28 17:17:15 +05:00
Andrej730 921241fbdd build-deps - include ccache for convenience 2025-10-28 17:17:15 +05:00
Andrej730 44b9dd64f6 build_win - extend cache size 2025-10-28 17:17:15 +05:00
Andrej730 bfa77255a5 build_win - use fork to resolve cache misses and duplicated cache 2025-10-28 17:17:14 +05:00
Andrej730 b125c651a8 build_win - test ccache 2025-10-28 17:17:14 +05:00
Thomas Krijnen eb1c81514b Check for attribute nil #7276 #7291 2025-10-28 10:51:31 +01:00
Thomas Krijnen 6df5632f91 black 2025-10-26 13:33:10 +01:00
Thomas Krijnen 391a412e65 test cases #7291 2025-10-26 13:31:31 +01:00
Thomas Krijnen b10415b1b3 Rework iterator constructor #7291 2025-10-26 13:31:31 +01:00
Thomas Krijnen b1c44d42e3 Reset logger product to none 2025-10-26 13:31:31 +01:00
Dion Moult 5f65e21878 Fix bug where you couldn't get elements using a predefined property set. 2025-10-26 23:05:05 +11:00
Dion Moult 0d3be9d101 Fix #5108. Selector now supports both GlobalId and Name as filter values. 2025-10-26 22:52:31 +11:00
Dion Moult eea585a3cd Fix #6258. Fix #5727 properly. Only assume layerset axis on "standard case" elements, nothing else. 2025-10-26 22:33:39 +11:00
Thomas Krijnen 1789406299 Ruff 2025-10-26 12:04:22 +01:00
Dion Moult b503061dc0 Fix #3868. Automatic annotation references are now auto deleted if their reference is also gone. 2025-10-26 20:58:15 +11:00
Dion Moult 90ccaf4aab Let users manually create automatic references too. 2025-10-26 20:46:32 +11:00
Dion Moult 05ff47fcff Remap deprecated entities in Brick 1.4 to new RealEstateCore URIs. 2025-10-26 20:38:58 +11:00
Louis Casteleyn c40ecdd550 deleted deprecated entities for v1.4 (#6511) 2025-10-26 20:32:28 +11:00
daniel-augusto 3a0622e9df Update introduction with hyperlinks for tools (#7290) 2025-10-26 20:29:30 +11:00
Dion Moult 0bb03750dc Fix #4914. Write docs for syntax and schema validation and schema querying 2025-10-26 20:27:07 +11:00
Thomas Krijnen 89defa9b6b build-all.py ruff: noqa: UP035 2025-10-26 10:20:13 +01:00
Thomas Krijnen 459aad54aa Black 2025-10-26 10:17:49 +01:00
Thomas Krijnen 6f3065f6ce ci.yml USE_MMAP=On 2025-10-26 10:15:52 +01:00
Thomas Krijnen 69863ce4a9 Try and fix stub test 2025-10-26 10:03:43 +01:00
Dion Moult e5ae19fd34 See #7291. Temporary workaround whilst segfaults are sorted. 2025-10-26 19:36:41 +11:00
Dion Moult afe617fb93 Revert "Bump IOS - necessary as last bunch of commits are incompatible with previous binaries"
This reverts commit d922f0b9ad.
2025-10-26 19:32:35 +11:00
Dion Moult d922f0b9ad Bump IOS - necessary as last bunch of commits are incompatible with previous binaries 2025-10-26 19:12:22 +11:00
Dion Moult f9d2d494b1 Fix #4275. Using psets_only kwarg in get_pset utility now includes predefined psets. 2025-10-26 18:21:06 +11:00
Thomas Krijnen 806aa14bd0 Compatibility for older builds 2025-10-25 21:55:06 +02:00
Thomas Krijnen 80066ba9e7 Different hack for allowing f.header.file_description.file.header.file_description.file 2025-10-25 21:54:42 +02:00
Thomas Krijnen 7cb1f07a0b hacky way to retain attribute too many messages on header entities in validate.py 2025-10-25 21:12:12 +02:00
Thomas Krijnen bdb52dcffd Pass header entity types during pass to resolve empty list type 2025-10-25 20:29:41 +02:00
Thomas Krijnen 933ad6c801 Fix header and schema validation errors in pass-rigid-op-IfcPlaneAngleMeasure-IfcPlaneAngleMeasure-ifc4x3_add2.ifc 2025-10-25 20:29:19 +02:00
Thomas Krijnen 1594b9505c Don't emit Parsing terminated on benign files by not reading past stream in skipComment() 2025-10-25 20:14:02 +02:00
Thomas Krijnen 325745a822 Test IfcConvert only on single file 2025-10-25 15:54:15 +02:00
Thomas Krijnen 74f8b047fb osx compat 2025-10-25 15:40:08 +02:00
Thomas Krijnen 0f8c6ffe9e Run the bulk of pytest in parallel 2025-10-25 15:38:25 +02:00
Thomas Krijnen fa46fe0cf0 Typos 2025-10-25 15:30:36 +02:00
Thomas Krijnen f0a1efa1f2 ruff --fix 2025-10-25 15:27:46 +02:00
Thomas Krijnen 71c1058e9e .gitignore for .exp files 2025-10-25 15:27:38 +02:00
Thomas Krijnen 7575bd4dfb Commit some files because I do not want them cleaned 2025-10-25 15:25:56 +02:00
Thomas Krijnen d697ed3384 Commit some files because I do not want them cleaned 2025-10-25 15:25:10 +02:00
Thomas Krijnen aed70c8a02 Run black 2025-10-25 15:20:36 +02:00
Thomas Krijnen e82ca0e932 Less back and forths by returning semi count in page 2025-10-25 15:08:21 +02:00
Thomas Krijnen 5910b39766 geom.stats module for preemptive scanning through file 2025-10-25 13:58:32 +02:00
Thomas Krijnen ea9e0c9ab4 readInstancePy() option to obtain type decls instead of strings 2025-10-25 13:55:55 +02:00
Thomas Krijnen 2e951eb952 Whitespace handling now that token strings are built on the fly 2025-10-25 13:55:15 +02:00
Thomas Krijnen 2497611abd Merge branch 'v0.8.0' of https://github.com/IfcOpenShell/IfcOpenShell into v0.8.0 2025-10-25 13:54:52 +02:00
Bruno Postle 90bf56d9ba Fix ifc5d documentation
Documentation claimed that ODS/XLSX output was to a given filename, but
the code actually writes files with generated names in a folder.

(also create the folder if necessary for convenience)
2025-10-24 22:19:01 +01:00
Bruno Postle e1b73ef0ef Fix build broken by a6d20c0 - link iostreams
FileReader.cpp now uses boost::iostreams::mapped_file regardless of
USE_MMAP setting
2025-10-24 15:35:19 +01:00
Thomas Krijnen bcb5fd7810 Missing return type 2025-10-24 13:32:18 +02:00
Thomas Krijnen 40c5145a13 Address some omissions in the FileReader rewrite regarding unicode paths on windows 2025-10-24 13:26:27 +02:00
Thomas Krijnen e304c3ad31 Merge branch 'v0.8.0' of https://github.com/IfcOpenShell/IfcOpenShell into v0.8.0 2025-10-24 13:25:05 +02:00
Thomas Krijnen 0494bd9677 Option to bypass storing types when opening model 2025-10-24 12:06:59 +02:00
Dion Moult fc0cdfabb9 Fix #7255. Bug where you couldn't edit header data. 2025-10-24 19:11:29 +11:00
nameloCmaS 2dac137801 Limit clipping plane euler rotation angles to <= 360 degrees (#6877)
The "Flip Clipping Plane" operator adds 180 degrees to the angle's value, meaning the angle will keep increasing with each press.
2025-10-24 14:10:38 +11:00
Dion Moult 8ffa6fcf47 Fix #7267. Bug where duplicating a drawing would cause annotation references to be associated with both the original and duplicate. 2025-10-24 14:09:00 +11:00
Dion Moult 8824e6e2c2 Fix #7268. Automatic annotation references (sections, elevations, etc) are now intelligently regenerated 2025-10-24 12:47:58 +11:00
Ryan Schultz 5dbfe539ac Need a little more freedom to rotate a RCP 2025-10-23 08:31:31 -05:00
Dion Moult d1453e1139 Fix bug where panels for psets/qtos/classifications/types were showing up on irrelevant objects (e.g. grid axes) 2025-10-23 08:59:15 +11:00
Dion Moult 5b5dcb3c6d Fix #7257. Always quote psets and props in our colour by property dropdown to account for spaces and characters. 2025-10-23 08:58:23 +11:00
Dion Moult 4f467d199e See #7253. See #7268. Rewrite grid generation to use IFC data, not rely on Blender object.
This also deprecates one more instance of the add_representation API
call. As this is slowly cleaned up we can move towards "regenerating"
annotations, not just generating from scratch.
2025-10-23 08:39:25 +11:00
Thomas Krijnen a6d20c0cc4 Follow up after 4d688170e0 2025-10-22 21:42:37 +02:00
Ryan Schultz d5d942bb2e Adds a TargetView CSS class to the drawings. 2025-10-22 10:06:43 -05:00
Thomas Krijnen 9e2c7e653f Commit suggestion in #7276 2025-10-22 14:37:10 +02:00
Thomas Krijnen 200c0bf773 Commit suggestion in #7276 2025-10-22 13:23:34 +02:00
Dion Moult 381b0d379a Optimise operators when a drawing is active by not needlessly regenerating the cut after each operation. 2025-10-22 18:03:40 +11:00
Dion Moult f48b5b9d92 Fix #7273. See #7253. Auto annotation references now cannot be deleted, but can be excluded. 2025-10-22 18:03:40 +11:00
Massimo Fabbro 1f47aadc94 Fix #7227. Sync cost item assigned resources also for SOR 2025-10-22 07:14:01 +02:00
falken10vdl bb3cd7e49c Annotation rotation when doing bulk tags (#7049)
* first attempt to do annotation rotation when dong bulk tags

* Enhance annotation rotation handling based on camera orientation

* handle properly S_G

* black .

* reorder property in UI

* cleanup imports
2025-10-22 15:07:52 +11:00
daniel-augusto edd01d44de Include direct links to tools (#7128) 2025-10-22 15:06:56 +11:00
Michael Godsven 52b899d070 Add icons (#7256) 2025-10-22 11:30:54 +11:00
Dion Moult 008292df0f Revert "Always show edit UI even if you don't have a BIM Tool activated."
This reverts commit 87bfd182d7.
2025-10-22 11:08:55 +11:00
Dion Moult 87bfd182d7 Always show edit UI even if you don't have a BIM Tool activated. 2025-10-22 11:07:18 +11:00
Dion Moult 8fcc622b8a Optimisation to only recalculate all drawing cuts if the camera is moved, not just selected. 2025-10-22 10:12:24 +11:00
Thomas Krijnen 9415878f57 Remove warning about combination of RefDirection as Axis #7251 2025-10-21 13:33:32 +02:00
Thomas Krijnen 919ac41a74 Consider case of only RefDirection in sectioned shapes #7251 2025-10-21 13:32:51 +02:00
Thomas Krijnen 80093f3777 Loft all wires not only the outer one #7251 2025-10-21 13:09:10 +02:00
Thomas Krijnen 28f5d6e91c Copy internal status on interpolated loops #7251 2025-10-21 13:08:29 +02:00
Thomas Krijnen 550779deee Merge branch 'v0.8.0' of https://github.com/IfcOpenShell/IfcOpenShell into v0.8.0 2025-10-21 13:06:05 +02:00
Thomas Krijnen e2cf60f0c1 Update to gmp 6.3.0 #7200 2025-10-21 12:18:48 +02:00
Dion Moult 546a042d40 Explicitly disable any voids, openings, and booleans in IFC4 Reference View MVD
It turns out vendors are still exporting them and creating a mess.
2025-10-21 10:49:17 +11:00
Thomas Krijnen 86b89f2153 Comment behaviour #7264 2025-10-20 10:37:35 +02:00
Thomas Krijnen 34f4aa430a Keep file_ as nullptr to not bypass addEntity() #7264 2025-10-20 10:33:09 +02:00
Thomas Krijnen 67678cb7f1 Merge branch 'v0.8.0' of https://github.com/IfcOpenShell/IfcOpenShell into v0.8.0 2025-10-20 10:27:50 +02:00
Thomas Krijnen f05b0d946d if -> ifdef #7174 2025-10-19 13:20:58 +02:00
Ryan Schultz 486651e0b7 additional tweak to the preceding commit. 2025-10-18 13:43:34 -05:00
Ryan Schultz 5885924bb7 Fix #5709: The RCP will not be denied! :) 2025-10-18 12:47:35 -05:00
Ryan Schultz ead849625d Automatically select annotations after creation to make it easier to move them in bulk. 2025-10-16 21:10:43 -05:00
Ryan Schultz f52aafdd6a closes #7249: for stairs, change the first/last tread lengths to less than the typical tread run. And even go to zero, whereby removing the tread altogether. 2025-10-14 21:53:22 -05:00
Ryan Schultz b0ae0a2c82 extend https://github.com/IfcOpenShell/IfcOpenShell/commit/322a2179e51a9ec4802fe9e35039c7e3e29f9678: Merges names with number suffix, as well (ex: foo, foo.001, foo.002) 2025-10-14 11:29:44 -05:00
Thomas Krijnen 4d688170e0 Storage rework WIP 2025-10-13 20:47:43 +02:00
Ryan Schultz 322a2179e5 Merge entities, if match on name or identification attribute only. 2025-10-13 11:25:36 -05:00
Dion Moult 8014980b88 Fix #7076. Lock representation items scale to prevent user confusion. 2025-10-13 08:52:59 +11:00
Dion Moult 65237cab65 Fix #7080. Potential bug with merging styles that didn't replace elements of the same class. 2025-10-13 08:44:47 +11:00
Dion Moult 155827528a Visibility during collector assignment now depends on the visibility mode set in the UI. 2025-10-13 08:08:35 +11:00
Dion Moult fb15435296 See #7229. Simpler solution to ensure representation isn't affected by visibility until assign class can be cleaned up more. 2025-10-13 08:08:10 +11:00
Dion Moult 6bba3ebeeb See #7159. Make polls consistent in add foo to sheet operators. 2025-10-13 08:02:06 +11:00
Dion Moult 3343f3fb35 Revert "Closes #7229: Unhide object before mesh tessellation export to prevent "Cannot edit hidden object" error when collector.assign() hides the object."
This reverts commit 96d05300bb.
2025-10-13 07:49:07 +11:00
Ryan Schultz 1b451d45cf Closes #7159: Fix AddReferenceToSheet operator poll checking wrong data_dir property (bim_props instead of prefs) 2025-10-12 13:51:14 -05:00
Ryan Schultz f5f676cf51 black . 2025-10-12 12:46:49 -05:00
Ryan Schultz 1dd477d382 Delete aggregate if all its parts are deleted. Prevents having orphaned aggregates, if you do a bulk delete with empties turned off. 2025-10-12 12:17:57 -05:00
Ryan Schultz 96d05300bb Closes #7229: Unhide object before mesh tessellation export to prevent "Cannot edit hidden object" error when collector.assign() hides the object. 2025-10-12 09:57:27 -05:00
Dion Moult 0073a4c0a2 Fix #7205. Regression when switching from drawing mode to model mode didn't hide drawings. 2025-10-12 21:21:27 +11:00
Dion Moult d3a5071d9d Fix #7211. Explain to user why they can't remove the last grid axis. 2025-10-12 21:07:13 +11:00
Dion Moult 471bd34fc6 Fix #7206. For convenience, deleted annotation references are marked as excluded and not regenerated. 2025-10-12 21:00:55 +11:00
Ryan Schultz 44cc12763b Allows the ability to activate an attached drawing_style regardless of whether a drawing has a underlay, or not. 2025-10-11 17:47:37 -05:00
Ryan Schultz b68aca04ae added EPset_Status.UserDefinedStatus to default join_criteria 2025-10-11 17:41:41 -05:00
Bruno Postle dd22264877 Fix sheet regeneration regression from d4f3280
Remove validate_sheet_files() check in regenerate_sheet() that prevented
regenerating missing LAYOUT files. The validation was blocking the
exact scenario that regeneration was designed to handle.

This allows users to open a bare IFC file with configured drawings and
sheets and have the SVG layouts automatically recreated with drawings
placed at default positions.
2025-10-11 20:25:13 +01:00
Ryan Schultz cc6ef0268f Introduces a toggle to turn on/off material layers in printed svg. 2025-10-11 09:52:55 -05:00
Dion Moult feecb89c8e Fix #7212. IfcTester now supports IFC2X3 type element mapping. 2025-10-11 21:30:49 +11:00
Dion Moult cb5c488cfd Fix #7213. IfcTester now supports checking for USERDEFINED predefined types
Can I just take this moment to complain about the overengineered
complexity of how predefined types work in IFC.
2025-10-11 21:09:41 +11:00
Dion Moult b68e8dedd2 Fix #5675. Bug where separate islands of polygons still merged CSS classes incorrectly. 2025-10-11 20:39:48 +11:00
Dion Moult 0975eb455e All default drawing patterns now have a white background, not transparent. 2025-10-11 20:37:28 +11:00
Dion Moult df0e8bba8c Fix #7225. Handle freestyle linework regardless of generated SVG filename. 2025-10-11 19:15:50 +11:00
Dion Moult 71d5239823 Revert "Closes ##7225 - Improve generate_freestyle_linework to robustly handle SVG output by falling back to the first generated linework file if the expected file is missing."
This reverts commit 89c039252b.
2025-10-11 19:02:04 +11:00
Dion Moult 92ae79f64e See #7133. Sync viewport visibility with render visibility when generating underlays. 2025-10-11 18:48:46 +11:00
Dion Moult 9c1f636cd4 Revert "Reintroduce https://github.com/IfcOpenShell/IfcOpenShell/issues/7133 : Add hide_render synchronization to isolate_objects so hidden viewport objects are also hidden from render"
This reverts commit 23c60b38fd.
2025-10-11 18:09:52 +11:00
Ryan Schultz 23c60b38fd Reintroduce https://github.com/IfcOpenShell/IfcOpenShell/issues/7133 : Add hide_render synchronization to isolate_objects so hidden viewport objects are also hidden from render 2025-10-10 22:24:57 -05:00
Ryan Schultz 89c039252b Closes ##7225 - Improve generate_freestyle_linework to robustly handle SVG output by falling back to the first generated linework file if the expected file is missing. 2025-10-10 17:28:15 -05:00
Thomas Krijnen 60d85b4259 Skip ifcxml writing tests 2025-10-09 14:03:35 +02:00
Thomas Krijnen e8a382b02a Only use cyclic dependencies when amongst static libs #7180 2025-10-09 13:24:31 +02:00
Thomas Krijnen 2b3ec66017 mark failed_on_purpose on IfcBoundingBox without --keep-bounding-boxes #7215 2025-10-09 08:45:25 +02:00
Thomas Krijnen 97dd37b345 Fix circular definition issue in cmake #7180 2025-10-08 15:25:38 +02:00
Thomas Krijnen e4877e8246 Ignore steal_instances() in python 2025-10-08 14:55:28 +02:00
Thomas Krijnen e216d345c1 Reimplement cecho.cmd to not depend on starting powershell.exe for speed boost 2025-10-08 14:18:52 +02:00
Thomas Krijnen 14c1b70768 Address some compiler warnings 2025-10-08 14:18:17 +02:00
Thomas Krijnen e15f222a19 Address segfault #7215 #7185 2025-10-08 14:17:47 +02:00
Ryan Schultz 4ab2664529 closes #7134 - Wall layer cuts exported out to a SVG during Freestyle linework mode. 2025-10-07 14:43:11 -05:00
Dion Moult bd0cfa5366 Fix bug where grid decorator only considered hide states, not hide viewport state or local isolation, etc 2025-10-07 14:44:57 +11:00
Dion Moult 2e4b0e83a2 Add feature to have work schedule columns for total inputs, outputs, and elements (inputs + outputs) 2025-10-07 13:34:07 +11:00
Dion Moult cf61111386 Fix bug where nested elements didn't show elements of the active task (only children) 2025-10-07 13:06:26 +11:00
Dion Moult 3aa5ddb070 Implement auto element selection for tasks in work schedule. Also add manual selection (instead of going into ICOM panel for speed) 2025-10-07 12:27:38 +11:00
Dion Moult 25dacc8fed Fix #7208. Merge duplicates patch recipe can now control merging by empty attributes. 2025-10-06 23:18:32 +11:00
Dion Moult 7cba63af9c Add IfcTester webapp workflow (#7209) 2025-10-06 23:15:16 +11:00
Dion Moult 3c1d6abc7e Update ci-ifctester-org.yml attempt 2 2025-10-06 17:51:50 +11:00
Dion Moult 8da4b9f23f Create ci-ifctester-org.yml
This definitely won't work the first time
2025-10-06 17:41:21 +11:00
Dion Moult 99fa77edee Fix #6873. Bug where geometry created through sync_references didn't have item editing metadata. 2025-10-06 17:23:29 +11:00
Andrej730 839c5ad932 black . 2025-10-06 11:02:33 +05:00
Dion Moult b68ce08811 Deprecate should_reload and is_global in switch representation as they don't do anything now.
Superseded by item editing mode, so always reload, and always global.
2025-10-06 16:57:54 +11:00
Dion Moult e662308665 Deprecate should_sync_changes_first for switching representation, since it is no longer relevant in item editing. 2025-10-06 16:19:39 +11:00
Andrea Ghensi a2ccff67ca fix(bcf): Create directory entries in the zip file's central directory (#7175)
This is done to comply with the Implementation Agreements
https://github.com/buildingSMART/BCF-XML/tree/release_3_0/Documentation#create-directory-folder-entries-in-the-zip-files-central-directory
2025-10-06 15:50:03 +11:00
Christoph Mellüh 8e045d772c Add "hide empty Specifications" to Bonsai IFCTester (#7190)
* add filter

* apply filter property

* allow name filter

* black .

* add hide-skipped to html

* rename prop

* only hide optional specifications
2025-10-06 15:49:35 +11:00
Christoph Mellüh 16fd614886 Add instructions to IFCTester in Blender (#7195)
* add instructions to blender ui

* add requirement instructions to html

* black .
2025-10-06 15:48:45 +11:00
Dion Moult f31df307c6 Fix #6674. Bug where newly created annotation types didn't have the necessary metadata for item editing. 2025-10-06 15:46:16 +11:00
Dion Moult 11873a7c51 Fix #7203. Help indicate that author should be an email. Add error styling. 2025-10-06 14:48:22 +11:00
Dion Moult ccccbe23f4 Fix #6709. Support same spatial element type even if not explicit in concept template. 2025-10-06 14:32:53 +11:00
Dion Moult 2173a562be Fix #7157. Don't fail if the bin dir isn't where we expect it (maybe it's packaged differently)
Honestly someone with motivation and coffee needs to take a long hard
look at our packaging and see if we can do a better job.
2025-10-06 14:14:49 +11:00
Dion Moult a11f81f2ce Fix #5701. Spaces are now invisible by default and use viewport hiding. 2025-10-06 14:07:20 +11:00
Dion Moult d3b553c4fb Blender tools for hiding and showing objects 2025-10-06 14:05:57 +11:00
Dion Moult 5eb11c3516 Remove "make spatial elements unselectable" setting because it's superseded by spatial locking. 2025-10-06 14:05:31 +11:00
Dion Moult c195799801 See #7202. Revert to safer way to control visibility.
Pity can't control hide_viewport in bulk, but this is perhaps the next
best thing.
2025-10-06 12:19:03 +11:00
Massimo Fabbro ac5a44a962 See #6570. Now it's possible to specify Description in csv import
Now it is possible to specify the column Description in the csv file in order to specify also the cost item description
2025-10-05 17:49:23 +02:00
Dion Moult 86880e9e62 See #4481. Optimise object visibility even further by using foreach_set.
Note: now we are using hide_viewport not hide_set anymore. There might
be pending issues from this. Also, now because we use foreach_set, we
can quickly also apply hide_render, which saves time during underlay
generation.
2025-10-05 23:20:32 +11:00
Dion Moult f8ccdf1170 See #4481. Optimise first load of drawing by lazy loading annotations. 2025-10-05 23:17:42 +11:00
Dion Moult e3d8473d47 Fix #7166. Don't create glazing constituent for doors without transoms. Clarify framing name. 2025-10-05 20:24:13 +11:00
Dion Moult bd5d4cecbf See #7166. Only show total thickness for layer sets. 2025-10-05 20:13:40 +11:00
Dion Moult 2ede8a2206 Fix #7158. UI didn't expect to find a material constituent set with no constituents.
It's technically valid but makes no sense.
2025-10-05 19:41:52 +11:00
Dion Moult cb77f9bd26 Fix #7179. Allow drawing polylines with segments as short as 1mm (previously 100mm which was too high) 2025-10-05 19:30:48 +11:00
Dion Moult 0bb21fedae Fix #7169. Bug where unit scale wasn't set for geometric operations on new projects. 2025-10-05 19:09:47 +11:00
Dion Moult 478f90c2d4 Update IfcTester webapp to use IfcTester logo 2025-10-05 18:46:05 +11:00
Dion Moult a016f6e5c8 Fix #7186. Support upgrading IFC2X3 IfcExtendedMaterialProperties to IFC4 2025-10-05 18:44:14 +11:00
Dion Moult 1b2fa4f994 Fix #7113. IfcTester webapp should use uppercase entity names 2025-10-05 15:32:55 +11:00
Christoph Mellüh 2d8383efc6 Fix MASSUNIT bug (#7173)
* add exception

* black
2025-10-05 15:31:06 +11:00
Dion Moult add5132dec Fix launching of IfcTester webapp with Bonsai 2025-10-05 15:11:18 +11:00
Andrej730 fe333051df build-deps - note on cloning opencollada 2025-10-04 21:40:07 +05:00
Andrej730 8d1b533f91 run-cmake.bat - echo SWIG_INSTALL_DIR
as `SWIG_DIR` is no longer used
2025-10-04 21:40:07 +05:00
Andrej730 fb304e141a build-all.py - note on doubled compilation times 2025-10-04 21:40:07 +05:00
Andrej730 bd094f930e build_rocky - support ccache 2025-10-04 21:40:07 +05:00
Andrej730 b61000d2fe ci.yml - bump ccache action version 2025-10-04 21:40:07 +05:00
Andrej730 c72cadb234 build_rocky_arm - use ccache 2025-10-04 21:40:06 +05:00
Andrej730 10642177a9 build_osx - bump ccache workflow version 2025-10-04 21:40:06 +05:00
Andrej730 0b8ea28463 aud - use main repo
As PR with a fix was merged
2025-10-04 21:40:06 +05:00
Andrej730 9b24f54f0d cmake - override CGAL_Boost_USE_STATIC_LIBS
The issue was with ci.yml - it was using system boost shared libraries (since Boost_USE_STATIC_LIBS by default is OFF), but CGALConfig was overriding leading to compilation issues.
2025-10-04 21:40:06 +05:00
Andrej730 289645dacc ci.yml - let cmake figure out system dependencies automatically 2025-10-04 21:40:06 +05:00
Andrej730 c365acb517 ci.yml - don't provide ccache explicitly
as it's covered automatically by cmake
2025-10-04 21:40:06 +05:00
Andrej730 785cf56621 cmake - specify cxx component for hdf5 package
by default it's targeting `C` and this was part of the issue why ci.yml was failing
2025-10-04 21:40:06 +05:00
Andrej730 60617eecce ci.yml - add ccache for rocksdb
Revert "ci.yml - add ccache for rocksdb"

This reverts commit 71178d4bbc023c793b0800f5987a979fdddc1c30.

Update ci.yml
2025-10-04 21:40:06 +05:00
Andrej730 26c68c00b7 cmake - proceed to package search if HDF5_LIBRARY_DIR not provided
Fixes issue with ci.yml
2025-10-04 21:40:05 +05:00
Esteban Dugueperoux ab0a602f9f black: Format incorrectly formated files (#7194) 2025-10-04 18:59:42 +05:00
Osyotr 066326ab3b Fix warning C4275
It's not enough to disable this warning by adding /wd4257 at build time because it's triggered when the library is consumed.
2025-10-03 18:12:56 +02:00
Thomas Krijnen 02713dbd39 nix build script add occt 7.9.1 patch 2025-10-03 18:08:37 +02:00
Thomas Krijnen d58dae5d2f nix build script add occt 7.9.1 patch 2025-10-03 18:05:39 +02:00
Thomas Krijnen ca3685900f Update clear_schemas() which is now handled by unique_ptr 2025-10-03 14:18:50 +02:00
Thomas Krijnen 5e10e61aca Clean-up parsed simple types #7185 2025-10-03 14:18:07 +02:00
Osyotr 92e25ce3cb Fix warning C4702: unreachable code 2025-10-03 13:56:10 +02:00
Thomas Krijnen 804a670454 Revert revert 2025-10-03 09:04:43 +02:00
Thomas Krijnen efa8382fc5 ifcopenshell.draw --arange-zones see http://blog.ifcopenshell.org/2025/10/bim-legal-2d-notorial-drawings-directly.html 2025-10-02 21:44:52 +02:00
Thomas Krijnen 92f9d5f506 Writing .ifcxml is not supported #7181 2025-10-02 20:28:17 +02:00
Ryan Schultz 8800c14105 extended previous commit to add functionality to printed svg, as well. 2025-10-01 23:21:14 -05:00
Ryan Schultz ec2d0bfa4a Add support for reversing and customizing separators in text annotation lists
Text annotations can now reverse the order of list values (e.g., materials) and use custom separators instead of the default comma-space. Two new properties have been added to EPset_Annotation: Reverse_List (boolean) and List_Separator (string). When text literals contain IFC list/tuple values, they are now detected during variable replacement and can be reversed and joined with the specified separator. The list separator supports escape sequences like \n for newlines, enabling multi-line list displays. These properties are exposed in the text editing UI and properly persist to the IFC file through the new update_text_annotation_properties method, which consolidates all annotation property updates into a single efficient operation.
2025-10-01 22:44:34 -05:00
Thomas Krijnen d684d47dc8 Make sure compound structure is retained as SvgSerializer depends on it 2025-10-01 15:01:50 +02:00
Andrej730 babf95785c Move IFCOPENSHELL_VERSION definition from IfcParse.h
To prevent recompiling all files that have IfcParse.h include and improve caching.
2025-09-30 19:17:46 +05:00
Andrej730 f6ebf80fab ifcopenshell-python/scripts/dev_environment.py 2025-09-30 17:47:30 +05:00
Andrej730 ea2cff3311 typing 2025-09-30 17:47:30 +05:00
Andrej730 bf4aa8cbb1 cmake - link mappings against IfcGeom
Not sure why it occurred only now, maybe after recent changes with shared libraries this problem just got more apparent and previously it was masked by some other library after mappings also using IfcGeom.
But the issue was that mapping were not linked against IfcGeom, though it's symbols were used in them. E.g. IfcSectionedSurface.cpp was using `has_loft` from `infra_sweep_helper`.
Issue occurred only on Linux - msvc and clang are less strict and probably do multiple passes to fetch symbols.

Example errors:
```
libgeometry_mapping_ifc4x3.a(IfcSectionedSolidHorizontal.cpp.o): In function `ifcopenshell::geometry::mapping_Ifc4x3::map_impl(Ifc4x3::IfcSectionedSolidHorizontal const*)':
IfcSectionedSolidHorizontal.cpp:(.text._ZN12ifcopenshell8geometry14mapping_Ifc4x38map_implEPKN6Ifc4x327IfcSectionedSolidHorizontalE+0x19a4): undefined reference to `ifcopenshell::geometry::make_loft(ifcopenshell::geometry::Settings const&, IfcUtil::IfcBaseClass const*, std::shared_ptr<ifcopenshell::geometry::taxonomy::function_item> const&, std::vector<ifcopenshell::geometry::cross_section, std::allocator<ifcopenshell::geometry::cross_section> >&)'
libgeometry_mapping_ifc4x3.a(IfcSectionedSurface.cpp.o): In function `ifcopenshell::geometry::mapping_Ifc4x3::map_impl(Ifc4x3::IfcSectionedSurface const*)':
IfcSectionedSurface.cpp:(.text._ZN12ifcopenshell8geometry14mapping_Ifc4x38map_implEPKN6Ifc4x319IfcSectionedSurfaceE+0x19c4): undefined reference to `ifcopenshell::geometry::make_loft(ifcopenshell::geometry::Settings const&, IfcUtil::IfcBaseClass const*, std::shared_ptr<ifcopenshell::geometry::taxonomy::function_item> const&, std::vector<ifcopenshell::geometry::cross_section, std::allocator<ifcopenshell::geometry::cross_section> >&)'
libgeometry_mapping_ifc4x3_tc1.a(IfcSectionedSolidHorizontal.cpp.o): In function `ifcopenshell::geometry::mapping_Ifc4x3_tc1::map_impl(Ifc4x3_tc1::IfcSectionedSolidHorizontal const*)':
IfcSectionedSolidHorizontal.cpp:(.text._ZN12ifcopenshell8geometry18mapping_Ifc4x3_tc18map_implEPKN10Ifc4x3_tc127IfcSectionedSolidHorizontalE+0x19a4): undefined reference to `ifcopenshell::geometry::make_loft(ifcopenshell::geometry::Settings const&, IfcUtil::IfcBaseClass const*, std::shared_ptr<ifcopenshell::geometry::taxonomy::function_item> const&, std::vector<ifcopenshell::geometry::cross_section, std::allocator<ifcopenshell::geometry::cross_section> >&)'
libgeometry_mapping_ifc4x3_tc1.a(IfcSectionedSurface.cpp.o): In function `ifcopenshell::geometry::mapping_Ifc4x3_tc1::map_impl(Ifc4x3_tc1::IfcSectionedSurface const*)':
IfcSectionedSurface.cpp:(.text._ZN12ifcopenshell8geometry18mapping_Ifc4x3_tc18map_implEPKN10Ifc4x3_tc119IfcSectionedSurfaceE+0x19c4): undefined reference to `ifcopenshell::geometry::make_loft(ifcopenshell::geometry::Settings const&, IfcUtil::IfcBaseClass const*, std::shared_ptr<ifcopenshell::geometry::taxonomy::function_item> const&, std::vector<ifcopenshell::geometry::cross_section, std::allocator<ifcopenshell::geometry::cross_section> >&)'
libgeometry_mapping_ifc4x3_add1.a(IfcSectionedSolidHorizontal.cpp.o): In function `ifcopenshell::geometry::mapping_Ifc4x3_add1::map_impl(Ifc4x3_add1::IfcSectionedSolidHorizontal const*)':
IfcSectionedSolidHorizontal.cpp:(.text._ZN12ifcopenshell8geometry19mapping_Ifc4x3_add18map_implEPKN11Ifc4x3_add127IfcSectionedSolidHorizontalE+0x19a4): undefined reference to `ifcopenshell::geometry::make_loft(ifcopenshell::geometry::Settings const&, IfcUtil::IfcBaseClass const*, std::shared_ptr<ifcopenshell::geometry::taxonomy::function_item> const&, std::vector<ifcopenshell::geometry::cross_section, std::allocator<ifcopenshell::geometry::cross_section> >&)'
libgeometry_mapping_ifc4x3_add1.a(IfcSectionedSurface.cpp.o):IfcSectionedSurface.cpp:(.text._ZN12ifcopenshell8geometry19mapping_Ifc4x3_add18map_implEPKN11Ifc4x3_add119IfcSectionedSurfaceE+0x19c4): more undefined references to `ifcopenshell::geometry::make_loft(ifcopenshell::geometry::Settings const&, IfcUtil::IfcBaseClass const*, std::shared_ptr<ifcopenshell::geometry::taxonomy::function_item> const&, std::vector<ifcopenshell::geometry::cross_section, std::allocator<ifcopenshell::geometry::cross_section> >&)' follow
collect2: error: ld returned 1 exit status
```
2025-09-30 13:10:59 +05:00
Andrej730 8b751577f4 Fix Ruff UP037 (unnecessary quotes in annotations) 2025-09-30 13:04:48 +05:00
Andrej730 6fbe982623 Fix Ruff UP006 (List -> list) 2025-09-30 13:04:48 +05:00
Andrej730 0b93694097 black . 2025-09-30 13:04:48 +05:00
Dion Moult 2027c71d99 Fix #7164. Property facets with a restriction in the baseName would incorrectly test null values.
Our tests missed this detail. The previous test also did
should_purge=True by default which doesn't property test for nullness.
2025-09-30 00:07:14 +10:00
Dion Moult 6da51c2a6e Update IfcTester to support changed upstream spec where prohibited specs cannot have requirements. 2025-09-30 00:05:57 +10:00
Fernando Gussão Bellon 53def55dc9 Added the file extension to the viewpoint guid comparison 2025-09-29 23:41:37 +10:00
Robin Quint 8722350c0b Plan view fixes (#7022) 2025-09-29 23:40:35 +10:00
Andrea Ghensi 34c92d4d9c fix(bcf): viewport creation functions result in malformed XML
fixes #6244
2025-09-29 23:33:15 +10:00
daniel-augusto 725cb40ef2 Update highlight from block code 2025-09-29 23:30:39 +10:00
daniel-augusto 0c81b41ac7 Update highlight of block code 2025-09-29 23:30:39 +10:00
Yan Peng a8a82450a5 Update documentation of bsdd based on the updated info of uri and bsdd functions. 2025-09-29 23:29:57 +10:00
Andrea Ghensi 1b5b9fdcf6 fix: use numpy 2d indexing, avoid np.matrix
fixes #7141
2025-09-29 23:29:08 +10:00
c-mellueh af1e542064 black 2025-09-29 23:28:20 +10:00
c-mellueh 78154d17bf add button 2025-09-29 23:28:20 +10:00
c-mellueh 9bc8012aa4 remove old function 2025-09-29 23:27:04 +10:00
c-mellueh 407962ec93 black 2025-09-29 23:27:04 +10:00
c-mellueh 21fd09b424 add bsdd_json 2025-09-29 23:27:04 +10:00
Andrej730 2264e69a1e cmake - remove redundant msvc check for ccache (e02d6c3f) 2025-09-29 17:39:43 +05:00
Andrej730 e02d6c3f4b cmake - support ccache for msvc (required cmake 3.25+)
As described in https://github.com/ccache/ccache/wiki/MS-Visual-Studio#usage-with-cmake
2025-09-29 16:43:29 +05:00
Andrej730 ec0abb7b37 cmake - fix missing installation for ifcgeom/serialization headers
Was trying to reproduce IfcOpenHouse example outside of IfcOpenShell project and noticed that it's referring to a header not present in installation.
2025-09-29 16:43:29 +05:00
Andrej730 477becab0b ruff - use preview behaviour
No particular preview rules we need, just to possibly early adapt new behavior.
2025-09-29 16:43:28 +05:00
Andrej730 60bf424461 ruff - remove from config a rule removed from ruff 2025-09-29 16:43:28 +05:00
Andrej730 923e8423f9 black . 2025-09-29 16:43:28 +05:00
Thomas Krijnen e228095391 Fix geomserver compile 2025-09-29 13:19:46 +02:00
myoualid 1492a660c8 adding paths to include schema files for wasm build (#7168) 2025-09-29 11:55:42 +01:00
Thomas Krijnen 7a931ea6f2 Submodule 2025-09-29 12:07:49 +02:00
Thomas Krijnen 2d59bb9cb8 Remove dependency on stdc++fs lib in cmake #7131 2025-09-29 11:30:40 +02:00
Thomas Krijnen 06f5ded038 Don't crash on missing schema when loading rdb 2025-09-29 11:29:52 +02:00
Thomas Krijnen 91f371a46e Be sure to init header_section_schema when obtaining schemas in python #7131 2025-09-29 11:29:35 +02:00
Thomas Krijnen 573e53ebfd Ugly workarounds to not depend on std::filesystem #7131 2025-09-29 11:29:07 +02:00
myoualid a492be5971 include schema files for Pyodide build via MANIFEST.in 2025-09-29 09:41:09 +01:00
Dion Moult ceac85ca02 Temporarily revert to old build behaviour since new builds are failing. 2025-09-29 11:00:59 +10:00
Dion Moult bfa981709a Fix regression. Schema should not be a Python package. 2025-09-29 10:43:14 +10:00
myoualid c64b477e53 last attempt to fix WASM build: libxml2 without threads and use explicit libxml2 paths 2025-09-29 00:49:12 +01:00
myoualid 4f7501e1e8 set Eigen3 path for WASM build to avoid find_package issues following commit 235eb3c83c 2025-09-28 21:56:27 +01:00
myoualid a1f20ec7bb add explicit OCCT paths for WASM builds 2025-09-28 20:20:43 +01:00
myoualid e2ee6c6e56 Fix WASM build by reverting CGAL handling to explicit paths from commit 3ec7b71565 2025-09-28 16:43:58 +01:00
myoualid 6940a05f2b remove yacc dependency for wasm build 2025-09-28 13:51:38 +01:00
myoualid ff8f4ecd3c Revert "add bison dependency for pyodide wasm build"
This reverts commit cfa21b3cbf.
2025-09-28 13:37:30 +01:00
Dion Moult de2bd3ff1a Fix #6914. Bug where HTML IDS report did not visually indicate prohibited results correctly. 2025-09-28 22:26:39 +10:00
myoualid cfa21b3cbf add bison dependency for pyodide wasm build 2025-09-28 12:21:50 +01:00
Dion Moult db7c3e3b01 Fix #6960. String reporting of cardinality did not match upstream docs.
The meaning of the upstream docs changed subtly a year ago and I never
caught up. There is still work to do.
2025-09-28 20:35:55 +10:00
myoualid 0532ceb029 Fix missing files in WASM build (#7168) 2025-09-28 11:30:23 +01:00
Dion Moult 0fe869c169 See #7131. Rollback to prevent instant segfaults on Linux. 2025-09-28 18:15:13 +10:00
myoualid bcde68d851 reproduce WASM missing schema files bug (#7168) 2025-09-27 20:54:23 +01:00
Bruno Perdigão 960a90e36c See commit 17d6b8a. Add a patch to update linked aggregates psets.
https://github.com/IfcOpenShell/IfcOpenShell/commit/17d6b8af61c8dd7cd82f6e72b2fb3831d851a33d#commitcomment-163151609
2025-09-26 22:57:18 -03:00
Bruno Perdigão aea0395fd6 See #7046. Remove snapping points that are not visible with clipping
planes.
2025-09-26 21:59:18 -03:00
Bruno Perdigão 416d51f7c7 Fix small issue with None value in polyline increment snap 2025-09-26 21:59:18 -03:00
Bruno Perdigão a9b13fd056 See #7046. Adapt snapping system to focal length value. 2025-09-26 21:59:17 -03:00
Andrej730 080056806e build_osx - separate arm64 ccache to avoid override 2025-09-26 21:53:33 +05:00
Andrej730 7a33a9eb02 build_osx - fix issue building arm64 2025-09-26 21:53:33 +05:00
Andrej730 07ba483a13 build-all - bump Python version to fix issue cross compiling
Not sure which patch version exactly fixed it, but 3.13.6 works.
2025-09-26 21:53:33 +05:00
Andrej730 4925741060 build_osx - add deps for cross compilation 2025-09-26 21:53:33 +05:00
Andrej730 7c4505b2fd build_osx - exclude arm64 gmp dependency to avoid cross compilation issues 2025-09-26 21:53:33 +05:00
Andrej730 f9ee838cd2 build-all - cross compile dependencies 2025-09-26 21:53:32 +05:00
Andrej730 cce0c39ab2 build-all.py - provide with-openssl for python on Mac 2025-09-26 21:53:32 +05:00
Andrej730 cd57fd4b1d build_osx - note on preinstalled dependencies 2025-09-26 21:53:32 +05:00
Andrej730 6b705f0448 build-all.py - document ADD_COMMIT_SHA env var 2025-09-26 21:53:32 +05:00
Andrej730 9cff6c87f0 cmake - don't fail silently with ADD_COMMIT_SHA and missing git 2025-09-26 21:53:32 +05:00
Andrej730 cac41064e0 build_osx - attempt to cross-compile intel binaries
ccache step broke (https://github.com/hendrikmuhs/ccache-action/issues/374) and macos-13 is now deprecated in general -
https://github.blog/changelog/2025-09-19-github-actions-macos-13-runner-image-is-closing-down/
2025-09-26 21:53:32 +05:00
Andrej730 350cf0406d build-all.py - override minimum cmake version for OpenCOLLADA 2025-09-26 21:53:32 +05:00
Andrej730 47fd52b7c1 build-all.py - bump eigen package to avoid issues on cmake 4 2025-09-26 21:53:32 +05:00
Andrej730 8a33e2fea1 workflows - unify ccache names 2025-09-26 21:53:31 +05:00
Andrej730 d4c02a312a build-all.py - bump json package to avoid issues on cmake 4 2025-09-26 21:53:31 +05:00
Andrej730 c20294b993 build_osx - upload logs artifacts to help debugging 2025-09-26 21:53:31 +05:00
Andrej730 7500631b81 build-rocky - upload logs artifacts to help debugging 2025-09-26 21:53:31 +05:00
Andrej730 7cc1a849a6 build-all.py - opencollada patch to support config package on Unix 2025-09-26 21:53:31 +05:00
Andrej730 4df93af1fd build-all.py - add OpenCOLLADA to IfcGeom dependencies
Otherwise it can be overlooked if you build IfcOpenShell-Python or any other target specifically, it was only built if you run build-all.py without any target arguments.
2025-09-26 21:53:31 +05:00
Andrej730 fc1c8f2071 build-all.py - CGAL to use v5.6.3
5.6.x-branch was removed, see https://github.com/CGAL/cgal/issues/9079
2025-09-26 21:53:31 +05:00
Andrej730 deedffa84e build-all.py - alter rocksdb's deps search only on Windows (da4508e) 2025-09-26 21:53:31 +05:00
Andrej730 e8d924426f build-all.py - add a note about xz requirement 2025-09-26 21:53:30 +05:00
Andrej730 5a3f809d03 build-all.py - fix Python 3.6 support for rocky (566c9af) 2025-09-26 21:53:30 +05:00
Andrej730 58ffd8bf62 ruff ci - check python 3.7 compatibility for build-all.py 2025-09-26 21:53:30 +05:00
Andrej730 b22452aaac build-all.py - print all missing commands simultaneoously 2025-09-26 21:53:30 +05:00
Andrej730 6c05e2ea8c Fix missing yacc in linux builds 2025-09-26 21:53:30 +05:00
Andrej730 a1773b6f46 black . 2025-09-26 21:53:30 +05:00
Andrej730 b3583d4191 typing 2025-09-26 21:52:35 +05:00
Thomas Krijnen 50e8d9f67e submodule 2025-09-26 14:32:34 +02:00
Thomas Krijnen 0d4819d6e7 dllimport/export #6926 2025-09-26 14:30:52 +02:00
Thomas Krijnen ce91d296b6 dllimport/export #6926 2025-09-26 14:24:49 +02:00
Ryan Schultz 21137b9268 closes:#6821 - This modification checks if the layer's material has a Category attribute and if it's not empty, then adds it as a CSS class with the format layer-material-category-{category_name}.
This will give you additional styling granularity when working with material layers, allowing you to target elements not just by their material name but also by their material category in your SVG styling.
2025-09-25 14:57:41 -05:00
Thomas Krijnen 0dc319e510 Fix compilation on older gcc versions required pod type for __thread 2025-09-25 13:17:12 +02:00
Bruno Perdigão 798beb0030 See #7046. Improve snapping inaccuracies in orthographic view 2025-09-24 17:46:55 -03:00
falken10vdl a717b348e0 Fix bounding box best origin default value
Initialize best_origin to 0 for the case no better origin is found.
Cheers!
2025-09-24 14:42:31 -03:00
falken10vdl 14ed4d1d08 feat: add comparison property to ifc_filter in draw_filter and update search query logic 2025-09-24 12:28:20 -03:00
Bruno Perdigão bd3250aff6 See #6883. Keeps each linked aggregate in their original container after refreshing. 2025-09-24 09:46:02 -03:00
Bruno Perdigão 1ee5bb73fa Fix RefreshLinkedAggregates renaming of aggregates 2025-09-24 09:46:02 -03:00
Thomas Krijnen 9a6dc54f6c Thread local current_product_ #7155 2025-09-24 13:56:35 +02:00
Thomas Krijnen ab59173135 Add a stream2_from_string() (mostly for wasm) 2025-09-23 11:32:52 +02:00
Thomas Krijnen b6abb24858 Support single circ/elip compcurves #7149 2025-09-23 11:11:42 +02:00
Thomas Krijnen 2b24d5ebe5 Initialize header schema in constructor and not statically #7131 2025-09-23 10:26:01 +02:00
Ryan Schultz 10a99fff05 Closes #7133: when activating a drawing, Bonsai will turn on/off 'Display in Render' when it turns on/off 'Hide in Viewport'. 2025-09-22 20:12:24 -05:00
Ryan Schultz 64aa1d07fb extend #6777 to have elevation print out as well. 2025-09-21 16:26:36 -05:00
Bruno Perdigão 730eafa74f IfcMaterialLayerSetUsage - Disable custom offset properties when the checkbox is unchecked 2025-09-19 17:41:03 -03:00
Andrej730 c077727374 Fix header data attr to match Blender prop names (559636e) 2025-09-19 19:07:44 +05:00
Andrej730 2e4241e435 typing 2025-09-19 19:04:53 +05:00
Andrej730 8a03a1379e cmake - match ifc4x3 for examples more precisely 2025-09-19 18:56:15 +05:00
Andrej730 8bb7ef5e25 cmake - only build examples if 2x3 is present in SCHEMA_VERSIONS
As examples currently require ifc2x3
2025-09-19 18:56:15 +05:00
Andrej730 da4508ef9a cmake - fix issue rocksdb locating zstd on Windows
See https://github.com/facebook/rocksdb/pull/13975 for the details.
2025-09-19 18:44:18 +05:00
Thomas Krijnen f3dedba320 Map opt<bool> in taxonony to none,false,true 2025-09-19 13:24:02 +02:00
Thomas Krijnen f659b9bb7b Fix exception in file.from_string() 2025-09-19 13:24:02 +02:00
Andrej730 488dee82d7 bim.create_all_shapes - add description and more readable output 2025-09-19 13:16:11 +05:00
Andrej730 3c4020be8d create_all_shapes - expose geom library selection to UI
Example - https://files.catbox.moe/oyv9bi.png
2025-09-19 13:16:11 +05:00
Thomas Krijnen ede4e49c0c submodule 2025-09-19 09:54:01 +02:00
Andrej730 3d2f361585 cmake - fix error with occt package (1857d0624) 2025-09-18 18:36:48 +05:00
Andrej730 4505ed1c98 cmake - remove trailing spaces 2025-09-18 18:36:48 +05:00
Andrej730 4cbad8804f cmake - use OpenCASCADE_VERSION as a version source if available 2025-09-18 18:36:48 +05:00
Andrej730 3ec7b71565 build-all.py - use find_package for CGAL 2025-09-18 17:53:35 +05:00
Andrej730 c0ec2e7e2b cmake - use find_package if explicit paths are not provided 2025-09-18 17:53:35 +05:00
Andrej730 048a94ddc5 build-all.py - bump json version and use find_package 2025-09-18 17:53:34 +05:00
Andrej730 ec43415822 cmake - support find_package for json 2025-09-18 17:53:34 +05:00
Andrej730 235eb3c83c build-all.py - use find_package for eigen3 2025-09-18 17:53:34 +05:00
Andrej730 4d0737c49b build-all, run-cmake - pass BOOST_ROOT as cmake prefix path 2025-09-18 17:53:34 +05:00
Andrej730 b499686c7c build-all.py - use find_package for occt 2025-09-18 17:53:34 +05:00
Andrej730 1857d06245 cmake - use find_package for occ if variables are not provided
cmake configs seems to be provided with the default installation, so `find_package` should do the job that `find_path` and `find_library` did previously.
2025-09-18 17:53:33 +05:00
Andrej730 663d233e3c build-all.py - document more env variables 2025-09-18 17:53:33 +05:00
Andrej730 fa1936c10a build-all.py - avoid building 3d viewer for OCCT 2025-09-18 17:53:33 +05:00
Andrej730 8c89ba497b build-all.py - use find_package for opencollada 2025-09-18 17:20:57 +05:00
Andrej730 2284ddd68c build-all.py - use find_package for libxml2 2025-09-18 17:20:55 +05:00
Andrej730 8daf6b0b04 build-all.py - use find_package for swig 2025-09-18 17:20:52 +05:00
Andrej730 e7a6f86299 build-all.py - don't break in case if some optional dependencies are missing 2025-09-18 14:07:58 +05:00
Andrej730 cae711b393 build-all.py - mention ssl requirement for Python (4ee6863) 2025-09-18 14:07:58 +05:00
Andrej730 566c9afa77 build-all.py - print live logs to the log file 2025-09-18 14:07:58 +05:00
Andrej730 867852688e cmake - use find_package for hdf5 as a general fallback
Previously we were setting `HDF5_LIBRARIES` explicitly, but I'm not sure if really worked, since we never set `HDF5_INCLUDE_DIR` and user would have to provide it manually either way.
`find_package(HDF5)` will search for default paths and will set `HDF5_LIBRARIES` and `HDF5_INCLUDE_DIR` automatically.
2025-09-18 14:07:58 +05:00
Andrej730 94851016d7 build-all.py - use find_package for hdf5 2025-09-18 14:07:58 +05:00
Andrej730 1dd3c298df build-all.py - explicitly disable xlib
I assume it's not needed, but Desktop Ubuntu seems to trying to build it anyway and fails since `libx11-dev` is missing.
2025-09-18 14:07:58 +05:00
Andrej730 c384ac26cd build-all.py - use pcre2 for swig
As it was needed for more recent swig version. Bumped swig in ae771cb without knowing this, so essentially building swig with build-all.py was broken for a bit.
2025-09-18 14:07:58 +05:00
Andrej730 a57080da74 build-all.py - ensure yacc is installed 2025-09-18 14:07:58 +05:00
Andrej730 71e59fe4c2 build-all.py - remove 'rel-' from swig tags
As they were used by the older versions and no longer provided after 4.1.0, see https://github.com/swig/swig/tags
2025-09-18 14:07:58 +05:00
Andrej730 aedae0b3c1 build-all.py - hdf5 to use cmake instead of ctest
After version 1.13.0 it seems hdf5 stopped publishing builds on the ftp and they also stopped publishing `CMake-hdf5-*` builds.
Switching to cmake, it will also make it consistent with build-deps.cmd
2025-09-18 14:07:58 +05:00
Andrej730 658f9b87a5 build-deps.cmd - bump hdf5 to match build-all
Has to skip hdf5 1.13.0 because it had a bug in it's cmake config setup, so `find_package` couldn't recognize, and the issue was fixed in 1.13.1.
2025-09-18 14:07:58 +05:00
Andrej730 fa9105e174 black . 2025-09-18 14:07:58 +05:00
Andrej730 d0d5f972df cmake - use find_package for rocksdb and zstd 2025-09-18 14:07:58 +05:00
Bruno Perdigão f5220fba56 Add custom offset to walls IfcMaterialLayerSetUsage 2025-09-15 17:08:25 -03:00
Bruno Perdigão 365f4f114b Add custom offset to slab IfcMaterialLayerSetUsage 2025-09-15 17:08:25 -03:00
Thomas Krijnen b5b64d6c4a ifc5d.quantify: lookup entity names directly; index into dict rather than iterate in simple cases 2025-09-15 18:29:58 +02:00
Andrej730 632e45af18 Fix missing platform in flask wheels (6497d5f) 2025-09-15 18:27:22 +05:00
Andrej730 559636ef0b IFC Header UI - display author and additional info in case if it's available 2025-09-15 18:27:21 +05:00
Andrej730 5a2ed576c4 Fix ids.from_string always breaking on validation (4a9cf43)
Since `tree` is never provided.
2025-09-15 18:27:21 +05:00
Andrej730 cc7732ecbf Replace .wrapped_data.header with .header (dfaa8d5) 2025-09-15 18:27:21 +05:00
Andrej730 a3c6e295c8 ifcopenshell_wrapper.pyi - remove HeaderEntity
Recently (e.g. ce02e7a) header entity was replaced with a generic `entity_instance`.
2025-09-15 18:27:20 +05:00
Andrej730 87069f3ac3 Groups/Systems UI - expand parent group when child group is added
So user can immediately see the added item, it seems more intuitive.
2025-09-15 18:27:20 +05:00
Andrej730 6469f79343 Groups/Systems UI - removing item to update uilist index 2025-09-15 18:27:20 +05:00
Andrej730 a3b04997ef Systems UI - display icons for each system type in the dropdown
Example - https://files.catbox.moe/rnyuro.png
2025-09-15 18:27:20 +05:00
Andrej730 4c1af9e2f5 Systems UI - display hierarchy of systems #7062 2025-09-15 18:27:19 +05:00
Andrej730 646f2f2e32 Add tool for 'group' module 2025-09-15 18:27:19 +05:00
Andrej730 629d6c85ae assign/unassign group - add info message 2025-09-15 18:27:19 +05:00
Andrej730 be66d4884d typing 2025-09-15 18:27:19 +05:00
Andrej730 5de96c9f95 Systems UI - support adding child systems #7062 2025-09-15 18:27:18 +05:00
Thomas Krijnen c661bb62ca Rework header access in exception handling 2025-09-15 12:01:13 +02:00
Thomas Krijnen b1b95ec2db Conditional compilation in wrapper 2025-09-14 19:15:31 +02:00
Thomas Krijnen 5f50e6fcf1 Conditional compilation in wrapper 2025-09-14 19:15:25 +02:00
Thomas Krijnen 23b48c43a6 Conditional compilation 2025-09-14 13:53:33 +02:00
Thomas Krijnen 75e1d0e3c7 Update CMakeLists.txt - wasm build add "4x3_add2" 2025-09-14 11:38:33 +02:00
Sayan Jyoti Das 0d942f968a fix: cleanup pyodide tmpdir properly 2025-09-14 07:13:54 +10:00
Thomas Krijnen b5ccb93618 Fix Outer bound check in serializer #7099 2025-09-13 14:24:03 +02:00
Andrej730 41fb8ca583 Bump IOS build in Bonsai
Since now we have additional `readonly` argument in `ifcopenshell.open` and we need a new build to support it.
2025-09-12 20:11:07 +05:00
Andrej730 a86904dd41 ifcopenshell.open overload signature to consider new readonly argument 2025-09-12 20:11:07 +05:00
Andrej730 8a82343e27 typing - fix annoying module symbol getting into ifcopenshell.open retun types 2025-09-12 20:11:07 +05:00
Andrej730 8a841b449a build-deps - download releases instead of cloning repo for rocksdb/zstd 2025-09-12 20:11:07 +05:00
Andrej730 24bbe9fb69 cmake - fix typo 2025-09-12 20:11:07 +05:00
Andrej730 9a38455465 black . 2025-09-12 20:11:06 +05:00
Thomas Krijnen ced52862a1 Fix inst id based line lookup in log_internal_cpp_errors() 2025-09-12 16:25:37 +02:00
Thomas Krijnen f0cd8c59c7 Build pyodide wheel without rocksdb 2025-09-12 16:10:19 +02:00
Thomas Krijnen e795cec56b win build: Update instal dir checks 2025-09-11 19:54:51 +02:00
Thomas Krijnen b1248be1b8 wopts.disableWAL for 3x better write performance 2025-09-11 19:10:05 +02:00
Thomas Krijnen 79672f795e Merge pull request #6203 from IfcOpenShell/tfk-rocksdb-storage
RocksDB instance/file storage
2025-09-11 18:39:18 +02:00
Thomas Krijnen 6ec12fe7c7 :Revert "Temporary Python 3.9 compatibility"
This reverts commit 0aae57620f.
2025-09-11 18:38:07 +02:00
Thomas Krijnen 4ee6863d43 nix build script: install some dependencies required for import base package 2025-09-11 18:34:54 +02:00
Andrej730 6497d5f78e Bonsai - add Flask required by ifctester web ui 2025-09-11 18:03:38 +05:00
Andrej730 5b96df89ea Fix error loading ifctester webapp (infinite "initialize environment...")
Browser was stuck trying to initialize the environment, because of the error below:
[worker] Received message: {type: 'init', payload: {…}, id: '9dLz/0eBQDa0xTQORXfdUg/0'} :5000/pyodide/pyodide.mjs:1  Failed to load module script: Expected a JavaScript-or-Wasm module script but the server responded with a MIME type of "text/plain". Strict MIME type checking is enforced for module scripts per HTML spec.
2025-09-11 18:03:38 +05:00
Andrej730 ce4ad3c3a7 ifctester webapp makefile - fix issue on windows 2025-09-11 18:03:38 +05:00
Thomas Krijnen 8d714ed3bc win build zstd paths 2025-09-11 13:56:11 +02:00
Thomas Krijnen 9d99de2340 file.reset_identity_cache() function for adv use cases 2025-09-11 13:56:11 +02:00
Thomas Krijnen 41f9b1522e Pass ZSTD to ifopsh build 2025-09-11 13:56:11 +02:00
Thomas Krijnen 42b1cf039d Revert "Debugging action"
This reverts commit e8b1b6f783.
2025-09-11 13:56:11 +02:00
Thomas Krijnen db832946e6 Update test_validate_rocksdb.py 2025-09-11 10:07:39 +02:00
Thomas Krijnen 05e8680b48 CMAKE_INSTALL_LIBDIR 2025-09-11 09:36:42 +02:00
Thomas Krijnen e8b1b6f783 Debugging action 2025-09-11 09:24:40 +02:00
Thomas Krijnen 9367da61a0 PORTABLE=1 for rocksdb 2025-09-11 09:22:54 +02:00
Thomas Krijnen c7e53e7762 Try different zstd_ config opts 2025-09-11 08:42:44 +02:00
Thomas Krijnen 2260f9983c Try different zstd_ config opts 2025-09-10 21:47:07 +02:00
Thomas Krijnen e68cc7201c Call init_locale() when streaming 2025-09-10 21:42:55 +02:00
Thomas Krijnen e2b39620a0 Test for supported compression 2025-09-10 21:42:30 +02:00
Andrej730 36da945e2d Keep viewport position even if some previous drawing camera is active #7101
during alt+click on drawing activation button
2025-09-10 17:46:01 +05:00
Andrej730 371aeed3f6 Move duplicated properties to ActivateDrawingBase 2025-09-10 17:46:01 +05:00
Andrej730 86902c159b Status UI status assignment - add test 2025-09-10 17:46:01 +05:00
Andrej730 f4be8812e2 Status UI - display active object status using icons
Example - https://files.catbox.moe/ucrtfg.mp4
2025-09-10 17:46:00 +05:00
Andrej730 12bcf1d2c7 bump svgfill 2025-09-10 17:45:53 +05:00
Andrej730 10e805b3f1 black . 2025-09-10 15:34:06 +05:00
Andrej730 1e9239b352 Fix error searching for annotation types #7103 2025-09-10 14:59:46 +05:00
Andrej730 7bea3d9d10 Annotation types - use natural sorting, make 'Untyped' appear always on top 2025-09-10 14:59:45 +05:00
Andrej730 e9bad17502 Fix broken scripts download urls #7107
They were hardcoded and `:download:` wasn't used, so sphinx never copied the scripts to be available to download.
They also were always pointing to main docs website, so they would show up on unstable documentation too, and I guess because they were hardcoded, there were no warnings when those files were recently moved.
2025-09-10 14:40:59 +05:00
Thomas Krijnen be79d3712d Initialize header after storage 2025-09-10 11:37:17 +02:00
Thomas Krijnen e13dbd4767 Take note of zstd cmake path 2025-09-10 11:14:16 +02:00
Thomas Krijnen c61d4bb70a build-all tuple typo 2025-09-10 10:37:05 +02:00
Thomas Krijnen ee632b7c37 Cmake libxml compatibility 2025-09-10 10:36:08 +02:00
Thomas Krijnen f86e5abb85 Cmake libxml compatibility 2025-09-10 10:17:59 +02:00
Thomas Krijnen b5275f5ab2 black 2025-09-10 10:08:14 +02:00
Thomas Krijnen a925226cbc Merge remote-tracking branch 'origin/v0.8.0' into tfk-rocksdb-storage 2025-09-10 10:06:01 +02:00
Thomas Krijnen 06a89f9b17 Add zstd to build-all.py 2025-09-10 10:05:43 +02:00
Thomas Krijnen 231d047ce9 Capture SPF specific errors in validation test 2025-09-10 09:40:20 +02:00
Thomas Krijnen a50fc3184b Minor attribute count fixes 2025-09-10 09:13:16 +02:00
Thomas Krijnen de8c8d3bed Rocksdb header parsing 2025-09-10 09:10:59 +02:00
Thomas Krijnen f8e523daff h| i| t| serialization consistency 2025-09-10 09:10:32 +02:00
Thomas Krijnen 8ca9bd63dc read-only validate 2025-09-10 09:10:03 +02:00
Thomas Krijnen 761b69ebfe test_validate_rocksdb.py 2025-09-10 09:09:48 +02:00
Massimo Fabbro e28979ceb7 See #6570. Better column name for import csv.
Change column name for import rate from csv from Rate Cost Schedule to RateSchedule
2025-09-10 06:50:50 +02:00
Richard Brice d552f247fa Fixed a typo mapping horizontal curve segments to geometry 2025-09-09 13:08:31 -07:00
Richard Brice 8ef083e3af Fixes position of zero-length segment 2025-09-09 12:13:09 -07:00
Thomas Krijnen 49bbf0cb9e Free memory 2025-09-09 13:26:37 +02:00
Thomas Krijnen a2f0bc8a17 Further implement serialization 2025-09-09 13:26:21 +02:00
Thomas Krijnen 62295beab2 Run black 2025-09-09 13:26:01 +02:00
Thomas Krijnen a0b93265c2 Rocksdb storage -- ifcopenshell.file compatibility 2025-09-09 13:25:32 +02:00
Andrej730 338d3cf089 Fix test_package after 12c795a 2025-09-09 16:07:24 +05:00
Andrej730 39702cc543 Fix failing ifc2x3 tests after 3e5a2e5
Also added ifc4x3 tests
2025-09-09 15:42:32 +05:00
Andrej730 a9c0c1f4ba control.unassign_control to support batching 2025-09-09 15:42:32 +05:00
Andrej730 abfb56350d control.assign_control to support batching 2025-09-09 15:42:32 +05:00
Andrej730 fcb263f59a util.element.get_controls 2025-09-09 15:42:31 +05:00
Andrej730 679fa6d876 Option to change text symbol from general text editing UI
Example - https://files.catbox.moe/kxyepa.mp4
2025-09-09 15:42:31 +05:00
Andrej730 876c5ac2e6 typing 2025-09-09 15:42:31 +05:00
Andrej730 29a86c6748 Fix ruff UP041 2025-09-09 15:42:31 +05:00
Andrej730 a4a04e6941 black . 2025-09-09 15:42:30 +05:00
Ryan Schultz 9aafa32008 Provide a little tolerance when using Cntl+e. 2025-09-08 14:28:36 -05:00
Ryan Schultz 4f8e37d733 Added current property, in search, as a lot of times your search is relative to what it was before. 2025-09-07 11:03:21 -05:00
Dion Moult 311f279b61 Don't assume /tmp exists, and cd - back out to prevent cp errors during pyodide-download 2025-09-07 21:47:57 +10:00
Sayan Jyoti Das 3ad7c52cc4 build step for pyodide 2025-09-07 21:08:47 +10:00
Sayan Jyoti Das a5d9fe551a update webapp + bonsai integration 2025-09-07 21:08:47 +10:00
Sayan Jyoti Das 1672a7da32 add proper shutdown handling 2025-09-07 21:08:47 +10:00
Sayan Jyoti Das 10dcd9a923 add IfcTester webapp to Bonsai UI and websocket server 2025-09-07 21:08:47 +10:00
Sayan Jyoti Das be72887216 add build support for new IfcTester webapp 2025-09-07 21:08:47 +10:00
Massimo Fabbro 5400712a7a Black 2025-09-06 07:20:48 +02:00
Massimo Fabbro 1dea8ca37b See #6570.Keep ifc5d independent from Bonsai 2025-09-06 07:20:48 +02:00
Andrej730 f945a94fed Classifications UI - display placeholder name for unnamed classifications 2025-09-05 19:10:36 +05:00
Andrej730 14ae8680e3 Fix find_package libxml compilation for more recent versions
Noticed compiling against libxml2 2.13.8 package that it's trying to use dynamic libs by default if `LIBXML_STATIC` is not defined. Adding `LIBXML2_DEFINITIONS` helps.
2025-09-05 19:10:36 +05:00
Andrej730 9ec0732a84 Add simple test for loading ifcsqlite to Bonsai 2025-09-05 19:10:36 +05:00
Andrej730 7b490bbc69 Bonsai - support loading element types from ifcsqlite 2025-09-05 19:10:36 +05:00
Andrej730 0cf3bb3da9 ifc2sql - support saving element types geometry 2025-09-05 19:10:36 +05:00
Andrej730 062bf8e60b typing 2025-09-05 19:10:36 +05:00
Andrej730 f457a7d831 import_ifc - remove mesh_shapes
Was introduced in c3a36b7 and unused now.
2025-09-05 19:10:35 +05:00
Andrej730 1861baaaa9 import_ifc - remove type_products
It was introduced in 85e55b6 to keep track of type relationships, but seems to be deprecated awhile ago.
2025-09-05 19:10:35 +05:00
Andrej730 39253c6a6d create_element_types - remove unnecessary check
Was introduced in 0ee9329, but no longer needed since `None` values are excluded from this set after 10f8453
2025-09-05 19:10:35 +05:00
Andrej730 21137de8a0 Fix error reapplying selection during assign_class #7082
It appeared in case if user had IfcTypeProduct collection disabled.
2025-09-05 18:27:24 +05:00
Andrej730 a53017d9dc Fix error editing IfcClassification without provided ReferenceTokens after e3ea12a #7091
Actually after 2ec2ac0 there's no need for json serialization as we support working with string subitems natively.

For some reason previously it was using get_georeference_props to add attributes, I guess it a typo that happened awhile ago.
2025-09-05 17:44:07 +05:00
Thomas Krijnen 70286f2bcb Minor 2025-09-04 16:49:18 +02:00
Thomas Krijnen 26467a1d0e Check for valid stream before streaming 2025-09-04 16:49:00 +02:00
Thomas Krijnen 09f9b23153 Harmonize and complete serialization of aggregates of aggregates 2025-09-04 16:48:41 +02:00
Thomas Krijnen 6ac95e1ed3 Access to underlying storage model in python 2025-09-04 16:47:56 +02:00
Massimo Fabbro 25c0ed6759 Black 2025-09-04 16:33:03 +02:00
Massimo Fabbro f75d629990 See #6570. Now it is possible to define the rate in import csv
In order to assign the rate in the csv import, use the columns 'Rate cost schedule' and 'RateID'
2025-09-04 16:33:03 +02:00
Andrej730 b492110652 Temporarily for ifcsqlite disable calculating model offset and loading element types #7085
To keep models loadable
2025-09-04 19:09:20 +05:00
Andrej730 942cb586b2 Bonsai - fix loading ifcsqlite file after 497542d #7085 2025-09-04 19:09:20 +05:00
Andrej730 49b9f99557 ifcopenshell.sqlite - add mvd_str 2025-09-04 19:09:19 +05:00
Andrej730 15b69bfa98 sql, stream - define wrapped_data to provide more clear errors 2025-09-04 19:09:19 +05:00
Andrej730 5f964bd33c stream - remove trailing spaces 2025-09-04 19:09:19 +05:00
Andrej730 274a5cbfad sql, stream - provide schema_identifier to avoid errors 2025-09-04 19:09:19 +05:00
Andrej730 b6fa1759ef sqlite_entity - define file 2025-09-04 19:09:19 +05:00
Andrej730 f016d72787 cmake - support find_package(CONFIG) for libxml2 dependency 2025-09-04 19:09:19 +05:00
Andrej730 8c12bd0322 Reuse builder.create_axis2_placement_3d 2025-09-04 19:09:18 +05:00
Andrej730 90e6838ddb typing 2025-09-04 19:09:18 +05:00
falken10vdl 5304072892 dms2dd and dd2dms - fix doc-strings, refactor, add tests (#6763) 2025-09-04 11:55:13 +00:00
Thomas Krijnen 59a5bf2344 RocksDB zstd encryption; cache tuning; readonly open mode 2025-09-03 11:11:55 +02:00
Andrej730 d4918edcd9 Fix broken literals reorder #6718 2025-09-02 18:28:00 +05:00
Andrej730 d901506029 Reordering and removing text literals - update viewport
So user can see the change right away.
2025-09-02 18:28:00 +05:00
Andrej730 aaf980b6b3 ifcwrap cmake - override _d interface suffix in debug builds (d004410cc)
https://discourse.cmake.org/t/a-correct-way-to-add-d-debug-prefix-for-debug-python-extensions-on-windows/15132
2025-09-02 18:27:59 +05:00
Andrej730 d419e50ece active_bsdd_property - make implied type more explicit 2025-09-02 18:27:59 +05:00
Andrej730 d5ff48fbc9 Fix "Copy Attribute Name" sometimes missing from attributes context menu
Due to a possibly unbound `url` variable this button sometimes went missing https://files.catbox.moe/2r8adp.png
2025-09-02 18:27:59 +05:00
Andrej730 99ca1c7eb4 Add description for pset enum properties too
Example - https://files.catbox.moe/ysmw6v.png
2025-09-02 18:27:59 +05:00
Andrej730 df4f565176 Fix missing IFC descriptions for already added pset props
Example - https://files.catbox.moe/dg1mzk.png
2025-09-02 18:27:58 +05:00
Andrej730 ed37ac3066 resolve_data_path_to_data_attr - fix typo in doc-string 2025-09-02 18:27:58 +05:00
Andrej730 1433240ae6 Fix text edit popup UI going out of sync with general text editing UI (a98cddf) 2025-09-02 18:27:58 +05:00
Andrej730 d9fe751163 Remove update_text_value and fix tests after refactor 2025-09-02 18:27:58 +05:00
Andrej730 555621ceae Avoid storing transient ui values in BIMTextProperties #4699
To avoid crashes and either way we stored the same data twice - once bim text props (and they were updated on each data refresh) and then again in data.py. Now it's going to use just data.py
2025-09-02 18:27:57 +05:00
Andrej730 d7ddbd2b99 typing 2025-09-02 18:27:57 +05:00
Richard Brice eba3ced5fe Fixes angle unit conversion when creating horizontal alignment from PI 2025-09-01 15:32:11 -07:00
Andrej730 d36205ea8b svgfill - bump 2025-09-01 21:08:46 +05:00
Thomas Krijnen a831884ee6 Free rocksdb iterators 2025-09-01 14:32:13 +02:00
Thomas Krijnen 01b64674ab Init max_id_ 2025-09-01 13:25:48 +02:00
Thomas Krijnen 78958567cf Insert consecutive numbering test into random test 2025-09-01 13:25:37 +02:00
Thomas Krijnen e6ea58cd72 Implement get_inverse_indices on rocksdb 2025-08-31 21:27:21 +02:00
Thomas Krijnen 6c607241a2 Clear merge output 2025-08-31 21:26:54 +02:00
Thomas Krijnen 18ad13cb8b Merge remote-tracking branch 'origin/v0.8.0' into tfk-rocksdb-storage 2025-08-31 16:06:07 +02:00
Thomas Krijnen 55e54f0b37 Re-add token offset to failing declaration lookup in order to be picked up by validate.py 2025-08-31 16:01:28 +02:00
Thomas Krijnen 453949ee01 Correctly wire up get_info2 2025-08-31 15:53:01 +02:00
Thomas Krijnen e4d08ce6b7 Don't raise exception in file constructor 2025-08-31 15:52:46 +02:00
Thomas Krijnen ce02e7a2a0 HeaderEntity does not exist anymore 2025-08-31 15:51:58 +02:00
Thomas Krijnen f43ddf2cd5 Defer execution of error details 2025-08-31 15:51:34 +02:00
Thomas Krijnen 9d0eb4f994 Merge pull request #7058 from Krande/feat/IfcFixedReferenceSweptAreaSolid
feat: improved support for IfcFixedReferenceSweptAreaSolid
2025-08-31 10:57:49 +02:00
smr 67fb569669 style: fix formatting with black 2025-08-30 20:04:58 +02:00
smr da9be7cff0 Fix PythonOCC >=7.8.0 compatibility in serialize_shape function
Resolves issue #6099: PythonOCC >=7.8.0 changed WriteToString() method
signature, causing TypeError in ifcopenshell.geom.serialise().

This fix uses signature inspection to detect the method signature:
- For PythonOCC < 7.8.0: Use WriteToString() (no parameters)
- For PythonOCC >= 7.8.0: Fall back to Write() method
- Graceful handling of signature inspection failures

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-30 20:04:58 +02:00
Richard Brice a839183ac2 Fixes referent sorting 2025-08-29 14:37:17 -07:00
Richard Brice 34bf374047 Corrects nesting of referents 2025-08-29 12:48:16 -07:00
Andrej730 43c35eaf24 ifcfm - fix error running without pandas 2025-08-29 23:50:27 +05:00
Andrej730 d91362a6f7 run-cmake - use swig install dir 2025-08-29 21:13:31 +05:00
Andrej730 76e3b8dd55 Bonsai - fix error appending curve/fill area styles
It would try to append them as Blender material and would fail, just import them as ifc elements.

Noticed testing #7066
2025-08-29 19:44:04 +05:00
Andrej730 d004410ccb ifcwrap cmake - add _d debug postfix required on Windows 2025-08-29 19:44:03 +05:00
Andrej730 abbc5c2159 run-cmake.bat - use opencollada install dir
instead of providing include/library dirs explicitly
2025-08-29 19:44:03 +05:00
Andrej730 ae771cb37d build-deps.cmd - bump swig version to 4.1.0 and use cmake
4.1.0 will match build-all.py and it's the first version to use cmake, so we can quickly build swig ourselves
2025-08-29 19:44:03 +05:00
Andrej730 b1a0b7a7d0 cmake - also try to use find_package(OpenCOLLADA) 2025-08-29 19:44:03 +05:00
Andrej730 556eb128d6 build-deps.cmd - add example use 2025-08-29 19:44:03 +05:00
Thomas Krijnen dfaa8d510c authorisation -> authorization in header schema for compatibility 2025-08-29 16:08:42 +02:00
Thomas Krijnen 93c2a4fe66 That's what you get for not using a visitor 2025-08-29 14:15:58 +02:00
Thomas Krijnen df726a2d61 Initialization in various other constructor forms 2025-08-29 14:13:21 +02:00
Thomas Krijnen 2cf5011813 Missing f-string f 2025-08-29 14:12:39 +02:00
Thomas Krijnen 9330e73a70 Call process_deletion_inverse() 2025-08-29 13:48:00 +02:00
Thomas Krijnen a73c60a467 Initialize guid map in case of empty file creation 2025-08-29 13:47:48 +02:00
Thomas Krijnen f29b0d776a Resiance in unpacking 2025-08-29 11:33:47 +02:00
Thomas Krijnen e6a7c5334b Resiance in unpacking 2025-08-29 11:10:08 +02:00
Thomas Krijnen 54b448cdb4 mkdir just in case 2025-08-29 10:10:28 +02:00
Thomas Krijnen 6bbff22a45 Update yml paths 2025-08-29 10:02:15 +02:00
Thomas Krijnen 51ae3f4c5e Update CI paths 2025-08-29 09:26:23 +02:00
krande df1b748b39 minor update 2025-08-28 20:05:45 +02:00
Thomas Krijnen 01ea1f627d Fix MacOS toolset to 10.15 due to std::filesystem 2025-08-28 17:06:12 +02:00
Andrej730 0d3545c621 bim.select_library_file - shortcut to reload the library
Location - https://files.catbox.moe/an9hif.png
2025-08-28 19:11:52 +05:00
Andrej730 12cfa21d9b Fix missing project library ui data refresh
E.g. it wasn't updated on undo
2025-08-28 19:11:52 +05:00
Andrej730 c8a60cc4d5 bim.refresh_library - add description 2025-08-28 19:11:51 +05:00
Andrej730 6702e912e7 bim.save_library - add info message for more responsive ui 2025-08-28 19:11:51 +05:00
Andrej730 b5aeab6404 Remove project library from UI #7057
Example - https://files.catbox.moe/940mhn.mp4
2025-08-28 19:11:51 +05:00
krande 7eea995b88 Remove load_ifc_occ_shape and related OpenCASCADE-specific code from test_sweeps.py. Simplify tests by focusing on mesh-based geometry validation. Clean up imports and unused assertions. 2025-08-28 15:41:20 +02:00
Thomas Krijnen d9265765c5 Show hdf5 build errors 2025-08-28 15:40:38 +02:00
Thomas Krijnen d2a560d144 Try with HDF5 1.13.0 2025-08-28 15:40:21 +02:00
Thomas Krijnen 974e62290c Try without installing cmake 2025-08-28 15:34:01 +02:00
Thomas Krijnen 1a1583405c USE_RTTI=On 2025-08-28 15:28:28 +02:00
Thomas Krijnen ef10c23842 -lstdc++fs on gcc < 9 2025-08-28 15:23:19 +02:00
krande 77acfd7069 Refactor tests: update input path resolution, optimize imports, and enhance load_ifc_occ_shape.
Simplify path definitions in `test_write.py` and `test_open.py`. Replace `typing` with `collections.abc` for `Sequence` usage in `test_sweeps.py` and adjust type hints to use Python's generic collections. Add optional verbosity to `load_ifc_occ_shape` and refine geometry test assertions. Update `simple_sweep_2.ifc` fixtures for consistency with test expectations.
2025-08-28 13:16:07 +02:00
krande 79546807d9 fix lint 2025-08-28 13:15:47 +02:00
krande e14974a1b5 Add linting feature and update test configurations in pixi.toml
Introduces a new `lint` feature with `ruff` and `black` dependencies. Extends test setup with additional dependencies and tasks for building, testing, and installation. Cleans up `.gitignore` and removes unused entries from `pixi.lock`.
2025-08-28 13:15:33 +02:00
Thomas Krijnen 4b5aa1221c Run black 2025-08-28 11:35:42 +02:00
Thomas Krijnen b448bea279 build-all correct install path 2025-08-28 11:28:23 +02:00
Thomas Krijnen a219d335ea to_string() default to True 2025-08-28 11:15:53 +02:00
Thomas Krijnen 47f7afb33b Help SWIG understand header entities 2025-08-28 11:15:36 +02:00
Thomas Krijnen 3245d0af5c Serialization of header entities with #0= 2025-08-28 11:15:18 +02:00
Thomas Krijnen b6712602e2 Retain exact attribute counts in rdb as parsed 2025-08-28 11:15:05 +02:00
Thomas Krijnen 2c6956ec02 Finish (de)deserialization 2025-08-28 11:14:11 +02:00
Thomas Krijnen 322fbe27d6 Python 3.10 compatibility 2025-08-28 11:13:42 +02:00
Thomas Krijnen a65fa1e606 Fix failing inverse test 2025-08-28 09:37:09 +02:00
Andrej730 71a6bf25bc Fix error loading IFC file without contexts #7060 (8d3aa98) 2025-08-28 11:09:46 +05:00
Andrej730 43fbdf57c8 black . 2025-08-28 11:09:45 +05:00
Richard Brice 39100b7c97 Fixes problems with referents 2025-08-27 11:32:25 -07:00
krande 1cd32be2fc Refactor test_sweeps.py: remove _is_swept_shape, restructure test directories, update test fixtures, and adjust assertions for geometry validation. Extend sweep_along_curve constructor to support fixed reference direction. 2025-08-27 19:37:47 +02:00
Richard Brice c090073858 Removes assumption about which nest contains alignment layout segments 2025-08-27 07:35:49 -07:00
Thomas Krijnen c97a1faecd Initialize file schema to nullptr, wire up guid map 2025-08-27 15:14:20 +02:00
krande 9dd7b488d6 Refactor and extend swept shape tests; adjust comments and import structure
Improves formatting and readability in `test_sweeps.py`, adjusts imports and comments, and adds assertions for geometry validation in `simple_sweep_1.ifc` and `simple_sweep_2.ifc` tests. Updates code comments in `IfcFixedReferenceSweptAreaSolid`.
2025-08-27 13:55:42 +02:00
Thomas Krijnen 4dca91c56e Compile rocks with -fPIC 2025-08-27 13:25:13 +02:00
Thomas Krijnen b92871818a Fix MacOS toolset to 10.13 due to rocksdb alignment requirements 2025-08-27 13:23:43 +02:00
krande d01bf9690d Add test and input for simple_sweep_2.ifc; extend constructor for sweep_along_curve to support fixed reference swept area solids
Includes `simple_sweep_2.ifc` test input, geometry validations in `test_sweeps.py`, and a new constructor for `sweep_along_curve` to handle directrix-based sweeps.
2025-08-27 12:11:02 +02:00
krande 604e0b0d94 Update .gitignore in test directory to include *.tmp files 2025-08-27 11:53:34 +02:00
krande 8420b98f3f Simplify IfcFixedReferenceSweptAreaSolid position check logic 2025-08-27 11:52:56 +02:00
Thomas Krijnen 46693baacf No walrus 2025-08-27 11:49:05 +02:00
Thomas Krijnen c665c9d7e5 Correction for previous commit 2025-08-27 11:33:01 +02:00
Thomas Krijnen b05c83e612 Qualify return type to keep older versions of swig happy 2025-08-27 11:05:59 +02:00
Thomas Krijnen a958f1373c Eliminate some warnings 2025-08-27 11:03:16 +02:00
Thomas Krijnen b2c20b15b4 Move definitions 2025-08-27 10:32:58 +02:00
Thomas Krijnen b9b12520f7 Compile rocksdb in ci.yml 2025-08-27 10:27:57 +02:00
Thomas Krijnen 11a048bf18 Rocksdb build fixes 2025-08-27 10:22:52 +02:00
Thomas Krijnen 5a06715843 Update examples 2025-08-27 10:21:45 +02:00
krande 6d9650e826 Update CMake presets: remove schema version 4 2025-08-26 21:24:54 +02:00
krande 2369f72798 Improve IfcFixedReferenceSweptAreaSolid handling and add swept shape tests
Enhances geometry processing for swept area solids by integrating matrix transformations. Includes new utility `_is_swept_shape` for topology analysis, extends testing with `load_ifc_occ_shape`, and updates schema versions in CMake presets.
2025-08-26 21:24:40 +02:00
krande 234cb76cd7 add 1 more test 2025-08-26 20:48:05 +02:00
Thomas Krijnen 0cd5c673c3 build-all.py rocksdb 2025-08-26 19:38:42 +02:00
Richard Brice 1de5940294 Separates referent and alignment layout usages into different referents 2025-08-26 08:02:57 -07:00
krande a0cc94a614 Add test for IfcFixedReferenceSweptAreaSolid with simple sweep example
Includes `simple_sweep_1.ifc` test input and geometry validation. Updates dependencies in `pixi.lock`.
2025-08-26 16:21:29 +02:00
krande 4835829700 refactor IfcFixedReferenceSweptAreaSolid logic and adjust install-debug task 2025-08-26 16:10:00 +02:00
Thomas Krijnen e5fe2df552 Template, typename, others to make GCC happy 2025-08-26 15:59:05 +02:00
Kristoffer Andersen 5719c3db2b Merge branch 'v0.8.0' into feat/IfcFixedReferenceSweptAreaSolid 2025-08-26 14:13:53 +02:00
Thomas Krijnen 9109fcec12 Further conditional compilation 2025-08-26 14:05:34 +02:00
Thomas Krijnen 4e71ae7d85 Enable rocksdb in ci.yml 2025-08-26 14:03:38 +02:00
Thomas Krijnen 96336d6f68 Ugly conditional compilation for without rdb support 2025-08-26 13:56:03 +02:00
krande 115d3d4498 start work on improving support for IfcFixedReferenceSweptAreaSolid 2025-08-26 13:32:44 +02:00
Thomas Krijnen 6095c523d7 Run black (unrelated) 2025-08-26 13:28:52 +02:00
Thomas Krijnen 71f1a7d0a4 Merge remote-tracking branch 'origin/v0.8.0' into tfk-rocksdb-storage 2025-08-26 13:28:21 +02:00
Thomas Krijnen a0c92638d2 RDB serializer: write type declarations in case of typed refs 2025-08-26 13:25:38 +02:00
Thomas Krijnen ff3fa48332 Add test case 2025-08-26 13:25:18 +02:00
Thomas Krijnen 8888e45115 Run black 2025-08-26 12:54:23 +02:00
Thomas Krijnen 92d4a89a43 Support propsetdefset in rocksdb streamer 2025-08-26 12:54:04 +02:00
Thomas Krijnen ea53c96134 Allow inspection of rocskdb keys in python 2025-08-26 12:53:35 +02:00
Thomas Krijnen 2f62064814 Python impl function 2025-08-26 12:53:06 +02:00
Thomas Krijnen 722e819e11 Support propsetdefset in python streaming mode 2025-08-26 10:20:36 +02:00
Thomas Krijnen 862aa71a77 Left-overs after merge 2025-08-26 10:20:08 +02:00
Thomas Krijnen e920379ca3 SFINAE for BaseClass* 2025-08-26 10:19:47 +02:00
Thomas Krijnen 4011666162 Fixes to header writing 2025-08-26 10:18:13 +02:00
Thomas Krijnen 9d9e9ed4cb Merge remote-tracking branch 'origin/v0.8.0' into tfk-rocksdb-storage 2025-08-26 10:17:57 +02:00
Richard Brice 9331e89d15 Alignments can now be created with or without geometric representations 2025-08-25 19:59:07 -07:00
Bruno Perdigão 8903d6a85c Change variable name for consistency. Related to #6963 2025-08-25 20:42:28 -03:00
Bruno Perdigão cb551e1248 Fix issue with creating walls from slabs in IFC2X3 files. Related to #6963 2025-08-25 20:42:28 -03:00
Bruno Perdigão 915c38947d See #6963. Fix issue with changing extrusion angle in IFC2X3 files. 2025-08-25 20:42:28 -03:00
Bruno Perdigão 190d9f8e3f Fix issue with IfcPolyline in get_polyline_coords 2025-08-25 20:42:28 -03:00
Thomas Krijnen d2c7c1532c Implement streaming scan through file and use in rocksdb serializer and python 2025-08-25 12:45:10 +02:00
daniel-augusto f7e8643f30 Update link to install Bonsai 2025-08-24 08:23:31 +02:00
falken10vdl dccd9d4139 lock drawing titleblock (managed by lock icon in Inkscape) (#7043) 2025-08-21 15:55:19 -05:00
Thomas Krijnen d31aafac5b Update ConversionSettings.h 2025-08-21 14:06:54 +02:00
Thomas Krijnen 2949a86f09 Properly initialize stream::eof #7045 2025-08-21 10:00:44 +02:00
Ryan Schultz 4cbf551c75 small tweak to dev_environment.py 2025-08-20 13:01:42 -05:00
Andrej730 3ef5b13bf8 cmake - also try find_package(OpenCASCADE) 2025-08-19 19:06:21 +05:00
Andrej730 f1114745fb cmake - fix OCC_INCLUDE_DIR strequal check working only once
If OCC_INCLUDE_DIR is not provided, then first it would pass, but the next time wouldn't since variable value would be 'OCC_INCLUDE_DIR-NOTFOUND'.
2025-08-19 19:06:21 +05:00
Andrej730 1d2b1dcbc8 build-deps - avoid redownloading Eigen 2025-08-19 19:06:21 +05:00
Andrej730 ea360733e4 run-cmake - use hdf5 install dir instead of providing include/library dir explicitly 2025-08-19 19:06:21 +05:00
Andrej730 1103cb6c03 build-deps - use the same hdf5 version as build-all
Also use general release cmake file, so there's no need for .patch
2025-08-19 19:06:20 +05:00
Andrej730 6bf39b3d6a cmake - also use find_package to find hdf5 2025-08-19 19:06:20 +05:00
Andrej730 b971135ce4 build-deps - fix trailing spaces 2025-08-19 19:06:20 +05:00
Robin Quint ef24bb52a7 Make Door / Window Tool place doors on the correct side of a wall (#6986) 2025-08-19 13:53:45 +00:00
daniel-augusto 6286d85850 Correct highlight code block python 2025-08-19 09:17:20 +02:00
Andrej730 3d82eb954f Fix missing project custom psets reload when changing IFC filepath #7037 2025-08-18 19:48:04 +05:00
Andrej730 2951aecc14 typing 2025-08-18 19:48:04 +05:00
Andrej730 c4d54f7709 switch_representation - clear geometry cache
Noticed wall representation wasn't updating after window was added to it, because of the existing cache.
2025-08-18 19:46:59 +05:00
Andrej730 bd8cdf5a82 cmake - also use find_package to find Eigen3 2025-08-18 19:46:59 +05:00
Andrej730 53e9837858 fix file_dict typing (126accd6a) 2025-08-18 19:46:59 +05:00
Dion Moult ddbe62772d Fix bug where copy to structure feature was completely inaccessible from the UI 2025-08-18 17:30:56 +10:00
Christoph Mellüh f9dc7d5d94 Improve docs (#7005) 2025-08-18 06:14:06 +00:00
Thomas Krijnen aa97cc25d1 Support faceset face with voids in shape_builder 2025-08-16 15:02:17 +02:00
Thomas Krijnen 0088f3933f Keep ruff happy 2025-08-16 14:07:11 +02:00
Thomas Krijnen 0054b27254 Support datetime instances in edit_pset 2025-08-16 13:35:21 +02:00
Thomas Krijnen 126accd6a2 Track ifcopenshell.file creation time for unique iden 2025-08-16 13:33:10 +02:00
Andrej730 bd0e16cee5 Add status assignment to Statuses UI
Example - https://files.catbox.moe/c6ydj7.mp4

Still need to add tests and support for userdefined statuses.
2025-08-15 19:51:01 +05:00
Andrej730 f5cb2dd21f black . 2025-08-15 19:51:00 +05:00
falken10vdl b024ba05da Fix UI bug with active representation indication for occurrences (#7009) 2025-08-15 13:36:15 +00:00
Richard Brice 1fcf2fb53f Fixed zero length segment for vertical alignment. Refactors curve segment transition code 2025-08-14 13:56:36 -07:00
Andrej730 6bc318b15c Option not to draw specific linked files #6947
Example - https://postimg.cc/7GTkhGPb
2025-08-14 19:54:17 +05:00
Andrej730 40a895b5ad docs\conf.py - skip .venv 2025-08-14 19:54:17 +05:00
Andrej730 3cd2963b01 cmake - fix errors on older cmake #7023 2025-08-14 12:13:48 +05:00
Andrej730 ff3c5b849e cmake - relax CGAL_INCLUDE_DIR check on Linux #7023 2025-08-13 19:45:36 +05:00
Andrej730 8294dacaa4 Move code style notes to docs from wiki
Currently it's in Bonsai docs as this next to previously added formatter docs. Probably, should move it to ifcopenshell docs later.

C++ code style part about braces seems to be outdated.
2025-08-13 19:45:35 +05:00
Andrej730 ca03d5d0c5 bonsai/docs/make - server target 2025-08-13 19:45:35 +05:00
Andrej730 74a3e8a4e6 cmake - remove cmake_policies superseded by cmake_minimum_required
Our minimum cmake version is 3.21, so policies below use `NEW` by default already:
- CMP0048 - VERSION option support for `project`, introduced in 3.0
- CMP0074 - find_package() uses <PackageName>_ROOT variables, introduced in 3.12
- CMP0078 - UseSWIG generates standard target names, introduced in 3.13
- CMP0086 - UseSWIG honors SWIG_MODULE_NAME via -module flag, introduced in 3.14
2025-08-13 19:45:35 +05:00
Andrej730 41142c73bf cmake ifcwrap - fix CMP0148 warning
The policy is removing FindPythonInterp and FindPythonLibs, but it was introduced in 3.27, so just skip it not to break minimum cmake ver.
2025-08-13 19:45:35 +05:00
Andrej730 6c0e2ce323 cmake - fix CMP0167 warning
CMP0167 is removing FindBoost module, but it's only introduced in 3.30, switching to OLD for now.
2025-08-13 19:45:35 +05:00
Andrej730 89c54291b0 Keep CMP0177 OLD (e54dce5dc) to avoid breaking min cmake version #7023 2025-08-13 19:45:35 +05:00
Andrej730 7311777a57 build-deps.cmd - skip installing Python if same version already present on the system #6276
due to existing standard Python installer's limitation
2025-08-13 18:30:56 +05:00
Andrej730 380434f9dd build-deps - error if python installer failed #6276 2025-08-13 18:09:12 +05:00
Andrej730 4d137171ec cmake - document PYTHON_MODULE_INSTALL_DIR 2025-08-13 18:09:12 +05:00
Andrej730 8d3b8b24f8 cmake - search for LibXml2 only with IFCXML_SUPPORT #2035 2025-08-13 14:22:46 +05:00
Andrej730 9e5b667380 black . 2025-08-13 14:22:46 +05:00
Chris Mayo 61fff3d2b4 Fix ifcwrap searching for headers in system directories #3883 (#5697) 2025-08-13 07:37:58 +00:00
Massimo Fabbro 94a3d58e49 See #6570. Now the rate cost item pop up shows also the cost schedule 2025-08-13 07:32:26 +02:00
Richard Brice d57777290b Elevated segment curve transition code to a public function 2025-08-12 16:37:39 -07:00
Andrej730 ffd1d52b4e Fix build-urls note (7c2ba4b)
Apparently backticks are hiding the string.
2025-08-12 20:02:02 +05:00
Andrej730 6a42ac7733 CgalSmoothAngleDegrees - fix compilation warnings
warning C4244: 'initializing': conversion from 'double' to 'const int', possible loss of data
2025-08-12 19:05:53 +05:00
Andrej730 29ba0f3c03 IfcConvert - prompt expected user response 2025-08-12 19:05:53 +05:00
Andrej730 64a9c1f473 cmake - WITH_CGAL to ensure include dir exist 2025-08-12 19:05:53 +05:00
Andrej730 3342bd923d cmake - detect missing HDF5_LIBRARIES on win/darwin
Previously it would assign .so files on Windows as libraries and you would detect error on linking stage.
2025-08-12 19:05:53 +05:00
Andrej730 95820516cf cmake - fix error building ifcconvert without opencascade
geometry_serializer target is defined only if WITH_OPENCASCADE=ON
2025-08-12 19:05:53 +05:00
Andrej730 e230270218 cmake - error when building IfcGeomServer with WITH_OPENCASCADE=OFF 2025-08-12 19:05:53 +05:00
Andrej730 3423e6b13d cmake - remove trailing spaces 2025-08-12 19:05:52 +05:00
Andrej730 34e699687d cmake - ensure EIGEN_DIR is provided 2025-08-12 19:05:52 +05:00
Andrej730 63f7315d90 run-cmake - provide SWIG_EXECUTABLE explicitly
It seems SWIG_DIR has no effect and used as output variable from `find_package(SWIG)`.
2025-08-12 19:05:52 +05:00
Andrej730 a955d2bdee ifcwrap cmake - add hint about missing SWIG_EXECUTABLE 2025-08-12 19:05:52 +05:00
Andrej730 a4045a37f1 typing 2025-08-12 19:05:52 +05:00
Andrej730 41128a397b black . 2025-08-12 19:05:52 +05:00
Osyotr 3dbc1fddcb Fix IfcGeom build without OpenCascade (#7007) 2025-08-12 13:12:07 +00:00
falken10vdl 8c5830ddab Fix adding void if object has no layer material usage after #7010 #7019 2025-08-12 16:42:48 +05:00
Dion Moult a6a27442fb Add test case for bugfix 55e97fd1 2025-08-12 19:00:28 +10:00
Dion Moult 55e97fd170 Fix bug where append_asset would pull in openings unnecessarily
If you try to append an asset which has a relationship such as
IfcRelAssociatesClassification to a whole bunch of opening elements, all
those openings will also (incorrectly) be pulled in.
2025-08-12 18:37:25 +10:00
Christoph Mellüh 3e5a2e5eb2 Fix UI bugs for settings predefined types / assign_type to prevent invalid ifc (#7011) 2025-08-12 06:11:55 +00:00
Andrej730 b5e977d7f3 bim.activate_model not to alter objects selection 2025-08-11 18:58:43 +05:00
Andrej730 4423e0bb10 pset.get_template use fallback schema for odd schemas #6672 2025-08-11 18:39:20 +05:00
Andrej730 e54dce5dcf ifcwrap cmake - set CMP0177 to new
To fix 1k warnings running in cmake 3.30+
The new policy is that cmake is normalizing destination paths in `install` and warns if normalization has any effect on them. In our case paths after normalization should be fine, so switching it to `NEW`.
2025-08-11 18:39:20 +05:00
Andrej730 39f4abe243 An option not to print linked ifc files #6947
Location - https://files.catbox.moe/9qinpy.png
This option is also a nice way of showing the user that this feature does exist.
2025-08-11 12:49:44 +05:00
Andrej730 f60abdd18f Drawings cache options - document that optional are global
Otherwise it might be confusing as this option is displayed through "Active Drawing" UI.
2025-08-11 12:49:44 +05:00
Andrej730 9f92e4853f assign_representation - assign repr only to occurrence for profile- or layer-based types #6934 2025-08-11 12:25:32 +05:00
Andrej730 f8f48796a9 test_assign_representation - cover ifc4x3 2025-08-11 12:25:32 +05:00
Andrej730 7c2ba4b18a make build-urls - add small note with platform names 2025-08-11 12:25:32 +05:00
Andrej730 ce6505847a black . 2025-08-11 11:23:18 +05:00
falken10vdl 8b1ffea91a Enhance AddElement operator to orient the extruded ifcopening along the AXIS orientation (#7010)
* Enhance AddElement operator to orient the extruded ifcopening along the AXIS orientation

* Adjust extrusion direction based on DirectionSense for AXIS2 & AXIS3 IfcOpeningElement
2025-08-10 14:21:42 -05:00
Richard Brice 762f4ff975 Implements business 2 geometry mapping for Viennese Bend for horizontal and cant layouts 2025-08-09 14:03:19 -07:00
Andrej730 9d2a79803a Fix typo in fe130eb #7008 2025-08-09 16:02:46 +05:00
falken10vdl 2597fcb463 Remove transform orientation settings in BoundingBoxDecorator (#6994)
* Remove transform orientation settings in BoundingBoxDecorator

* Remove unused transform orientation handling in update_measure_xyz and black formatting
2025-08-08 12:01:59 -05:00
Andrej730 36b86bbb54 Apply RUF022 (sorted __all__) 2025-08-08 19:12:11 +05:00
Andrej730 858e8743ba IfcStore cache - small refactor and doc-strings 2025-08-08 19:12:11 +05:00
Andrej730 3f09dff79e Option to always cache geometry
Settings location - https://files.catbox.moe/5cjtc1.png
2025-08-08 19:12:11 +05:00
Andrej730 fe130ebb5a typing 2025-08-08 19:12:10 +05:00
Andrej730 b8f4149603 HdfSerializer::read_surface_style - use isnan for clarity 2025-08-08 19:12:10 +05:00
Andrej730 f2f28f8ba6 Use DIR_PATH subtype for properties
It adds this option to open directory in system browser using alt+click and we don't need anymore a special operator `bim.select_dir` to fill these props.

Example - https://files.catbox.moe/t8ejrs.png
2025-08-08 16:45:58 +05:00
Andrej730 12c795a482 Fix binaries urls (3d30d809d)
Should use 0.8.4 now, not 0.8.3
2025-08-08 16:34:03 +05:00
Andrej730 c2730a81d6 bim.activate_model - avoid processing same type occurrences multiple times #5696 2025-08-08 16:15:24 +05:00
Andrej730 2855e96e53 HdfSerializer::read_surface_style - fill style.instance
E.g. Bonsai is relying on geometry.materials to identify what styles object has and in this case it would skip all styles without entities.
2025-08-07 21:02:35 +05:00
Andrej730 4b7dfcdae5 HdfSerializer::read - fix nullptr dereference reading surface styles
The problem was with the line `read_surface_style(surface_styles[i], surface_style_ptrs[i]);` since `surface_style_ptrs[i]` was a nullptr.

Changed the signature to `style&` to make it more clear that it's expecting already created style struct.
2025-08-07 21:02:35 +05:00
Andrej730 67d405ba76 HdfSerializer - fix missing edges_item_ids item in cache (dd9de98)
It wasn't written, but HdfSerializer was still requiring and throwing errors if it couldn' t find it, so cache wasn't working...

Honestly, me when I realized what happened - 🫣🫣
2025-08-07 21:02:35 +05:00
Andrej730 d671d6bed1 HdfSerializer - avoid crashes when passing CgalShape 2025-08-07 21:02:35 +05:00
Andrej730 6483fee792 typing 2025-08-07 21:02:35 +05:00
Andrej730 cee034b5b2 Fix stub after 3c7e938 2025-08-07 21:02:35 +05:00
Andrej730 0132edd774 Sync stub with the wrapper #6976 2025-08-07 21:02:34 +05:00
Andrej730 ed8a31c54b Update ignored settings structs in IfcPython.i #6976 2025-08-07 21:02:34 +05:00
Andrej730 3d30d809d1 Bump IfcOpenShell build #6909 2025-08-07 21:02:34 +05:00
Andrej730 5b0503e721 Geometry.get_cache 2025-08-07 21:02:34 +05:00
Thomas Krijnen 6924012dc8 - != + 2025-08-07 10:27:37 +02:00
Thomas Krijnen 007c451a77 Fix SurfCurveSweptArea solid #6984 2025-08-07 04:18:50 +02:00
Andrej730 358395c237 bim.copy_property_to_selection - fix missing bl_options 2025-08-06 18:18:32 +05:00
Andrej730 e7652a4846 bim.copy_property_to_selection - more friendly error for unsupported value types 2025-08-06 18:18:31 +05:00
Andrej730 630cb5f2dc bim.activate_model - show time it took #5696 2025-08-06 18:18:31 +05:00
Andrej730 117cb1ba5a Switch to pypa/gh-action-pypi-publish
Though there are no particular known issues with https://github.com/ortega2247/pypi-upload-action we've used before, but it wasn't updating for 5 years now, so it's better to switch to official PyPA workflow.

Args for workflow seem to be exactly the same, so it's just a drop-in replacement.
2025-08-06 18:18:31 +05:00
Andrej730 33f2f2e49e prop_with_search - set search_threshold to 0 for relating type properties
Otherwise it had no effect anywhere.
2025-08-06 18:18:31 +05:00
Andrej730 0f6cc23c28 prop_with_search.enable_relating_type_suggestions - keep default to False
To gradually introduce it when it's needed.
2025-08-06 18:18:30 +05:00
Andrej730 ce154cc8d2 prop_with_search - move new args to kw-only for readibility 2025-08-06 18:18:30 +05:00
Andrej730 d7d592de6f typing 2025-08-06 18:18:30 +05:00
falken10vdl 2f23f3cdd7 Add suggestions for relating types in enum property search (#6962) 2025-08-06 10:03:07 +00:00
Andrej730 6757026e3e Fix missing pset templates update when changing IFC filepath #6979
E.g. when user opened .blend file and ifc filepath was pointing to a wrong destination, after they changed the filepath pset templates wouldn't reload.
2025-08-06 14:48:39 +05:00
Andrej730 2154200697 black . 2025-08-06 14:48:39 +05:00
Thomas Krijnen 6ffcf363a6 Fix geom literals #6974 2025-08-06 10:49:45 +02:00
shmoody_y bf6e02f99d fix missing parantheses 2025-08-06 09:46:26 +02:00
shmoodyyy 15a31074e8 fix leaking as_compound() calls 2025-08-06 09:46:26 +02:00
Thomas Krijnen c9eb345491 standalone_drawer.py: no openings though 2025-08-06 09:29:04 +02:00
Thomas Krijnen 7e2b9dc7f3 Warn about failure to create camera from IfcAnnotation/DRAWING in Svgserializer 2025-08-06 09:22:47 +02:00
Thomas Krijnen 7a2dc5c0c5 Prevent unnecessary trsf::form() = other #6909 #6841 2025-08-06 09:21:57 +02:00
Thomas Krijnen 51afe03b78 shared_ptr references in compile-time loop to prevent unnecessary ref-bumps 2025-08-06 09:19:38 +02:00
Thomas Krijnen be8e96d918 standalone_drawer.py: dont require drawing elements to be speified on cli 2025-08-06 09:18:10 +02:00
Thomas Krijnen 071353eddc Vertex normal smoothing in CGAL --cgal-smooth-angle-degrees #6997 2025-08-06 05:46:07 +02:00
Andrej730 d1bcd887ca Zones UI - show currently edited zone 2025-08-05 13:57:40 +05:00
Andrej730 a05bae78ff search.operators - add missing bl_options
If operator is changing blend data, then it should always provide undo option, otherwise it may lead to crashes.
2025-08-05 13:57:40 +05:00
Andrej730 31e9b125e3 Selection filters - refactor code
As most of the code can be just reused
2025-08-05 13:57:39 +05:00
Andrej730 d0d913a97b Remove dead code in search.prop 2025-08-05 13:57:39 +05:00
Andrej730 50ff363501 Remove UIList.use_filter_linked
It seems it's either was never used or it was used in some very old Blender version.
2025-08-05 13:57:39 +05:00
Andrej730 1c06d12efc Support 2f1de2f when adding bsdd properties
Previously you would still need to open bsdd ui and preload dictionaries.
2025-08-05 13:57:39 +05:00
Andrej730 eb7550b63e bim.add_bsdd_properties - add poll check 2025-08-05 13:57:39 +05:00
Andrej730 9d83eec674 typing 2025-08-05 13:57:38 +05:00
Andrej730 4cf4628e63 remove unused code 2025-08-05 13:57:38 +05:00
Andrej730 a498e75712 bim.add_element - add poll check #6985 2025-08-05 13:54:32 +05:00
Massimo Fabbro 8a4739f9c9 Running black 2025-08-05 08:56:06 +02:00
Massimo Fabbro c6093430c2 See #6570. Now rate cost item works also with categories 2025-08-05 08:56:06 +02:00
Christoph Mellüh 57658eb5df Fix Bonsai classification tests after bonsai bsdd changes (#6988) 2025-08-05 06:01:48 +00:00
Andrej730 f25ad2a9cb bsdd ui - preload properties when loading classes
It was confusing that you still needed to click on the first property, even though it was selected by defalt.
2025-08-04 21:18:15 +05:00
Andrej730 3b8b4c1566 typing 2025-08-04 21:18:15 +05:00
Christoph Mellüh d2939067bd Add Description-ContextMenu Entry to bSDD Properties (#6970)
See #6970 for example.
2025-08-04 13:52:00 +00:00
Andrej730 37c05f763e Fix IFC undo data loss in 645298e #6973
There was a contradiction - modal operators were treated as special and were always creating new transactions (`is_top_level_operator = method == "MODAL"`), but those transactions were only closed if modal returned `FINISHED` or `CANCELLED`, so in most case previous transactions were just overridden, so IFC undo data was lost.

Ping @Moult just in case
2025-08-04 18:47:08 +05:00
carlopav e00a865bce Various fixes to IfcCostSchedule PDF export (#6983)
* IfcCostSchedue PDF export: changed Output type from off to auto

* Fixed currency value

* Fix summary total if no nested structure present
2025-08-04 08:46:20 +00:00
Dion Moult 4d42512b6a Add support for integer data types in bsdd 2025-08-04 17:02:32 +10:00
Thomas Krijnen 037fd22b51 util/unit.py::calculate_unit_scale() Check for valid unit_type 2025-08-04 08:53:08 +02:00
Thomas Krijnen 1ad2c62a22 add_qto.py: MethodOfMeasurement=BaseQuantities to comply with spec text 2025-08-04 08:52:02 +02:00
Dion Moult 823eb7d199 SetFalseOrigin recipe now by default resets non-geometric spatial elements (XY values only). 2025-08-02 18:11:33 +10:00
Dion Moult 7038cbe871 ResetSpatialElementLocations patch now supports only_xy toggle.
Also rewrote the patch to use API and util functions to make it more
robust.
2025-08-02 17:54:55 +10:00
Andrej730 1cb44da76c Refactor toggling target view to a single operator 2025-08-01 20:07:59 +05:00
Andrej730 291b313d79 prop.Drawing - add some notes 2025-08-01 20:07:59 +05:00
Andrej730 cf13c6fdc1 Fix old bug with collapsing/expanding drawing list #6969
It was checking `is_expanded` for all drawings items, though it should have checked just target view items.
2025-08-01 20:07:59 +05:00
Andrej730 5bd9a58936 Zones UI - fix missing name update 2025-07-31 19:47:34 +05:00
Andrej730 ff75875045 Zones UI - add classification UI #6941 2025-07-31 19:47:33 +05:00
Andrej730 4ff0fd56e9 ClassificationsData - simplify 2025-07-31 19:47:33 +05:00
Andrej730 9cc5338602 Rename ClassificationReferencesData -> ObjectClassificationsData
To make it more clear what element's classification data it's storing.
2025-07-31 19:47:33 +05:00
Andrej730 37a62e3004 Zones UI - add psets ui #6941 2025-07-31 19:47:33 +05:00
Andrej730 9cc1347dd8 Reuse props.active_group 2025-07-31 19:47:32 +05:00
Andrej730 716919d052 typing 2025-07-31 19:47:32 +05:00
Andrej730 c82a7b708c build-all - verbose logs to print timestamps
So it will be easier to track build times from logs
2025-07-31 19:12:50 +05:00
Andrej730 5acacaa9d8 build-all - fix verbose logging
verbose logging was setting log level only for `logger`, never setting for the `logger`'s handler, so `-v` option, it seems, never worked. For simplicity now handler will just inherit log level from the `logger`.
2025-07-31 19:12:50 +05:00
Andrej730 e386c82ada build-all - add notes 2025-07-31 19:12:50 +05:00
falken10vdl 18b2364d52 Groups UI - fix crash accessing invalid collection items references #6811 (#6965) 2025-07-31 19:06:49 +05:00
falken10vdl 7cd423d423 S_Z for wall tool to change_extrusion_depth (#6935) 2025-07-29 12:59:15 -05:00
Andrej730 edd2dcc6c6 Fix bim.change_log_level console error on reregister 2025-07-29 21:26:46 +05:00
Andrej730 486e622f77 Limit active type prop width #6943
Example - https://files.catbox.moe/m49wt1.png
2025-07-29 21:26:46 +05:00
Andrej730 5ad566f42d Bonsai Mac app - allow to be called without arguments 2025-07-29 20:18:30 +05:00
Andrej730 aec286d85b Bonsai Mac app to quickly open .ifc files in Bonsai directly from Finder.
Demo for setting it up https://files.catbox.moe/1pyqps.mp4
2025-07-29 20:18:30 +05:00
Andrej730 38b594d159 dev_environment.py - fix REPO_PATH autodetection after 4a2411c05 2025-07-28 19:28:00 +05:00
Andrej730 5166416c61 build-all - add a couple of notes 2025-07-28 19:27:59 +05:00
Andrej730 c700a32b09 Fix RUF015 2025-07-28 19:27:59 +05:00
Andrej730 0cb6d9de72 typing 2025-07-28 19:27:59 +05:00
Andrej730 cdeeab4b31 black . 2025-07-28 17:03:25 +05:00
Andrej730 23944d6060 Fix small typo in 99d7f5ad7 2025-07-28 16:47:08 +05:00
Thomas Krijnen e13ba7627a Rocky8 python3.6 build-all compatibility 2025-07-28 13:27:08 +02:00
Thomas Krijnen 9e6c0758d5 Rocky8 python3.6 build-all compatibility 2025-07-28 13:23:10 +02:00
Thomas Krijnen 6932d2a268 Rocky8 python3.6 build-all compatibility 2025-07-28 13:21:43 +02:00
Thomas Krijnen 638e1ebcec Rocky8 python3.6 build-all compatibility 2025-07-28 13:17:38 +02:00
Dion Moult 106b02fad1 Allow URI browsing for IfcPatch recipes with directory names 2025-07-28 16:44:44 +10:00
Dion Moult 54522aab6a Add AGS2IFC patch recipe by David 2025-07-28 16:44:32 +10:00
Thomas Krijnen eb5df2f8c3 Simple SPF submodule 2025-07-28 05:27:22 +02:00
Richard Brice c8dbb72f69 Updated alignment stationing to account for stationing being defined on a parent alignment 2025-07-27 15:10:23 -07:00
Richard Brice e56f09071a Updates IfcOffsetCurveByDistance to be more permissive 2025-07-27 15:10:23 -07:00
Richard Brice a824141b90 Fixes IfcOffsetCurveByDistance 2025-07-27 15:10:23 -07:00
Richard Brice bb56882879 A few more fixes for zero length segments 2025-07-27 15:10:22 -07:00
Richard Brice ed0e825283 Alignment api bug fixes 2025-07-27 15:10:22 -07:00
Richard Brice c12ed46c49 Bug fixes with zero length segment and b2g mapping when project angle is not radian 2025-07-27 15:10:22 -07:00
Richard Brice f3c72920de Alignment patch recipes 2025-07-27 15:10:22 -07:00
Richard Brice 3ef7f1c141 Alignment API updates to support new patch recipes 2025-07-27 15:10:22 -07:00
Richard Brice 3e0ef46a37 Updates IfcHierarchyHelper::addRelatedObject to work with IfcRelNests 2025-07-27 15:10:22 -07:00
Bruno Perdigão 689d8d1644 Remove leftover line from 651d924759 2025-07-27 11:56:57 -03:00
Bruno Perdigão 9bf799e69e black . 2025-07-27 11:54:19 -03:00
Bruno Perdigão c27f89a109 Remove old comment 2025-07-27 11:47:43 -03:00
Bruno Perdigão 651d924759 Prevents using aggregate mode with IfcSpatialElement 2025-07-27 11:24:54 -03:00
Bruno Perdigão 17d6b8af61 Add Name to Linked Aggregates and keep product assignment after refreshing.
See #6831. Warning: this is a breaking change.
Linked Aggregate names are numbered to keep them consistent when reopening
the file instead of relying on Blender auto numbering objects with the
same name. However, for annotation purposes, the numbering is irrelevant,
and the user might want to use just the aggregate name. So it was added a
"Name" to the "BBIM_Linked_Aggregate" Pset that can be used in these cases.
When refreshing the linked aggregates, their names will be updated to reflect
the "Name" value and the product assignment will be preserved to keep
annotations in sync.
In order to adapt existing files to this new Pset structure see this gist:
https://gist.github.com/brunoperdigao/37a5b838935b15a91aa70b2bc4de325f
2025-07-27 11:24:54 -03:00
Dion Moult 4a2411c05d Document new Python based dev installation 2025-07-27 19:21:43 +10:00
Dion Moult 9f9abaadc8 Support Linux (tested and seems to work) 2025-07-27 19:21:43 +10:00
Dion Moult 99d7f5ad7a Clarify which Blender versions are supported 2025-07-27 19:21:43 +10:00
Osyotr bf7171b7ba Don't mark function that throws exception noexcept 2025-07-26 08:40:03 +02:00
Andrej730 1ac5a8d785 build-all - small refactor for readability 2025-07-25 18:22:18 +05:00
Andrej730 9004c5d153 Include build-all.py to black formatter 2025-07-25 18:22:18 +05:00
Andrej730 99cdc4da35 date.ifc2datetime - refactor for readability 2025-07-25 18:22:18 +05:00
Andrej730 3c338db364 bim.create_shape_from_step_id - include curves by default
Though it's still possible to disable it from Redo menu.
2025-07-25 18:22:18 +05:00
Andrej730 7322cc9018 bim.create_shape_from_step_id - use cursor as the location for the shapes 2025-07-25 18:22:18 +05:00
Andrej730 dcebd55031 bim.create_instance - simplify logic
Just use active object instead of the selected, move basic check to `poll`.
2025-07-25 18:22:17 +05:00
Andrej730 1d789da066 test_copy_work_schedule - cover ifc2x3 support 2025-07-25 18:22:17 +05:00
Andrej730 dd1c47f9dc sequence.add_date_time
API method to create IfcDateAndTime / IfcDatetime in schema agnostic way.
2025-07-25 18:22:17 +05:00
Andrej730 98e64c1830 sequence.duplicate_task - fix example using non-existent api 2025-07-25 18:22:16 +05:00
Andrej730 e8a4f7947d sequence.duplicate_task - fix misleading description 2025-07-25 18:22:16 +05:00
Andrej730 05a8824019 typing 2025-07-25 18:22:16 +05:00
Andrej730 cfd5d2a4eb Fix pagination issues when restarting type manager #6917 2025-07-25 16:57:40 +05:00
Andrej730 b79256ce32 mix_snap_and_axis - fix subtle bug with creating zero Vector 2025-07-25 16:57:40 +05:00
Andrej730 d8ae33dd2a Element types dropdown + search #6943
Example - https://files.catbox.moe/jv9uxt.png
2025-07-25 15:23:45 +05:00
Andrej730 b76b05fc71 sequence.copy_work_schedule #6901
Similar to e50215ddc but for IfcWorkSchedules

Button location - https://files.catbox.moe/jfd1ol.png
2025-07-24 19:39:14 +05:00
Andrej730 f5b28c0df8 util.get_work_schedule_tasks - fix critical bug with missing root tasks
Now we also use generator to mirror get_schedule_cost_items
2025-07-24 19:39:14 +05:00
Andrej730 a99bfd9294 sequence.get_root_tasks_ids - remove unused method 2025-07-24 19:39:14 +05:00
Andrej730 cbdd091d6f sequence.add_work_schedule - add missing object_type doc-string 2025-07-24 19:39:14 +05:00
Andrej730 82fcdfc160 export_duration_prop - remove dead assignment statements 2025-07-24 19:39:14 +05:00
Andrej730 cb724dbfde Work schedule UI - fix issue with some durations props not loading
E.g. IfcWorkSchedule.Duration wasn't recognized as such or IfcWorkSchedule.TotalFloat wasn't imported properly and was uneditable.

Now we also check IfcDuration type on attributes explicitly, instead of relying on hardcoded list
2025-07-24 19:39:14 +05:00
Andrej730 973b6be2aa Deduplicate ISODuration definition 2025-07-24 19:39:13 +05:00
Andrej730 7eba094a39 BIMWorkPlanProperties.editing_type - use enum 2025-07-24 19:39:13 +05:00
Andrej730 6bfa2aaf10 Work schedule UI - add missing button for disabling attributes editing 2025-07-24 19:39:13 +05:00
Andrej730 03e09a97c6 Work schedule UI - hide buttons labels to make it more tidy 2025-07-24 19:39:13 +05:00
Andrej730 6e9ec4861e bim.import_work_schedule_csv - make info message look nicer 2025-07-24 19:39:13 +05:00
Andrej730 d3bca858b0 Add import work schedule button to work schedule ui
Location - https://files.catbox.moe/sxfxv4.png
To mirror the similar UI we have in 4d, this way feature will much easier to find than checking File->Import
2025-07-24 19:39:13 +05:00
Andrej730 ba3e5ae28c Rename bim.import_csv -> bim.import_work_schedule_csv
To make name less generic
2025-07-24 19:39:12 +05:00
Andrej730 516f8cdb15 Fix broken sequence color schema UI in Blender 4.4+
We missed sequences being renamed to strips in Blender 4.4 and previous icon name broke, so UI wasn't able to load.
2025-07-24 19:39:12 +05:00
Andrej730 f3efb1601a copy_cost_schedule - add a test 2025-07-24 19:39:12 +05:00
Andrej730 f8a933e094 typing 2025-07-24 19:39:12 +05:00
sboddy 0a50a3cb24 Option to convert custom properties to ifc psets when assigning an IFC class (#6921)
Feature location - https://files.catbox.moe/cuvdan.png (assign class with alt+click modifier)
See #6921 for an example of converted props
2025-07-24 06:12:22 +00:00
Andrej730 e50215ddce cost.copy_cost_schedule #6901
A feature allowing duplicate existing IfcCostSchedule - either from API or from Bonsai UI
Button location in Bonsai - https://files.catbox.moe/ct058q.png
2025-07-23 18:57:40 +05:00
Andrej730 f24adcdadb control.assign_control - small optimization 2025-07-23 18:55:50 +05:00
Andrej730 84f6632c13 Reuse assign_control instead of creating IfcRelAssignsToControls 2025-07-23 18:55:50 +05:00
Andrej730 c82191f40b typing 2025-07-23 18:55:49 +05:00
Andrej730 3dde609519 enable/disable editing representation items to affect all selected objects
To simplify the process when you need to review representation items / their styles for multiple objects.
2025-07-23 18:55:49 +05:00
Andrej730 ed65c039dc Test for missing platforms
Needed to ensure all necessary platforms are covered when build is bumped
2025-07-22 18:07:55 +05:00
Andrej730 dd5d997d47 ifcopenshell-python workflows - include py313 2025-07-22 18:06:20 +05:00
Andrej730 d6a3900f3e ifcopenshell-python - support python 3.13 2025-07-22 18:06:20 +05:00
Andrej730 64d3951d5e installation.rst - add Python 3.13 urls 2025-07-22 18:06:20 +05:00
Andrej730 0ef255bc3c Fix linking project missing offsets for instances of complex geometry
After ba2456a if main IFC project had an offset and linked object had more than 333 faces, then it was imported at it's original location instead, missing an offset.

Also processing occurrences should be now more optimized, since we reuse the same verts buffer instead of recreating it 10 times.
2025-07-22 18:06:20 +05:00
Andrej730 8f5905c801 ifcopenshell_wrapper.pyi - document Element attributes 2025-07-22 18:06:19 +05:00
Andrej730 7ac7190d57 typing 2025-07-22 18:06:19 +05:00
Andrej730 06ad541c56 troubleshooting.rst - update Blender version 2025-07-22 18:06:19 +05:00
Andrej730 b4740b6949 append_asset to also match material sets by the name #6762 2025-07-21 18:10:11 +05:00
Andrej730 d66dd1be18 Button that allows changing linked ifc project filepath
Example - https://files.catbox.moe/usc5cu.png
2025-07-21 18:10:11 +05:00
Andrej730 adfe56c777 typing 2025-07-21 18:10:11 +05:00
carlopav dcf8329b04 Pdf ifc cost schedule export improvements (#6884)
* Export_IfcCostSchedule_to_PDF_improvements

* IfcCostSchedule CSV export: Added ItemIsASum column

New column in the ifc export that tracks if IfcCostItem is a sum, also added a new static method to the IfcDataGetter class.

* IfcCostSchedule CSV export: Added cost quantities column

Cost quantities are a serialsed list containing the name of the quantity and the quantity value.

* IfcCostScheduel PDF export: add options to fine tune export

New options include nested_structure_depth, should_print_cover, should_print_description, should_print_rates, should_print_summary, should_print_cost_ids.

Also pass project currency to typst (still not used).

Added footer with "proudly created with IfcOpenShell".

Updated Cover with formatting and IfcCostSchedule Description
2025-07-21 11:34:00 +05:00
Richard Brice d49a3486b9 Commented out debugging code for alignment 2025-07-18 14:47:14 -07:00
Richard Brice 78759a63f2 Updates helmert curve business2geometry mapping (again) 2025-07-18 12:29:28 -07:00
Richard Brice 913076de94 Updates helmert curve business2geometry mapping 2025-07-18 09:47:59 -07:00
Andrej730 e318cbd9e6 dev_environment.py - process broken symlinks 2025-07-18 20:17:04 +05:00
Andrej730 2f1de2f104 Autoload active bsdd from IFC file
Now we store in the IFC file list of active bsdd user was using in Bonsai.
So when you open IFC file it automatically marks dictionaries as active and there's no need to go to bsdd UI, unless there are new dictionaries to add/remove.

Example - https://files.catbox.moe/kzwa2n.mp4
2025-07-18 20:17:04 +05:00
Andrej730 0e74ac8eea dev_environment.py - support Mac 2025-07-18 20:17:04 +05:00
Andrej730 31ec4820fc dev_environment.py - readable errors in case bonsai path wasn't found
Since we added lookup for multiple paths, it was failing with confusing "Could not find Bonsai path in expected locations" even if the problem was with BLENDER_PATH.
2025-07-18 20:17:03 +05:00
Andrej730 917e7f9f15 dev_environment scripts - bump Blender version 2025-07-18 20:17:03 +05:00
Andrej730 2f0014a489 Mac compilation instructions - update Python version 2025-07-18 20:17:03 +05:00
Andrej730 92340f159d Mac compilation instructions - include eigen
Otherwise compilation doesn't work
2025-07-18 20:17:03 +05:00
Richard Brice a392a1fbfb Adds alignment as offset curve 2025-07-17 10:48:42 -07:00
Andrej730 728f9e2c04 util.shape - replace ShapeType with W.Triangulation for accuracy 2025-07-17 19:58:48 +05:00
Andrej730 2edfe1e5d8 profile.add_parameterized_profile - add profile_type arg
To create more valid profiles by default. Noticed then Bonsai creates new profiles, it doesn't set ProfileType, leading to validation errors.
2025-07-17 19:58:48 +05:00
Andrej730 0b48120a66 bim.create_all_shapes - allow selecting library to use 2025-07-17 19:58:48 +05:00
Andrej730 577d46eb70 typing 2025-07-17 19:58:47 +05:00
Andrej730 83a3813f53 debug operators - remove unnecessary undo step 2025-07-17 19:58:47 +05:00
Bruno Perdigão dd14f33c0b Allow "Refresh Linked Aggregate" to be called when uppermost aggregate is selected. 2025-07-16 17:52:48 -03:00
Bruno Perdigão b305e2354b Fix issue with DuplicateMoveLinkedAggregate object selection.
When dealing with multiple aggregates, the operator was not selecting
the right aggregate to move.
2025-07-16 17:52:48 -03:00
Andrej730 afb2742c2f standalone_drawer - print example args 2025-07-16 18:55:38 +05:00
Andrej730 55d533309e Change Python log level from UI
Location - https://files.catbox.moe/4umtyc.png

E.g. can be useful to narrow down some issues during ifc import
2025-07-16 18:55:37 +05:00
Andrej730 00f7871386 BIM_UL_topics - move to bcf module 2025-07-16 18:55:37 +05:00
Andrej730 f15a23483e typing 2025-07-16 18:55:37 +05:00
Andrej730 f14b4c467d Revert "Bump IOS" #6909
This reverts commit a4dd1c3463.
2025-07-16 16:36:16 +05:00
Dion Moult 4a9cf433d1 Fix bug in IfcTester thanks to Sayan where parsing XML text using ET would expand namespaces and therefore break namespaces during decode 2025-07-16 18:14:45 +10:00
Andrej730 866362c6ed More readable error creating a drawing with underlay but no active style #4870 2025-07-16 12:31:10 +05:00
Andrej730 0dc17a2141 Revert optional pyradiance 41e6478 #6633
Since issue is resolved upstream and there's no need to keep import optional.
2025-07-16 11:22:45 +05:00
Andrej730 d55e7faf2a Fix ifc4x3 breaking import of csvs that have enum values after c9847ca #6708 2025-07-15 18:01:57 +05:00
Andrej730 52762f828c Save all properties from Preferences UI as actual preferences
Previously some of them were saved only for current .blend file, moving them to preferences will make it more consistent with usual Blender UX. If needed we'll be able to add some way to fine-grain them later.

There's also a temporary patch that's going to migrate old .blend-props to new preferences-props to make process less disruptive.
2025-07-15 17:47:38 +05:00
Andrej730 1d0868eb18 bim.attribute_search_values - enable by default if possible
Since release just happened, it's more safe to try out propagating attribute search feature everywhere.
2025-07-15 17:47:37 +05:00
Andrej730 9461c6369e ci-bonsai-daily - use Blender 4.5 build 2025-07-15 17:47:37 +05:00
Andrej730 0f3b570800 Fix get_segment_length bug with non-parametrized profiles (f9c4b6a)
`settings` wasn't defined, so `create_shape` was always resulting in an error. Also, `create_shape` is returning `Triangulation` in this kind of cases, so there's no `.geometry`.

Also removed IfcCircleProfileDef if-check since it's covered by IfcParameterizedProfileDef.
2025-07-15 17:47:37 +05:00
Andrej730 30cbfad871 Fix code typo in 40f92d1 2025-07-15 17:47:37 +05:00
Andrej730 262739f37a owner.remove_role - fix error handling resource level rel (fe1e307)
It's probably was just an overlook in the original commit - it was referring to `settings["organisation"]`, though `"organization"` was never passed, leading to an error. And probably by accident remove_role tests were using the same tests as remove_organization, so the issue went under the radar for a while.
2025-07-15 17:47:37 +05:00
Andrej730 03fa850ce2 Fix old bug in FixArchiCADToRevitDoorSwings (1d74306)
It was using variable `f` that was never defined
2025-07-15 17:47:36 +05:00
Andrej730 8d2c0d0785 Fix old error setting up bcf camera in some cases (0d6cacd)
`cam_height` and `cam_width` were used in `setup_camera()` but never defined.
2025-07-15 17:47:36 +05:00
Andrej730 742a9df311 Fix error starting import_ifc profiling (in 515bfd1) 2025-07-15 17:47:36 +05:00
Andrej730 c95a0e8ed5 Fix error in generating error message in 8e9d4be
`profile` variable was never defined in this context
2025-07-15 17:47:36 +05:00
Andrej730 a28478c193 Fix bim.align_product operator (after 2db6b86)
It was using `core` in it's code though it was never defined.
2025-07-15 17:47:36 +05:00
Andrej730 b521901c90 Fix error message when filtering more than 50 selected objects (after c4ffc06)
name variable was undefined leading to an error
2025-07-15 17:47:35 +05:00
Andrej730 20f8737fb3 generate_furniture_library - remove unused methods
We have them in demo library either way
2025-07-15 17:47:35 +05:00
Andrej730 f18c93c9ee typing 2025-07-15 17:47:35 +05:00
Richard Brice a461281b1e Fixes problem moving alignment representation from parent to child alignment. Forgot to assign the ObjectPlacement 2025-07-14 11:09:02 -07:00
Andrej730 2d3d747d49 Move props from 'Other' preferences tab to preferences #6733
To prevent users confusion since it's a general Blender UX to expect here general preferences, not per-blend file settings.
2025-07-14 18:53:11 +05:00
Andrej730 d165cd2692 Update material classification UI on changing selected materials #6902 2025-07-14 18:53:11 +05:00
Andrej730 3f0e30245b Fix TestSelectSimilarContainer after 553003e 2025-07-14 18:53:11 +05:00
Andrej730 c111aafd3a Fix TestAddContext after 2698ba6 2025-07-14 18:53:11 +05:00
Andrej730 465bd23d6f import_attributes2 -> import_attributes
import_attributes were removed in 76f0b57ff
2025-07-14 18:53:10 +05:00
Andrej730 c7d3e00dca typing 2025-07-14 18:53:10 +05:00
Andrej730 72af88a4b3 black . 2025-07-14 18:53:10 +05:00
Richard Brice 73b76ba666 Adds IfcPolyline representation for alignment. Also some general cleanup 2025-07-13 16:34:52 -07:00
Dion Moult e93a66be49 Update VERSION 2025-07-13 20:25:14 +10:00
Dion Moult a4dd1c3463 Bump IOS 2025-07-13 19:55:21 +10:00
Andrej730 6d8e513f97 Temporary hack for path tags without 'd' attr #6871 #6876 2025-07-11 18:24:00 +05:00
Andrej730 baeaa073df dimensionality - add description 2025-07-11 18:24:00 +05:00
Andrej730 f07391181d context-ids, context-types, context-identifiers - add descriptions
Hope I don't miss anything, but couldn't find any references to ContextTypes, ContextIdentifiers and they seem to have no effect.
2025-07-11 18:23:59 +05:00
Andrej730 722f71b3b3 ifcgeom/ConversionSettings.h - fix duplicated ContextIds derived type
I guess it only affected how `defineOption` worked. Noticed the issue when was looking through `ifcconvert --help` and `context-ids` were duplicated 3 times.
2025-07-11 18:23:59 +05:00
Andrej730 76e4ec0069 bim.select_uri_attribute - simplify data_path eval 2025-07-11 18:23:59 +05:00
Andrej730 df18124bec vs-cfg.cmd - update error message
To make it a bit more easier to understand what to do in cases like below (the solution is to provide generator explicitly: `run-cmake.bat vs2022-x64 -DADD_COMMIT_SHA=ON -DVERSION_OVERRIDE=ON`).

```
run-cmake.bat -DADD_COMMIT_SHA=ON -DVERSION_OVERRIDE=ON

vs-cfg.cmd: The used CMake version does not support generator `-DADD_COMMIT_SHA` - cannot proceed.
```
2025-07-11 18:23:59 +05:00
Andrej730 370488cd27 docs conf.py - update year 2025-07-11 18:23:59 +05:00
Andrej730 4bbc463c8f ifcopenshell-python\docs\requirements.txt 2025-07-11 18:23:59 +05:00
Andrej730 4a11a117ad Fix bim.activate_model hiding all elements #6893
It was an overlook with using by accident bim.disable_status_filters instead of bim.enable_status_filters in bim.activate_status_filters, but it was also kind of unexpectedly introduced in 7858cb1.

But thinking about it, bim.activate_model shouldn't activate Statuses UI either way, since it might bring their filters they had before but explicitly disabled.
2025-07-11 18:23:58 +05:00
Andrej730 19be8107b3 Fix Ruff UP037 (quoted-annotation) 2025-07-11 18:23:58 +05:00
Andrej730 e1976d5bfd Fix Ruff UP013 (convert-typed-dict-functional-to-class)
Apparently `type` is okay and doesn't break things in even in Python 3.12
2025-07-11 18:23:58 +05:00
Andrej730 0fcc47508a Structural UI - refactor common code to tool, fix bugs
Also revert previous change in UI - `draw_attributes` doesn't cover it and there indeed should be special handling.
2025-07-10 19:42:31 +05:00
Andrej730 76f0b57ff1 Migrate to import_attributes2 2025-07-10 19:42:30 +05:00
Andrej730 1d8ee406af Fix alignment.__all__ missing create_segment_representations 2025-07-10 19:42:30 +05:00
Andrej730 05cb06a28e typing 2025-07-10 19:42:30 +05:00
Andrej730 8a6eb1b60f Update IfcApplication attributes export after 5866994 2025-07-10 19:42:30 +05:00
Andrej730 37d4ee97e7 alignment - fix missing imports 2025-07-10 19:42:29 +05:00
Andrej730 ef5d1448da Fix is_null not updating when adding new attribute subitems #6869 2025-07-10 19:42:29 +05:00
Massimo Fabbro eed42b8fac Fix #6711. Forgot to change the space elevation 2025-07-09 22:27:31 +02:00
Thomas Krijnen 1f0ac8fdb9 submodule 2025-07-09 20:45:39 +02:00
Andrej730 1b1a1f143a bim.attribute_search_values - enable it in more places
Since this feature can be generally useful, let's try it out to see the cases when it should be disabled.

Additionally to Materials UI, it's now enabled in object attributes, materials, profiles, styles and explorer ui.
2025-07-09 19:02:27 +05:00
Andrej730 9649c23a3b bim.attribute_search_values - more clear description 2025-07-09 19:02:27 +05:00
Andrej730 0ad5ace35f bim.attribute_search_values - support not just scene props 2025-07-09 19:02:27 +05:00
Andrej730 f7fdb8cc81 bim.attribute_search_values - rearrange props for readability 2025-07-09 19:02:27 +05:00
Andrej730 41e64781d8 Skip pyradiance import if it fails #6633 2025-07-09 19:02:27 +05:00
Andrej730 6ea7ee84a6 Remove prop.GlobalId
It seems it was unused since 6f55cd5
2025-07-09 19:02:27 +05:00
Andrej730 e7b86ae5b0 bim.add_group - use dynamic description to clarify when it's adding subgroups
It was kind of confusing since the icon and everything else was the same.
2025-07-09 19:02:27 +05:00
Andrej730 f6035609c9 Groups UI - use natsort 2025-07-09 19:02:27 +05:00
Andrej730 76feeaccc9 typing 2025-07-09 19:02:26 +05:00
Andrej730 af02a6b3a6 Fix UP037 (quoted-annotation) 2025-07-09 19:02:26 +05:00
Andrej730 832e68cb6f Fix Ruff UP034 (extraneous-parentheses) 2025-07-09 19:02:26 +05:00
Andrej730 a8268e8323 Replace deprecated typing.Sequence (40f92d15c) 2025-07-09 19:02:26 +05:00
Andrej730 5a4ad69bf7 black . 2025-07-09 19:02:26 +05:00
Richard Brice 40f92d15c3 Alignment api update (#6817)
* Some basic COGO survey points functions

* Update alignment api

Includes defining alignment segment by segment, automatic geometry definitions, and automatric stationing and referents

* Fixes bonsai import alignment from csv

* Adds DMS angle conversion functions to COGO api

* Updated per @civilx64 review comments

* Fixes problem with segment representations

* Fixes problem with segment transition codes

* Allows for compound vertical and horizontal curves

* Implements callbacks for referent naming

* Renames angle_from_bearing to bearing2dd for consistency with ifcopenshell.util.geolocation.dms2dd. Removes angle_from_dms because it duplicates dms2dd

* Documents register_referent_name_callback

* Fixes all sorts of problems with Cant/SegRefCurve implementation

* refactor referent unit tests to use a fixture for test setup

* lint with black

---------

Co-authored-by: Scott Lecher <civilx64@gmail.com>
2025-07-08 10:09:14 -07:00
Andrej730 ad8d02bfed Groups UI - support renaming groups directly from UI
Example - https://files.catbox.moe/u4b918.mp4
2025-07-08 21:20:59 +05:00
Andrej730 5866994b84 Intergrate explorer UI to support editing some props like #6869
Example - https://files.catbox.moe/ujhlwv.mp4
2025-07-08 21:20:59 +05:00
Andrej730 2ec2ac0e5c Attributes UI to support attributes with string subitems
Example - https://files.catbox.moe/oew1ue.mp4
2025-07-08 21:20:58 +05:00
Andrej730 c7555652d7 Bulk Rename Pset Props - show how many props were affected 2025-07-08 21:20:58 +05:00
Andrej730 5a7ce6d68b bim.bulk_remove_psets - show how many psets were removed
Also removed exception handling to catch that bug sneaking in, if it ever returns.
2025-07-08 21:20:58 +05:00
Andrej730 ad8913a979 Move bulk properties to GlobalPsetProperties 2025-07-08 21:20:58 +05:00
Andrej730 188b6a03a8 Attribute.is_uri - move to Attribute.special_type 2025-07-08 21:20:57 +05:00
Andrej730 7f3860b025 util.attribute - add tests 2025-07-08 21:20:57 +05:00
Andrej730 d08756d1b4 typing 2025-07-08 21:20:57 +05:00
Andrej730 525ef2b77b Explorer UI - add is_loaded toggle 2025-07-07 19:11:39 +05:00
Andrej730 fca2bf7aa8 Search filters - add example to criteria descriptions
To give users some default value to get familiar with the tool.
Example - https://files.catbox.moe/d1zh5n.png
2025-07-07 19:11:39 +05:00
Andrej730 ff82262490 Reuse get_active_sheet_item 2025-07-07 19:11:38 +05:00
Andrej730 c82351476a SheetBuilder - move references to local scope
Previously it was set as sheet builder attribute, but was never used as such.
2025-07-07 19:11:38 +05:00
Andrej730 d4f32802aa Show warnings if some sheets related files are missing
Previously when you would load/open/create sheets and some files were missing you would get traceback errors.

Also removed warnings for missing sheets svgs since they can go missing if someone is opening ifc project and want to regenerate sheets. We'll be able to return them in the future, if needed, but they will need some refinement.
2025-07-07 19:11:38 +05:00
Andrej730 d7668c3e3f drawing.get_sheet_identification 2025-07-07 19:11:38 +05:00
Andrej730 1445f91289 Fix very old bug with IfcPersonAndOrganization enum not loading (6ce8a36) 2025-07-07 19:11:37 +05:00
Andrej730 44e27f706a Owner UI - further decouple data.py from Blender entities 2025-07-07 19:11:37 +05:00
Andrej730 416ebde333 Fix names lists are not updated immediately
Similar to addresses problem in #6869
2025-07-07 19:11:37 +05:00
Andrej730 40dcd393c6 Fix addresses not updating immediately in IfcPerson UI
Found by @sboddy in #6869

Caused by trying to remove Blender entities from owner/data.py
2025-07-07 19:11:37 +05:00
Andrej730 4fda916c2f Fix duplicated assignments 2025-07-07 19:11:37 +05:00
Andrej730 acb9953ce3 dev_environment.py - add comments and small changes 2025-07-07 19:11:36 +05:00
Andrej730 4154356288 bim.operator - document resetting screen behaviour 2025-07-07 19:11:36 +05:00
Andrej730 54488bddbb bim.attribute_search_values - use enumproperty for data_type 2025-07-07 19:11:36 +05:00
Andrej730 8f21866248 typing 2025-07-07 19:11:36 +05:00
Thomas Krijnen f3b63aae76 Use should_use_presentation_style_assignment 2025-07-06 18:39:21 +02:00
Thomas Krijnen 3f05bab4e5 Shape builder: allow translate() on tesselated face sets 2025-07-06 18:35:19 +02:00
Thomas Krijnen 8534333092 Update doc comment 2025-07-06 18:34:50 +02:00
Ryan Schultz 5f2b4c96a6 fixes #6874 2025-07-06 10:26:12 -05:00
Massimo Fabbro 00836ec983 Fix #6736. Better use of non-SI units in creating spaces and coverings 2025-07-05 13:59:04 +02:00
Andrej730 fb78f75541 Basic IFC Entities explorer UI
A generic UI to allow editing simple entities like #6869 without creating an entire edit attributes UI inside edit attributes UI.
Still work in progress and should be connected to attributes UI.

Example - https://www.imgchest.com/p/agyv9lpq978
2025-07-04 19:48:12 +05:00
Andrej730 5948282ed0 bim.add_address - display it in more readable way
Before - https://cdn.imgchest.com/files/4gdcxp5j9l4.png
After - https://cdn.imgchest.com/files/yrgcnzgj5n4.png
2025-07-04 19:34:12 +05:00
Andrej730 47b81a6f89 bim.save_search - prefer only SEARCH IfcGroups by default #6857
Previously it was asking for a name to use to save search and users might type anything they find convenient at the moment, but it was possible that this name was used already by something important (for example drawing's IfcGroup) and would change it's description and assign objects there unexpectedly.

Now it will target IfcGroups with SEARCH ObjectType by default and only if user confirms, it will target all IfcGroups available (to keep the search a powerful tool for advanced users that allows them to populate any IfcGroup they want with items).

There's also a temporary patch in place  - when you load/save search Bonsai will try to find old search IfcGroups with ObjectType = None and update their ObjectType, this needed to make sure transition works seamlessly for the simple cases.
2025-07-04 19:34:12 +05:00
Andrej730 8ae08cb90e bim.save_search - not to fail silently 2025-07-04 19:34:11 +05:00
Andrej730 7796856119 typing 2025-07-04 19:34:11 +05:00
falken10vdl f75045f0c5 See #6570. Now it is possible to remove the csv cost file link.
This is a followup to that issue. In this particular case, a remove csv link button is added next to the refresh csv link button.
2025-07-04 12:35:17 +02:00
Andrej730 e52af2baad Iterator.validate_iterator_state to avoid crashes using next() and get()
Just to avoid accidental crashes using .get() / .next() when using them from Python - in cases when iterator was initialized but there were no elements or if iterator got exhausted.
2025-07-03 18:49:41 +05:00
Andrej730 da4ae4c2f2 Fix typo in 2a199cf 2025-07-03 18:48:30 +05:00
Andrej730 28043a8e5d ifc2sql - skip creating geometry if iterator failed to initialize 2025-07-03 18:48:30 +05:00
Andrej730 0e8fb44301 Remove unused Iterator.task_result_index_ (c78b289) 2025-07-03 18:48:08 +05:00
Andrej730 b97dca5d47 typing 2025-07-03 18:48:08 +05:00
Andrej730 207db459a7 Iterator.h - remove redundant typename (eeaf04c) 2025-07-03 18:48:07 +05:00
Andrej730 026eebf39b pyproject.toml - remove enableTypeIgnoreComments
As Pylance now allows inserting pyright ignore comments without it 🎉

https://github.com/microsoft/pylance-release/issues/7220
2025-07-03 18:48:07 +05:00
carlopav 5f5c0b41d5 Basic infrastructure for IfcCostSchedule PDF export with typst (#6860) 2025-07-03 13:18:03 +00:00
falken10 3055dfa1a6 clean up from developer's feedback + black formatting 2025-07-03 05:51:59 +02:00
falken10 b59bdb585b Refactor cost documents following developrs advice 2025-07-03 05:51:59 +02:00
falken10 ccd97c66ae refactor and black formatting 2025-07-03 05:51:59 +02:00
falken10 e6747b258c Remove CostSchedulesMapping and added csv_filepaths to data.py 2025-07-03 05:51:59 +02:00
falken10 6aa6803490 Added relative CSV file paths 2025-07-03 05:51:59 +02:00
falken10 72fbe3a6d9 Refactor cost schedule CSV filepath to use document references 2025-07-03 05:51:59 +02:00
Andrej730 68a602573b ifcopenshell.geom.iterator - more descriptive error in __init__ #6865 2025-07-02 18:14:34 +05:00
Andrej730 1e06dfcb76 Fix console errors when project is not loaded 2025-07-02 18:14:34 +05:00
Andrej730 3a0a912022 Use property_unset instead of in and del 2025-07-02 18:14:34 +05:00
Andrej730 b16fb7d917 bim.pip_install - add dynamic description 2025-07-02 18:14:34 +05:00
Andrej730 94d2d32d18 typing 2025-07-02 18:14:34 +05:00
falken10vdl e743db27f4 Draw attributes with search (#6849)
See example in #4325
2025-07-02 11:11:29 +05:00
Thomas Krijnen bb329affb8 settings: DeferProcessingFirstElement, MaxOffset, MaxOffsetDeviation, ApplyOffset; taxonomy: centroid funcs; iterator get_tasks + items() funcs; geom.map_shape() 2025-07-01 21:10:24 +02:00
Bruno Perdigão 6c4e4e5f91 Partial solution for #6775.
The issue happens when a wall has a "ATPATH" connection and has a
negative direction sense. It mixes the profile points in an incorrect
order. This commit seems to fix it, but maybe there is a better solution.
2025-06-30 19:50:41 -03:00
falken10 a31aa6053e black formatting 2025-06-30 18:25:41 -03:00
falken10 b90f146a68 update gizmo based on selected items 2025-06-30 18:25:41 -03:00
falken10 f67dca8de0 Enhance label rendering in BoundingBoxDecorator to prevent text overlaps 2025-06-30 18:25:41 -03:00
falken10 a686d70908 Updated based on feedback from @brunoperdigao 2025-06-30 18:25:41 -03:00
falken10vdl 38fe7fea65 Update workspace.py cosmetic remove nl from previous edits 2025-06-30 18:25:41 -03:00
falken10 b26890f74b black formating 2025-06-30 18:25:41 -03:00
falken10 2c16247943 moved to viewport overlays 2025-06-30 18:25:41 -03:00
falken10 53fc7bce0c clenaup 2025-06-30 18:25:41 -03:00
falken10 f5db905223 Separate decorator from operator to follow other modules in model / project 2025-06-30 18:25:41 -03:00
falken10 3557b11e64 same style as polyline texts 2025-06-30 18:25:41 -03:00
falken10 c420402334 black . formating 2025-06-30 18:25:41 -03:00
falken10 589c562cba refactor everyting within the class MeasureXYZDimensionsTool 2025-06-30 18:25:41 -03:00
falken10 d3f2711fe4 Moved everything to explore tool 2025-06-30 18:25:41 -03:00
falken10 8b4305360e updated to cope for multiple selection and better looking using trihedrons 2025-06-30 18:25:41 -03:00
falken10 1213bbdd73 set exact same color for bounding box edges as gizom axis 2025-06-30 18:25:41 -03:00
falken10 c3380daa19 better layout with colored bounding box 2025-06-30 18:25:41 -03:00
falken10 7aa87907d7 Add local orientation operator and UI toggle for colored dimensions 2025-06-30 18:25:41 -03:00
Andrej730 8cfd6b1754 Unify doc-strings (remove type/rtype)
As this information is already provided in type hints and we don't need to maintain it in two places.
2025-06-30 18:55:14 +05:00
Andrej730 fc10915d2b ifcopenshell.validate - remove simple_spf dependency (689289b)
Moved it to `TYPE_CHECKING` since it's currently used just for typing.

Was breaking validation in Bonsai since it doesn't provide all submodules with IfcOpenShell https://github.com/IfcOpenShell/IfcOpenShell/issues/6723#issuecomment-3016223786

Also added a simple test so github workflow would catch a simple error like this.
2025-06-30 18:08:34 +05:00
Andrej730 c23c21cb88 black . 2025-06-30 18:08:29 +05:00
Geert Hesselink 260bc80a4b update simple_spf submodule 2025-06-30 10:11:40 +02:00
Thomas Krijnen d7cf803fdf Don't use anonymous namespace for geometry_conversion_result 2025-06-29 20:04:44 +02:00
Thomas Krijnen 4488044a68 yum install xz 2025-06-29 19:58:37 +02:00
skemaikin 21a4db7823 serialize roughnessFactor
add roughnessFactor for gltf serialization
2025-06-29 14:24:52 +02:00
Ryan Schultz d300454118 Option to select only immediate children in Spatial Decomposition panel 2025-06-28 15:00:23 -05:00
Ryan Schultz 553003e664 Closes #6748: An option, when running bim.select_similar_container() to only select those objects in the immediate container 2025-06-28 13:16:51 -05:00
Ryan Schultz 524561a398 similar to #6748: option to select only immediate children, not recursively 2025-06-28 12:07:22 -05:00
Ryan Schultz 16f82683c8 closes #6843 - made merge by distance a little more tolerable 2025-06-28 10:07:54 -05:00
Ryan Schultz 4dbec59b9c Fix #6840: Add search to profile selection, when creating a new extrusion type 2025-06-28 09:17:40 -05:00
falken10vdl dcf69c46e5 Update PLAN_LEVEL annotation (#6844)
* Update PLAN_LEVEL annotation

* Length of line segment based on scale

---------

Co-authored-by: Ryan Schultz <ryan@openingdesign.com>
2025-06-27 09:48:12 -05:00
Andrej730 611e83ff1e Remove unused code for additional ifc files in the drawings
Code isn't used for over 3 years now and it's quite simple, so it's easy to restore if we'll need it again.
Noticed when started to investigate what was the use for `include_query` and `exclude_query` and turned out they basically had no effect for all this time.
2025-06-27 18:51:15 +05:00
Andrej730 bdcebd0f98 document.add_information - error handling in case project is not found 2025-06-27 18:51:15 +05:00
Andrej730 9278974d98 Reuse get_linked_models_document 2025-06-27 18:51:15 +05:00
Andrej730 b3a708c06c typing 2025-06-27 18:51:15 +05:00
falken10vdl 0b05c3bcfc Z-coordinate in PlanLevelDecorator relative to spatial container if exists. Absolute otherwise (#6845)
* Z-coordinate  in PlanLevelDecorator relative to spatial container if exists. Absolute otherwise
2025-06-27 08:20:50 -05:00
Piotr Smolira fef6ef76ed Update code_examples.rst
Added example to iterate through entire project.
2025-06-27 11:37:47 +02:00
Piotr Smolira e39d62b35a Update code_examples.rst
Added example about iterating entire model.
2025-06-27 11:37:47 +02:00
Thomas Krijnen f1827d02ca Retain non-uniform scaling by assigning to gtrsf mat directly #6841 2025-06-27 09:54:13 +02:00
Andrej730 65ccc635d4 Fix sheeter issue after 7440c321b 2025-06-27 10:58:28 +05:00
falken10vdl 2698ba69d5 Display TargetScale in Contexts UI / edit target scale denominator (#6816) 2025-06-27 05:48:14 +00:00
Andrej730 efb3b9d255 Add eevee shadows props to shading_styles.json #6847 2025-06-26 20:19:41 +05:00
Andrej730 b0ec185c34 Fix removing occurrences when removing type object #3931 2025-06-26 19:57:10 +05:00
Andrej730 0ca92f6a1d Bonsai preferences - add 'bsdd' label to make bsdd props more recognizable 2025-06-26 19:57:09 +05:00
Andrej730 6e4b784652 bsdd props ui - small tweaks 2025-06-26 19:57:09 +05:00
Andrej730 c764da3511 Status Filter - add missing row alignment in UI 2025-06-26 19:57:09 +05:00
Andrej730 c0d97051fd Status Filters operators - add undo step to prevent Blender crashes
In Blender if operator is editing any Blender data it must have `UNDO` option, otherwise undo might lead to a crash.
2025-06-26 19:57:09 +05:00
Andrej730 2a199cf8a7 Status Filters - add explicit button to refresh status filter
Button location - https://files.catbox.moe/yuk2e6.png
See the reasoning in https://github.com/IfcOpenShell/IfcOpenShell/pull/6826#issuecomment-3004090797
2025-06-26 19:57:08 +05:00
Andrej730 b5dacfd621 Fix console errors toggling ifc status (same as e92520b77) 2025-06-26 19:57:08 +05:00
Andrej730 1a67ce87a1 light.feature - more test fixes 2025-06-26 19:57:08 +05:00
Andrej730 b7db741474 typing 2025-06-26 19:57:08 +05:00
Andrej730 7b1aa207d8 Add a warning in case user set a large drawing resolution #6686
Example - https://files.catbox.moe/0ygukk.png
2025-06-26 16:28:52 +05:00
Stephen Boddy 9b58d4aa47 Minor refinements for 931d8e6 2025-06-26 10:12:55 +05:00
Stephen Boddy bc2d67220e Improve fix for #5563 based on feedback:
- Remove INFO - No statuses selected,
- Remember and set last status on disable-reenable
- Moved duplicated code into shared tool.Sequence class method
2025-06-26 10:12:55 +05:00
Stephen Boddy 7858cb128e Fix #5563 inconsistent behaviour of Status filter 2025-06-26 10:12:55 +05:00
Bruno Perdigão 0d859bd4ee See #6837. Fix handling of connections when splitting walls. 2025-06-25 19:00:25 -03:00
Andrej730 360afe68aa sheeter - replace by_id with by_guid
No functional changes, just to make it more idiomatic (both `by_id` and `by_guid` end up doing `ifc_file[xxx]` under the hood).
2025-06-25 19:01:41 +05:00
Andrej730 b6af68bfe6 data/templates/titleblocks/README.md
Basic readme about folder contents. Will need to move it more general documentation later.
2025-06-25 19:01:41 +05:00
Andrej730 7440c321b6 sheeter - use more strict data access where it's implied 2025-06-25 19:01:41 +05:00
Andrej730 73b5c2f1ae sheeter - simplify namespace access using constants 2025-06-25 19:01:41 +05:00
Andrej730 485ce22ca7 bim.select_all_sheets - fix a typo 2025-06-25 19:01:41 +05:00
Andrej730 e92520b777 Fix value errors in update callback
Blender is requiring update callback to return `None`, otherwise it prints `ValueError: the return value must be None`.
2025-06-25 19:01:40 +05:00
Andrej730 00414a1590 bim.assign_scene_units - expose operator to ui 2025-06-25 19:01:40 +05:00
Andrej730 6b6bf248ff typing 2025-06-25 19:01:40 +05:00
Andrej730 03fcd59c5a black . 2025-06-25 19:01:40 +05:00
Andrej730 5e89748ba6 unit - remove unnecessary ifc operators 2025-06-25 19:01:39 +05:00
Stephen Boddy c5987bca3d Fix #4588 fix broken rev cloud styles in sheets. 2025-06-25 18:59:42 +05:00
Bruno Perdigão 94f98b1e0e Fix issue where edge intersection snap were not being calculated. 2025-06-24 18:17:24 -03:00
Thomas Krijnen 38dcdde7ae submodule 2025-06-24 22:12:38 +02:00
Thomas Krijnen 95f8af01f0 submodule 2025-06-24 22:03:13 +02:00
Thomas Krijnen 8f0d053049 Factor out code into Iterator.cpp 2025-06-24 22:03:13 +02:00
Andrej730 caccfd2516 unit operators - add some descriptions 2025-06-24 19:08:43 +05:00
Andrej730 b4c4efcf5b unit.unassign_unit - smal doc-string fix 2025-06-24 19:08:43 +05:00
Andrej730 fe81dc7f21 Units UI - match icons in enum with icons in ui list
To build a visual association
Example (previously enum had no icons)
https://files.catbox.moe/0ks3jj.png
https://files.catbox.moe/y1yrv5.png
2025-06-24 19:08:42 +05:00
Andrej730 4f77c41bd5 calculate_unit_scale - small optimization 2025-06-24 19:08:42 +05:00
Andrej730 47b077b555 Fix sheets related tests 2025-06-24 19:08:42 +05:00
Andrej730 845e034614 test_feature - fix non-unique function name 2025-06-24 19:08:42 +05:00
Andrej730 82d020b20d bim light tests - fix after f684a6058
Since defaults were updated
2025-06-24 19:08:42 +05:00
Andrej730 cd73f80894 Fix tool test_drawing after 992ad8e 2025-06-24 19:08:41 +05:00
Andrej730 705a924f41 Fix context's TestImportAttributes after e4a50b3 2025-06-24 19:08:41 +05:00
Andrej730 097e03d6f5 Fix TestGenerateSheetIdentification (b20997d) 2025-06-24 19:08:41 +05:00
Andrej730 4a69df1f6b Classification source - automatically update on changes in bsdd ui 2025-06-24 19:08:41 +05:00
Andrej730 df69ca27da Remove duplicated active_dictionary prop (22f10e5) 2025-06-24 19:08:41 +05:00
Andrej730 b3778facda Fix core drawing tests after be65774 2025-06-24 19:08:41 +05:00
Andrej730 c333535ae5 Blender 4.5 - prevent infinite loading of previews
Related - https://projects.blender.org/blender/blender/issues/140903
2025-06-24 19:08:40 +05:00
Andrej730 fcaeb920ec typing 2025-06-24 19:08:40 +05:00
Andrej730 50d3cab1ec Fix regression with thumbnails update #6839 (be1836f) 2025-06-24 19:08:40 +05:00
Andrej730 4574351817 Light UI - detect Sun Position addon activation/deactivation more reliably 2025-06-23 19:06:16 +05:00
Andrej730 623997b40d Revert unintended prop_with_search change (98c479f1b) 2025-06-23 19:06:16 +05:00
Andrej730 8f7b965a58 Light UI - add our own 'coordinates' property
To ensure when it's changed - latitude and longitude update will follow. Previously we were just displaying sun position addon's `coordinates' prop.
2025-06-23 19:06:16 +05:00
Andrej730 c1e6e7d736 light module true_north prop - use Blender angle subtype 2025-06-23 19:06:16 +05:00
Andrej730 f684a6058c Light UI - quickly select current time/pick location from Google Maps
Location - https://files.catbox.moe/ew9tgd.png ("Now" and "Pick" buttons)
2025-06-23 19:06:15 +05:00
Andrej730 1a80e3f1a1 bim.enum_property_search - note on activate_init 2025-06-23 19:06:15 +05:00
Andrej730 a76af3c2ba validate IfcApplication.UR2 - check that both version and app name are not None (263d238f9)
Otherwise it will be caught by regular validation checks
2025-06-23 19:06:15 +05:00
Andrej730 28bee52dff Blender 4.5 - deprecate GPUShader constructor
Now it should be replaced with `gpu.shader.create_from_info`
2025-06-23 19:06:15 +05:00
Andrej730 58449368fb radiance_exporter_properties -> BIMRadianceExporeterProperies
For consistency with other props
2025-06-23 19:06:15 +05:00
Andrej730 30c33518f0 typing 2025-06-23 19:06:14 +05:00
Andrej730 3a06afae25 black . 2025-06-23 19:06:14 +05:00
falken10vdl 98c479f1bd Create instance context menu (#6830) 2025-06-22 07:09:57 -05:00
Ryan Schultz d875baefde #5709 - Partly addresses RCP camera flipping around. (still hacky though) 2025-06-21 10:14:09 -05:00
Ryan Schultz 9149bb0fdc whoops, accidently pushed. 2025-06-21 08:11:01 -05:00
Ryan Schultz f3c86d7fcc added a few to ifc_classes_suggestions.json 2025-06-21 08:08:50 -05:00
Ryan Schultz 64aeef7103 Automatically detect bonsai_path 2025-06-21 07:59:51 -05:00
Andrej730 cd1bda5311 regenerate_wall_representation - remove debug prints 2025-06-20 18:48:38 +05:00
Andrej730 67ae9fced0 bim.extend_walls_to_polyline_point - fix poll errors selecting non-ifc objects
E.g.
```
  File "\bonsai\bim\module\model\wall.py", line 142, in poll
    if not tool.Ifc.get_entity(obj).is_a("IfcWall"):
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'is_a'
```
2025-06-20 18:48:37 +05:00
Andrej730 22fdb324ac Restore daily builds 2025-06-20 18:48:37 +05:00
Andrej730 263d238f9c ifcopenshell.validate - fix IfcApplication.UR2 validation
Previously we were checking for just ApplicationFullName, without considering Version.

https://github.com/buildingSMART/IFC4.3.x-development/issues/966
2025-06-20 18:48:37 +05:00
Andrej730 c6fd02869b ifcopenshell.validate - check json_logger more explicitly 2025-06-20 18:48:37 +05:00
Andrej730 b4d41790a5 ifcopenshell.validate - fix mixed up rule names (IfcApplication.UR) 2025-06-20 18:48:37 +05:00
Andrej730 e18346d4ea bim.remove_application - remove unneccessery info from the tooltip
Since now user can edit applications and see that info there.
2025-06-20 18:48:36 +05:00
Andrej730 c724b2a888 Applications UI - also show app versions
So apps with different version would be identifiable by a glance.
2025-06-20 18:48:36 +05:00
Andrej730 d05f320665 Bonsai - prevent duplicating IfcOpenShell organization for new IfcApplications 2025-06-20 18:48:36 +05:00
Andrej730 6599f74d11 Make Bonsai IfcApplication identifier unique
To avoid validation errors.
2025-06-20 18:48:36 +05:00
Andrej730 4f03c7e03e OwnerData.can_add_user - remove as unnecessary 2025-06-20 18:48:36 +05:00
Andrej730 946cae4065 ifcgit.git_diff - save diff to temp file on alt-click 2025-06-20 18:48:35 +05:00
Andrej730 98145fbbd9 Purge/merge IfcPersonAndOrganizations 2025-06-20 18:48:35 +05:00
Andrej730 74598b805b Purge/merge IfcPerson entities 2025-06-20 18:48:35 +05:00
Andrej730 90ab846a18 typing 2025-06-20 18:48:34 +05:00
Andrej730 5ec77b1b1c black . 2025-06-20 18:48:34 +05:00
Bruno Perdigão 8d079ce0cb Remove unused code. 2025-06-19 16:38:22 -03:00
Bruno Perdigão fb9edb733b Refactor MeasureDecorator to use model PolylineDecorator code. 2025-06-19 16:33:51 -03:00
Andrej730 42b777b1f0 application ui - support changing organization 2025-06-19 19:28:34 +05:00
Andrej730 a968cad4cc core/tool tests for application methods 2025-06-19 19:28:34 +05:00
Andrej730 7ab03109b9 typing 2025-06-19 19:28:33 +05:00
Andrej730 6782729ed8 black . 2025-06-19 19:28:33 +05:00
Ryan Schultz 9dc75ece44 Fix #6593 - preference to turn on/off cut decorator 2025-06-18 21:36:04 -05:00
Andrej730 cbd78506ce Fix mistake in 96bdda305 - expose IfcApplication purge to UI
Noticed a mistake when merge was included twice for applications, instead of including purge+merge.
2025-06-18 19:13:59 +05:00
Andrej730 9af15aeb0b Simple application UI for editing attributes
Example - https://files.catbox.moe/i0wgid.png

Previously before 71d469a27 we produced a lot of IfcApplications on live-builds because of the version differences, now it's possible to edit them from UI - fix the differences and merge them using 106323847
2025-06-18 19:12:12 +05:00
Andrej730 934c9e1485 test_edit_organisation - add ifc4x3 tests 2025-06-18 19:12:12 +05:00
Andrej730 bbebdd56ca owner.edit_application 2025-06-18 19:12:12 +05:00
Andrej730 b1bfe5c3b3 tool.ifc.run - replace with direct api calls 2025-06-18 19:12:11 +05:00
Andrej730 a72e1231f2 test_ids - use more generic exception to fix tests on xmlschema>=4.0
In xmlschema 4.0 it started to throw a more generic XMLSchemaValidationError - I guess there are many things that can trigger validation check and in the new version some other issue gets there first.
2025-06-18 19:12:11 +05:00
Andrej730 47da4ef3ae Fix overlook in 67b539aba 2025-06-18 19:12:11 +05:00
Andrej730 08a8afba5b ifcopenshell-python - fix 3.9 support (replace match statements) 2025-06-18 19:12:10 +05:00
Andrej730 44e5f89119 ruff 0.12 - ignore UP045
Kind of acts the same as UP007 asking to convert all Optional[xxx] to X | None
2025-06-18 19:12:10 +05:00
Andrej730 c68b0c7280 typing 2025-06-18 19:12:10 +05:00
Andrej730 8c5affaae6 linter github workflow - use uv for acquiring black 2025-06-18 19:12:09 +05:00
Andrej730 bd4b80bdc2 linter github workflow - use correct minimum required versions
Previously it was using Python 3.12 for everything, therefore syntax errors from Python 3.9 (e.g. `match` statement in ifcopenshell-python) went under the radar.
2025-06-18 19:12:09 +05:00
Thomas Krijnen 5a597d1a84 Fix binary size issue 2025-03-28 12:08:25 +01:00
Thomas Krijnen 61c4797b8f Fix issue in CurveSegment 2025-03-28 12:08:10 +01:00
Thomas Krijnen c935b2fc12 Merge branch 'v0.8.0' into tfk-rocksdb-storage 2025-03-25 13:05:45 +01:00
Thomas Krijnen 425de7b857 Further small memory optimizations 2025-03-18 10:41:03 +01:00
Thomas Krijnen 8c466eab00 Remove temp goto 2025-03-14 19:15:08 +01:00
Thomas Krijnen 929611f384 Specific speed-ups 2025-03-14 18:56:27 +01:00
Thomas Krijnen 8af4afa781 Do use merges, much better perf, instantiate inverses directly and generally, no longer copy map 2025-03-14 16:16:25 +01:00
Thomas Krijnen 8a3c979172 Speed up toposort with inverse map 2025-03-14 13:11:53 +01:00
Thomas Krijnen 15bbb3b779 Implement rocksdb-based has() 2025-03-14 13:11:30 +01:00
Thomas Krijnen 6cefb2e991 Update .py guess_format() 2025-03-14 10:32:11 +01:00
Thomas Krijnen 10682fb226 Fix python binding 2025-03-14 10:20:22 +01:00
Thomas Krijnen df6b7a34f7 Auto-detect filetype 2025-03-13 13:09:39 +01:00
Thomas Krijnen 67932a22c3 Working non-streaming serializer and read-only model 2025-03-13 12:34:54 +01:00
Thomas Krijnen 9f49ad5f71 Non-streaming rocksdb serializer nearing completion 2025-03-09 21:20:16 +01:00
Thomas Krijnen ce4407ff3c Some successes writing and reading 2025-02-27 22:07:31 +01:00
Thomas Krijnen c58c8269af Fix codegen 2025-02-26 09:34:02 +01:00
Thomas Krijnen c0f148cd3c Run codegen for header schema 2025-02-26 09:25:04 +01:00
Thomas Krijnen 1d9dcb3ab7 Add header schema 2025-02-25 21:30:20 +01:00
Thomas Krijnen a420c4b707 Work towards serialization of data 2025-02-25 21:29:54 +01:00
Thomas Krijnen 048f77cfed Getting closer to working SPF again 2025-02-24 20:46:29 +01:00
Thomas Krijnen b4d0cfe0c8 Wim build script 2025-02-21 16:14:48 +01:00
Thomas Krijnen 69139dee5c Update late bound inst in ifcconvert 2025-02-21 16:14:34 +01:00
Thomas Krijnen e82cfda6a3 Update CMake 2025-02-21 16:14:01 +01:00
Thomas Krijnen 5c9ff09517 Rerun codegen 2025-02-21 16:13:39 +01:00
Thomas Krijnen fb1d78b311 Update codegen 2025-02-21 16:13:21 +01:00
Thomas Krijnen da4e86a1d5 Exploration of using rocksdb as file+instance storage 2025-02-21 16:12:16 +01:00
1106 changed files with 91087 additions and 48070 deletions
+38 -17
View File
@@ -11,13 +11,9 @@ jobs:
matrix:
include:
- os: macos
runner: macos-13
runner: macos-14
arch: x64
oldarch:
- os: macos
runner: macos-14
arch: arm64
oldarch: m1
steps:
- name: Checkout Repository
@@ -34,15 +30,11 @@ jobs:
lfs: true
token: ${{ secrets.BUILD_REPO_TOKEN }}
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.x'
- name: Install Dependencies
run: |
brew update
brew install git bison autoconf automake libffi cmake findutils
# preinstalled: xz, cmake
brew install git bison autoconf automake libffi findutils
echo "$(brew --prefix findutils)/libexec/gnubin" >> $GITHUB_PATH
- name: Install aws cli
@@ -51,20 +43,49 @@ jobs:
- name: Unpack Dependencies
run: |
install_root=$(find ./build -maxdepth 4 -name install)
find "$install_root" -type f -name 'cache-*.tar.gz' -maxdepth 1 -exec tar -xzf {} -C "$install_root" \;
rm -rf ./build/*/*/*/install/*gmp* ./build/*/*/*/install/*cgal*
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
- name: ccache
uses: hendrikmuhs/ccache-action@v1
uses: hendrikmuhs/ccache-action@v1.2
with:
key: ${GITHUB_WORKFLOW}-${{ matrix.os }}
key: mac-${{ matrix.arch }}
- name: Run Build Script
shell: bash
run: |
if [ "${{ matrix.os }}" == "macos" ]; then
DARWIN_C_SOURCE=-D_DARWIN_C_SOURCE
fi
CXXFLAGS="-O3" CFLAGS="-O3 ${DARWIN_C_SOURCE}" ADD_COMMIT_SHA=1 BUILD_CFG=Release python3 ./nix/build-all.py --diskcleanup
if [ "${{ matrix.arch }}" == "x64" ]; then
arch -x86_64 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
MAC_INTEL=-mac-cross-compile-intel
# We don't use gmpcxx, but it comes preinstalled on macos runner as arm64 bottle
# and CGAL detects it and breaks cross compilation.
brew uninstall --ignore-dependencies gmp
# Otherwise Python will fallback to use arm64 `pkg-config`,
# will pick up arm64 libraries ('zstd' in particular),
# and break the build.
/usr/local/bin/brew install pkg-config
# Required by Python.
/usr/local/bin/brew install gettext openssl
fi
set -o pipefail
IFCOS_SCHEMAS=4 CXXFLAGS="-O3" CFLAGS="-O3 ${DARWIN_C_SOURCE}" ADD_COMMIT_SHA=1 BUILD_CFG=Release \
python3 ./nix/build-all.py -v -py-313 --diskcleanup ${MAC_INTEL} \
| tee build.log
- name: Upload Build Logs
if: always()
uses: actions/upload-artifact@v4
with:
name: build-logs-osx-${{ matrix.arch }}
path: |
build.log
build/*/*/*/logs/*.log
build/*/*/*/build/ifcopenshell/**/CMakeCache.txt
retention-days: 30
- name: Pack Dependencies
run: |
@@ -85,7 +106,7 @@ jobs:
- name: Package .zip archives
run: |
VERSION=v`cat VERSION`
cd ./build/`uname`/*/10.9/install/ifcopenshell
cd ./build/`uname`/*/10.15/install/ifcopenshell
mkdir ~/output
ls -d python-* | while read py_version; do
+55 -21
View File
@@ -14,33 +14,67 @@ jobs:
submodules: recursive
path: IfcOpenShell
- name: Checkout Pyodide
- name: Checkout Build Repository
uses: actions/checkout@v3
with:
submodules: recursive
repository: pyodide/pyodide
ref: '0.28.0a3'
repository: IfcOpenShell/build-outputs
path: ifcopenshell_build
ref: wasm
lfs: true
token: ${{ secrets.BUILD_REPO_TOKEN }}
path: pyodide
- name: Unpack Dependencies
run: |
cd ifcopenshell_build
python ../IfcOpenShell/pyodide/cache_dependencies.py unpack
- name: ccache
uses: hendrikmuhs/ccache-action@v1.2
with:
key: ubuntu-22.04-${{ runner.arch }}
- name: Build
run: |
VERSION=`cat IfcOpenShell/VERSION`
sed -i s/0.8.0/$VERSION/g IfcOpenShell/pyodide/meta.yaml
sed -i s/0.8.0/$VERSION/g IfcOpenShell/pyodide/setup.py
echo '#!/usr/bin/bash' > script.sh
echo 'cd pyodide' >> script.sh
echo 'make' >> script.sh
echo 'cd ..' >> script.sh
echo 'mkdir -p packages/ifcopenshell' >> script.sh
echo 'cp IfcOpenShell/pyodide/meta.yaml packages/ifcopenshell' >> script.sh
echo 'PYODIDE_ROOT=/src/pyodide \' >> script.sh
echo 'PATH=/src/pyodide/emsdk/emsdk:/src/pyodide/emsdk/emsdk/node/22.16.0_64bit/bin:/src/pyodide/emsdk/emsdk/upstream/emscripten:$PATH \' >> script.sh
echo 'pyodide build-recipes ifcopenshell --install' >> script.sh
chmod +x script.sh
sed -i s/--tty// pyodide/run_docker
pyodide/run_docker ./script.sh
mv dist/ifcopenshell-$VERSION-py3-none-any.whl dist/ifcopenshell-$VERSION+${GITHUB_SHA:0:7}-cp313-cp313-emscripten_4_0_9_wasm32.whl
./IfcOpenShell/pyodide/build_pyodide.sh
FILE=`echo dist/ifcopenshell-*.whl`
NEW_FILE=`echo $FILE | sed "s/-/+${GITHUB_SHA:0:7}-/2"`
mv $FILE $NEW_FILE
- name: Upload Build Logs
if: always()
uses: actions/upload-artifact@v4
with:
name: build-logs-pyodide
path: |
ifcopenshell_build/*/*/logs/*.log
retention-days: 30
- name: Run wheel tests
run: |
cp -r IfcOpenShell/pyodide/test test
# venv set up in build_pyodide.sh.
source .venv/bin/activate
uv pip install pytest-pyodide
PYODIDE_ROOT_DIST=`pyodide config get pyodide_root`/dist
# `pytest-pyodide` requires pyodide in 'pyodide' directory in cwd, when running `pytest`.
cp -r $PYODIDE_ROOT_DIST test/pyodide
cp dist/ifcopenshell-*.whl test/pyodide
cd test
pytest --capture=no
- name: Pack Dependencies
run: |
cd ifcopenshell_build
python ../IfcOpenShell/pyodide/cache_dependencies.py pack
- name: Commit and Push Changes to Build Repository
run: |
cd ifcopenshell_build
git config user.name "IfcOpenBot"
git config user.email "ifcopenbot@ifcopenshell.org"
git add */*/install/cache-*.tar.gz
git commit -m "Update build artifacts [skip ci]" || echo "No changes to commit"
git push || echo "Push failed"
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
+22 -9
View File
@@ -16,7 +16,8 @@ jobs:
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 \
findutils
findutils xz byacc
python3 -m pip install typing_extensions
git config --global --add safe.directory '*'
- name: Install aws cli
@@ -43,18 +44,30 @@ jobs:
- name: Unpack Dependencies
run: |
install_root=$(find ./build -maxdepth 4 -name install)
find "$install_root" -type f -name 'cache-*.tar.gz' -maxdepth 1 -exec tar -xzf {} -C "$install_root" \;
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
# Not supported on docker
# - name: ccache
# uses: hendrikmuhs/ccache-action@v1
# with:
# key: ${GITHUB_WORKFLOW}-rockylinux8-x64
- name: ccache
# Latest release (1.2.19) doesn't support Rocky, so using a specific commit.
uses: hendrikmuhs/ccache-action@eca11c308176d48942455b9e5b1b70ff6950a778
with:
key: ubuntu-22.04-${{ runner.arch }}-rockylinux8
- name: Run Build Script
shell: bash
run: |
CXXFLAGS="-O3" CFLAGS="-O3 ${DARWIN_C_SOURCE}" ADD_COMMIT_SHA=1 BUILD_CFG=Release python3 ./nix/build-all.py --diskcleanup
set -o pipefail
CXXFLAGS="-O3" CFLAGS="-O3 ${DARWIN_C_SOURCE}" ADD_COMMIT_SHA=1 BUILD_CFG=Release python3 ./nix/build-all.py -v --diskcleanup 2>&1 | tee build.log
- name: Upload Build Logs
if: always()
uses: actions/upload-artifact@v4
with:
name: build-logs-rocky
path: |
build.log
build/*/*/logs/*.log
retention-days: 30
- name: Pack Dependencies
run: |
+21 -8
View File
@@ -16,7 +16,8 @@ jobs:
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 \
findutils
findutils xz byacc
python3 -m pip install typing_extensions
git config --global --add safe.directory '*'
- name: Install aws cli
@@ -43,18 +44,30 @@ jobs:
- name: Unpack Dependencies
run: |
install_root=$(find ./build -maxdepth 4 -name install)
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
# Not supported on docker
# - name: ccache
# uses: hendrikmuhs/ccache-action@v1
# with:
# key: ${GITHUB_WORKFLOW}-rockylinux8-x64
- name: ccache
# Latest release (1.2.19) doesn't support Rocky, so using a specific commit.
uses: hendrikmuhs/ccache-action@eca11c308176d48942455b9e5b1b70ff6950a778
with:
key: ubuntu-22.04-${{ runner.arch }}-rockylinux8
- name: Run Build Script
shell: bash
run: |
CXXFLAGS="-O3" CFLAGS="-O3 ${DARWIN_C_SOURCE}" ADD_COMMIT_SHA=1 BUILD_CFG=Release python3 ./nix/build-all.py --diskcleanup
set -o pipefail
CXXFLAGS="-O3" CFLAGS="-O3 ${DARWIN_C_SOURCE}" ADD_COMMIT_SHA=1 BUILD_CFG=Release python3 ./nix/build-all.py -v --diskcleanup 2>&1 | tee build.log
- name: Upload Build Logs
if: always()
uses: actions/upload-artifact@v4
with:
name: build-logs-rocky-arm64
path: |
build.log
build/*/*/logs/*.log
retention-days: 30
- name: Pack Dependencies
run: |
+11 -49
View File
@@ -9,7 +9,6 @@ jobs:
strategy:
fail-fast: false
matrix:
python: ['3.9.11', '3.10.3', '3.11.8', '3.12.1', '3.13.0']
arch: ['x64']
steps:
- name: Checkout Repository
@@ -30,14 +29,6 @@ jobs:
run: |
choco install -y sed 7zip.install awscli
- name: Install Python
run: |
$installer = "python-${{ matrix.python }}-amd64.exe"
$url = "https://www.python.org/ftp/python/${{ matrix.python }}/$installer"
Invoke-WebRequest -Uri $url -OutFile $installer
Start-Process -Wait -FilePath .\$installer -ArgumentList '/quiet InstallAllUsers=0 PrependPath=0 Include_test=0 TargetDir=C:\Python\${{ matrix.python }}'
Remove-Item .\$installer
- name: Unpack Dependencies
run: |
cd _deps-vs2022-x64-installed
@@ -45,21 +36,21 @@ jobs:
7z x $_.FullName
}
- name: Run Build Script
- name: ccache
# Use fork to resolve cache misses / duplicated cache entries on Windows.
uses: Andrej730/ccache-action@main
with:
key: win-${{ matrix.arch }}
# Windows ccache needs ~1GB
# and with default 500MB some cache gets deleted, leading to misses.
max-size: 5000MB
- name: Run Build Script And Pack .zip Archives
shell: cmd
run: |
setlocal EnableDelayedExpansion
SET PYTHON_VERSION=${{ matrix.python }}
for /f "tokens=1,2,3 delims=." %%a in ("%PYTHON_VERSION%") do (
set PY_VER_MAJOR_MINOR=%%a%%b
)
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat"
SET IFCOS_INSTALL_PYTHON=FALSE
cd win
echo y | call build-deps.cmd vs2022-x64 Release
SET PYTHONHOME=C:\Python\${{ matrix.python }}
call run-cmake.bat vs2022-x64 -DENABLE_BUILD_OPTIMIZATIONS=On -DGLTF_SUPPORT=ON -DADD_COMMIT_SHA=ON -DVERSION_OVERRIDE=ON
call install-ifcopenshell.bat vs2022-x64 Release
python build-all-win.py
- name: Pack Dependencies
run: |
@@ -81,35 +72,6 @@ jobs:
git commit -m "Update build artifacts [skip ci]" || echo "No changes to commit"
git push || echo "Push failed"
- name: Package .zip Archives
run: |
$VERSION = 'v' + ((Get-Content VERSION).Trim())
$SHA = ${env:GITHUB_SHA}.Substring(0, 7)
$OUTPUT_DIR = "$env:USERPROFILE\output"
New-Item -ItemType Directory -Force -Path $OUTPUT_DIR
if ("${{ matrix.python }}" -eq "3.9.11") {
# only for the first python version the executables are assembled for upload
cd _installed-vs2022-x64/bin
Get-ChildItem -Path . | ForEach-Object {
echo $_
$exe = $_.Name
$baseName = $exe.Substring(0, $exe.Length - 4)
$zipName = "${baseName}-$VERSION-$SHA-win64.zip"
7z a $zipName $exe
}
mv *.zip $OUTPUT_DIR
}
$pyVersion = "${{ matrix.python }}"
$pyVersionMajor = ($pyVersion -split '\.')[0..1] -join ''
cd C:\Python\${{ matrix.python }}\Lib\site-packages
Remove-Item -Recurse -Force ifcopenshell\__pycache__ -ErrorAction SilentlyContinue
Get-ChildItem -Path ifcopenshell -Filter "*.pyc" -Recurse | Remove-Item -Force
$zipName = "ifcopenshell-python-$pyVersionMajor-$VERSION-$SHA-win64.zip"
7z a $zipName ifcopenshell
mv $zipName $OUTPUT_DIR
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v4
with:
+1 -1
View File
@@ -34,7 +34,7 @@ jobs:
cd src/bcf &&
make dist IS_STABLE=TRUE
- name: Publish a Python distribution to PyPI
uses: ortega2247/pypi-upload-action@master
uses: pypa/gh-action-pypi-publish@release/v1
with:
user: __token__
password: ${{ secrets.PYPI_API_TOKEN }}
+15 -10
View File
@@ -4,9 +4,6 @@ on:
push:
pull_request:
env:
PYTHON_VERSION: "3.12"
jobs:
lint-formatting:
runs-on: ubuntu-latest
@@ -17,35 +14,43 @@ jobs:
- name: Action - install python
uses: actions/setup-python@v5.3.0
with:
python-version: "${{ env.PYTHON_VERSION }}"
python-version: "3.9"
- name: Action - install python
uses: actions/setup-python@v5.3.0
with:
python-version: "3.11"
- name: Install dependencies
run: |
python3 -m pip install --upgrade pip
python3 -m pip install 'black>=24.10.0'
curl -LsSf https://astral.sh/uv/install.sh | sh
uv tool install ruff
uv tool install black
uv tool install poethepoet
# black doesn't catch all syntax errors, so we check them explicitly.
- name: Check syntax errors
id: syntax-errors
run: |
ERROR=0
python3 -W error -m compileall -q src/ifcopenshell-python || ERROR=1
python3 -W error -m compileall -q src/bonsai || ERROR=1
python3.9 -W error -m compileall -q src/ifcopenshell-python || ERROR=1
python3.11 -W error -m compileall -q src/bonsai || ERROR=1
exit $ERROR
continue-on-error: true
- name: Black formatter
id: black
run: |
python3 -m black --diff --check .
black --diff --check .
continue-on-error: true
- name: Ruff check
id: ruff
run: |
uvx ruff check
ERROR=0
poe ruff-main || ERROR=1
poe ruff-old || ERROR=1
exit $ERROR
continue-on-error: true
- name: Final check
+2 -2
View File
@@ -96,7 +96,7 @@ jobs:
uses: actions/checkout@v2
with:
repository: IfcOpenShell/bonsai_unstable_repo
token: ${{ secrets.IOS_TO_BLENDER_REPO }}
token: ${{ secrets.IFCOPENBOT_TOKEN }}
path: bonsai_unstable_repo
- name: Download Blender and run critical tests
@@ -104,7 +104,7 @@ jobs:
# Ensure Bonsai and ifcsverchok enable/disable works before uploading to extensions repo.
# Download Blender.
wget -q -O blender.tar.xz https://download.blender.org/release/Blender4.4/blender-4.4.0-linux-x64.tar.xz
wget -q -O blender.tar.xz https://download.blender.org/release/Blender4.5/blender-4.5.0-linux-x64.tar.xz
tar -xf blender.tar.xz
# Setup Blender.
+1 -1
View File
@@ -28,7 +28,7 @@ jobs:
cd src/bsdd &&
make dist IS_STABLE=TRUE
- name: Publish a Python distribution to PyPI
uses: ortega2247/pypi-upload-action@master
uses: pypa/gh-action-pypi-publish@release/v1
with:
user: __token__
password: ${{ secrets.PYPI_API_TOKEN }}
+1 -1
View File
@@ -28,7 +28,7 @@ jobs:
cd src/ifc4d &&
make dist IS_STABLE=TRUE
- name: Publish a Python distribution to PyPI
uses: ortega2247/pypi-upload-action@master
uses: pypa/gh-action-pypi-publish@release/v1
with:
user: __token__
password: ${{ secrets.PYPI_API_TOKEN }}
+1 -1
View File
@@ -28,7 +28,7 @@ jobs:
cd src/ifc5d &&
make dist IS_STABLE=TRUE
- name: Publish a Python distribution to PyPI
uses: ortega2247/pypi-upload-action@master
uses: pypa/gh-action-pypi-publish@release/v1
with:
user: __token__
password: ${{ secrets.PYPI_API_TOKEN }}
+1 -1
View File
@@ -28,7 +28,7 @@ jobs:
cd src/ifccityjson &&
make dist IS_STABLE=TRUE
- name: Publish a Python distribution to PyPI
uses: ortega2247/pypi-upload-action@master
uses: pypa/gh-action-pypi-publish@release/v1
with:
user: __token__
password: ${{ secrets.PYPI_API_TOKEN }}
+1 -1
View File
@@ -28,7 +28,7 @@ jobs:
cd src/ifcclash &&
make dist IS_STABLE=TRUE
- name: Publish a Python distribution to PyPI
uses: ortega2247/pypi-upload-action@master
uses: pypa/gh-action-pypi-publish@release/v1
with:
user: __token__
password: ${{ secrets.PYPI_API_TOKEN }}
+1 -1
View File
@@ -28,7 +28,7 @@ jobs:
cd src/ifccsv &&
make dist IS_STABLE=TRUE
- name: Publish a Python distribution to PyPI
uses: ortega2247/pypi-upload-action@master
uses: pypa/gh-action-pypi-publish@release/v1
with:
user: __token__
password: ${{ secrets.PYPI_API_TOKEN }}
+1 -1
View File
@@ -28,7 +28,7 @@ jobs:
cd src/ifcdiff &&
make dist IS_STABLE=TRUE
- name: Publish a Python distribution to PyPI
uses: ortega2247/pypi-upload-action@master
uses: pypa/gh-action-pypi-publish@release/v1
with:
user: __token__
password: ${{ secrets.PYPI_API_TOKEN }}
+1 -1
View File
@@ -28,7 +28,7 @@ jobs:
cd src/ifcfm &&
make dist IS_STABLE=TRUE
- name: Publish a Python distribution to PyPI
uses: ortega2247/pypi-upload-action@master
uses: pypa/gh-action-pypi-publish@release/v1
with:
user: __token__
password: ${{ secrets.PYPI_API_TOKEN }}
@@ -24,7 +24,7 @@ jobs:
strategy:
fail-fast: false
matrix:
pyver: [py39, py310, py311, py312]
pyver: [py39, py310, py311, py312, py313, py314]
config:
- {
name: "Windows 64bit",
@@ -61,7 +61,7 @@ jobs:
cd src/ifcopenshell_${{ matrix.config.short_name }}_${{ matrix.pyver }} &&
make dist PLATFORM=${{ matrix.config.short_name }} PYVERSION=${{ matrix.pyver }} IS_STABLE=TRUE
- name: Publish a Python distribution to PyPI
uses: ortega2247/pypi-upload-action@master
uses: pypa/gh-action-pypi-publish@release/v1
with:
user: __token__
password: ${{ secrets.PYPI_API_TOKEN }}
+1 -1
View File
@@ -19,7 +19,7 @@ jobs:
strategy:
fail-fast: false
matrix:
pyver: [py39, py310, py311, py312]
pyver: [py39, py310, py311, py312, py313, py314]
config:
- {
name: "Windows 64bit",
+1 -1
View File
@@ -28,7 +28,7 @@ jobs:
cd src/ifcpatch &&
make dist IS_STABLE=TRUE
- name: Publish a Python distribution to PyPI
uses: ortega2247/pypi-upload-action@master
uses: pypa/gh-action-pypi-publish@release/v1
with:
user: __token__
password: ${{ secrets.PYPI_API_TOKEN }}
+32
View File
@@ -0,0 +1,32 @@
name: ci-ifctester-org
on:
workflow_dispatch:
push:
paths:
- src/ifctester/**
jobs:
publish_website:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v2
- name: Checkout ifctester_org_static_html
uses: actions/checkout@v4
with:
repository: IfcOpenShell/ifctester_org_static_html
token: ${{ secrets.IFCOPENBOT_TOKEN }}
path: ifctester_org_static_html
- name: Build webapp
working-directory: ./src/ifctester
run: |
sudo apt update && sudo apt install -y nodejs
git config --global user.name 'IfcOpenBot'
git config --global user.email 'IfcOpenBot@users.noreply.github.com'
make webapp-build
- name: Commit and push
run: |
cp -r src/ifctester/webapp/dist/* ifctester_org_static_html/
git -C ifctester_org_static_html add .
git -C ifctester_org_static_html commit --allow-empty -m "$(git log --oneline -1)"
git -C ifctester_org_static_html push
+1 -1
View File
@@ -28,7 +28,7 @@ jobs:
cd src/ifctester &&
make dist IS_STABLE=TRUE
- name: Publish a Python distribution to PyPI
uses: ortega2247/pypi-upload-action@master
uses: pypa/gh-action-pypi-publish@release/v1
with:
user: __token__
password: ${{ secrets.PYPI_API_TOKEN }}
+48 -28
View File
@@ -49,7 +49,8 @@ jobs:
python -m pip install --upgrade pip
pip install xmlschema xsdata numpy lxml pytest isodate lark networkx tabulate python-dateutil shapely
pip install src/bcf --no-deps
pip install https://github.com/Andrej730/aud/archive/refs/heads/master-reduced-size.zip
pip install git+https://github.com/zdhoward/aud
pip install pytest-xdist==3.8.0
- name: Install C++ dependencies
run: |
@@ -69,9 +70,32 @@ jobs:
libhdf5-dev libcgal-dev libeigen3-dev
- name: ccache
uses: hendrikmuhs/ccache-action@v1
uses: hendrikmuhs/ccache-action@v1.2
with:
key: ${GITHUB_WORKFLOW}
key: ubuntu-22.04-${{ runner.arch }}
# RTTI is only enabled by default in Debug builds of rocksdb.
# Distros are using Release builds, so we're compiling it ourselves with RTTI forced on.
# https://github.com/facebook/rocksdb/blob/a3aa44a7167b8336f9bc15c8aba063260268ff68/CMakeLists.txt#L433
- name: build rocksdb
run: |
git clone https://github.com/facebook/rocksdb --branch v9.11.2
cd rocksdb
mkdir build && cd build
# rocksdb is using ccache automatically.
cmake -DFAIL_ON_WARNINGS=Off \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=/usr/local \
-DWITH_TESTS=OFF \
-DWITH_TOOLS=OFF \
-DWITH_GFLAGS=OFF \
-DWITH_BENCHMARK_TOOLS=OFF \
-DWITH_CORE_TOOLS=OFF \
-DROCKSDB_BUILD_SHARED=Off \
-DCMAKE_POSITION_INDEPENDENT_CODE=On \
-DUSE_RTTI=On \
..
sudo make -j$(nproc) install
- name: Build ifcopenshell
run: |
@@ -79,9 +103,9 @@ jobs:
echo ${{ env.pythonLocation }}
mkdir build && cd build
# Ubuntu 22.04's libocct-foundation-dev package doesn't have Config.cmake, so we provide OCC paths directly.
# In later versions of Ubuntu, this can be simplified and the OCC paths can be removed.
cmake \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
-DCMAKE_CXX_STANDARD=17 \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_PREFIX_PATH=/usr \
@@ -90,36 +114,32 @@ jobs:
-DOCC_LIBRARY_DIR=/usr/lib/x86_64-linux-gnu \
-DPYTHON_EXECUTABLE:FILEPATH=${{ env.pythonLocation }}/bin/python \
-DPYTHON_INCLUDE_DIR:PATH=${{ env.pythonLocation }}/include/python3.11 \
-DPYTHON_LIBRARY:FILEPATH=${{ env.pythonLocation }}/lib/libpython3.11.so \
-DCOLLADA_SUPPORT=Off \
-DUSE_MMAP=On \
"-DSCHEMA_VERSIONS=2x3;4;4x3_add2" \
-DGLTF_SUPPORT=On \
-DJSON_INCLUDE_DIR=/usr/include \
-DCGAL_INCLUDE_DIR=/usr/include \
-DGMP_INCLUDE_DIR=/usr/include \
-DMPFR_INCLUDE_DIR=/usr/include \
-DGMP_LIBRARY_DIR=/usr/lib/x86_64-linux-gnu \
-DMPFR_LIBRARY_DIR=/usr/lib/x86_64-linux-gnu \
-DHDF5_INCLUDE_DIR=/usr/include/hdf5/serial \
-DEIGEN_DIR=/usr/include/eigen3 \
-DWITH_ROCKSDB=On \
../cmake
sudo make -j $(nproc)
sudo make install
- name: Run IfcConvert on Sample files
run: |
(find test/input src/bonsai/test/files -name '*.ifc' | while read i; do \
echo $i | tee -a log; \
timeout 1m "$(which IfcConvert)" -yv "$i" "$i.obj" --validate >> log 2>&1; \
echo $i $? >> statuses; \
done) || true
echo Failed
grep -v 0$ statuses
grep -v 0$ statuses | wc -l
echo Succeeded
grep 0$ statuses
grep 0$ statuses | wc -l
# - name: Run IfcConvert on Sample files
# run: |
# (find test/input src/bonsai/test/files -name '*.ifc' | while read i; do \
# echo $i | tee -a log; \
# timeout 1m "$(which IfcConvert)" -yv "$i" "$i.obj" --validate >> log 2>&1; \
# echo $i $? >> statuses; \
# done) || true
# echo Failed
# grep -v 0$ statuses
# grep -v 0$ statuses | wc -l
# echo Succeeded
# grep 0$ statuses
# grep 0$ statuses | wc -l
- name: Run IfcConvert on Sample file
run: |
IfcConvert test/input/acad2010_walls.ifc test/input/acad2010_walls.obj
- name: Test ifcopenshell-python
run: |
@@ -129,7 +149,7 @@ jobs:
mv ifcopenshell ifcopenshell-local # Force testing on installed module
pip install -e ../ifcpatch --no-deps # Needed for sql.py tests.
ERROR=0
make test || ERROR=1
make test-parallel || ERROR=1
cd ../bcf && make test || ERROR=1
pip install requests
cd ../bsdd && make test || ERROR=1
+5
View File
@@ -107,4 +107,9 @@ src/ifcopenshell-python/ifcopenshell/ifcopenshell_wrapper.py
src/bonsai/bonsai/bim/schema/Brick.ttl
bonsaiDecoratorForLoads.code-workspace
dev_environment.bat
.pixi/
src/ifcopenshell-python/ifcopenshell/express/*.exp
src/ifcopenshell-python/ifcopenshell/express/*.exp.cache.dat
+18 -18
View File
@@ -37,25 +37,25 @@ Contents
| Name | Description | License | Service |
| ------------------------- | --------------------------------------------------------------------- | ------------------- | ------- |
| bcf | Library to read and write BCF-XML and query OpenCDE BCF-API modules | LGPL-3.0-or-later | [![PyPI](https://img.shields.io/pypi/v/bcf-client?label=PyPI&color=006dad)](https://pypi.org/project/bcf-client/) [![Anaconda-Server Badge](https://anaconda.org/conda-forge/bcf-client/badges/version.svg)](https://anaconda.org/conda-forge/bcf-client) |
| bonsai | Add-on to Blender providing a graphical native IFC authoring platform | GPL-3.0-or-later | [![Official](https://img.shields.io/badge/BonsaiBIM.org-Download-70ba35)](https://bonsaibim.org/download.html) [![GitHub Unstable](https://img.shields.io/github/v/release/ifcopenshell/ifcopenshell?filter=bonsai-*&label=GitHub-Unstable&color=f6f8fa)](https://github.com/IfcOpenShell/IfcOpenShell/releases?q=bonsai&expanded=true) [![Chocolatey](https://img.shields.io/chocolatey/v/blenderbim-nightly?label=Chocolatey&color=5c9fd8)](https://community.chocolatey.org/packages/blenderbim-nightly/) |
| bsdd | Library to query the bSDD API | LGPL-3.0-or-later | [![PyPI](https://img.shields.io/pypi/v/bsdd?label=PyPI&color=006dad)](https://pypi.org/project/bsdd/) |
| ifc2ca | Utility to convert IFC structural analysis models to Code_Aster | LGPL-3.0-or-later |
| ifc4d | Convert to and from IFC and project management software | LGPL-3.0-or-later | [![PyPI](https://img.shields.io/pypi/v/ifc4d?label=PyPI&color=006dad)](https://pypi.org/project/ifc4d/) |
| ifc5d | Report and optimise cost information from IFC | LGPL-3.0-or-later | [![PyPI](https://img.shields.io/pypi/v/ifc5d?label=PyPI&color=006dad)](https://pypi.org/project/ifc5d/) |
| ifcbimtester | Wrapper for Gherkin based unit testing for IFC models | LGPL-3.0-or-later |
| [bcf](https://docs.ifcopenshell.org/bcf.html) | Library to read and write BCF-XML and query OpenCDE BCF-API modules | LGPL-3.0-or-later | [![PyPI](https://img.shields.io/pypi/v/bcf-client?label=PyPI&color=006dad)](https://pypi.org/project/bcf-client/) [![Anaconda-Server Badge](https://anaconda.org/conda-forge/bcf-client/badges/version.svg)](https://anaconda.org/conda-forge/bcf-client) |
| [bonsai](https://docs.ifcopenshell.org/bonsai.html) | Add-on to Blender providing a graphical native IFC authoring platform | GPL-3.0-or-later | [![Official](https://img.shields.io/badge/BonsaiBIM.org-Download-70ba35)](https://bonsaibim.org/download.html) [![GitHub Unstable](https://img.shields.io/github/v/release/ifcopenshell/ifcopenshell?filter=bonsai-*&label=GitHub-Unstable&color=f6f8fa)](https://github.com/IfcOpenShell/IfcOpenShell/releases?q=bonsai&expanded=true) [![Chocolatey](https://img.shields.io/chocolatey/v/blenderbim-nightly?label=Chocolatey&color=5c9fd8)](https://community.chocolatey.org/packages/blenderbim-nightly/) |
| [bsdd](https://docs.ifcopenshell.org/bsdd.html) | Library to query the bSDD API | LGPL-3.0-or-later | [![PyPI](https://img.shields.io/pypi/v/bsdd?label=PyPI&color=006dad)](https://pypi.org/project/bsdd/) |
| [ifc2ca](https://docs.ifcopenshell.org/ifc2ca.html) | Utility to convert IFC structural analysis models to Code_Aster | LGPL-3.0-or-later |
| [ifc4d](https://docs.ifcopenshell.org/ifc4d.html) | Convert to and from IFC and project management software | LGPL-3.0-or-later | [![PyPI](https://img.shields.io/pypi/v/ifc4d?label=PyPI&color=006dad)](https://pypi.org/project/ifc4d/) |
| [ifc5d](https://docs.ifcopenshell.org/ifc5d.html) | Report and optimise cost information from IFC | LGPL-3.0-or-later | [![PyPI](https://img.shields.io/pypi/v/ifc5d?label=PyPI&color=006dad)](https://pypi.org/project/ifc5d/) |
| [ifcbimtester](https://docs.ifcopenshell.org/bimtester.html) | Wrapper for Gherkin based unit testing for IFC models | LGPL-3.0-or-later |
| ifcblender | Historic Blender IFC import add-on | LGPL-3.0-or-later\* |
| ifccityjson | Convert CityJSON to IFC | LGPL-3.0-or-later | [![PyPI](https://img.shields.io/pypi/v/ifccityjson?label=PyPI&color=006dad)](https://pypi.org/project/ifccityjson/) |
| ifcclash | Clash detection library and CLI app | LGPL-3.0-or-later | [![PyPI](https://img.shields.io/pypi/v/ifcclash?label=PyPI&color=006dad)](https://pypi.org/project/ifcclash/) |
| ifcconvert | CLI app to convert IFC to many other formats | LGPL-3.0-or-later\* | [![Official](https://img.shields.io/badge/IfcOpenShell.org-Download-70ba35)](https://docs.ifcopenshell.org/ifcconvert/installation.html) [![GitHub](https://img.shields.io/github/v/release/ifcopenshell/ifcopenshell?filter=ifcconvert-*&label=GitHub&color=f6f8fa)](https://github.com/IfcOpenShell/IfcOpenShell/releases?q=ifcconvert&expanded=true)
| ifccsv | Library and CLI app to export and import schedules from IFC | LGPL-3.0-or-later | [![PyPI](https://img.shields.io/pypi/v/ifccsv?label=PyPI&color=006dad)](https://pypi.org/project/ifccsv/) |
| ifcdiff | Compare changes between IFC models | LGPL-3.0-or-later | [![PyPI](https://img.shields.io/pypi/v/ifcdiff?label=PyPI&color=006dad)](https://pypi.org/project/ifcdiff/) |
| ifcfm | Extract IFC data for FM handover requirements | LGPL-3.0-or-later | [![PyPI](https://img.shields.io/pypi/v/ifcfm?label=PyPI&color=006dad)](https://pypi.org/project/ifcfm/) |
| ifcmax | Historic extension for IFC support in 3DS Max | LGPL-3.0-or-later\* | [![Official](https://img.shields.io/badge/IfcOpenShell.org-Download-70ba35)](https://docs.ifcopenshell.org/ifcmax.html)
| ifcopenshell-python | Python library for IFC manipulation | LGPL-3.0-or-later\* | [![Official](https://img.shields.io/badge/IfcOpenShell.org-Download-70ba35)](https://docs.ifcopenshell.org/ifcopenshell-python/installation.html) [![GitHub](https://img.shields.io/github/v/release/ifcopenshell/ifcopenshell?filter=ifcopenshell-python-*&label=GitHub&color=f6f8fa)](https://github.com/IfcOpenShell/IfcOpenShell/releases?q=ifcopenshell-python&expanded=true) [![PyPI](https://img.shields.io/pypi/v/ifcopenshell?label=PyPI&color=006dad)](https://pypi.org/project/ifcopenshell/) [![Anaconda](https://img.shields.io/conda/vn/conda-forge/ifcopenshell?label=Anaconda&color=43b02a)](https://anaconda.org/conda-forge/ifcopenshell) [![Anaconda](https://img.shields.io/conda/vn/ifcopenshell/ifcopenshell?label=Anaconda-Unstable&color=43b02a)](https://anaconda.org/ifcopenshell/ifcopenshell) [![Docker](https://img.shields.io/docker/pulls/aecgeeks/ifcopenshell?label=Docker&color=1D63ED)](https://hub.docker.com/r/aecgeeks/ifcopenshell) [![AUR](https://img.shields.io/aur/version/ifcopenshell?label=AUR&color=1793d1)](https://aur.archlinux.org/packages/ifcopenshell) [![AUR Unstable](https://img.shields.io/aur/version/ifcopenshell-git?label=AUR-Unstable&color=1793d1)](https://aur.archlinux.org/packages/ifcopenshell-git) |
| ifcpatch | Utility to run pre-packaged scripts to manipulate IFCs | LGPL-3.0-or-later | [![PyPI](https://img.shields.io/pypi/v/ifcpatch?label=PyPI&color=006dad)](https://pypi.org/project/ifcpatch/) |
| ifcsverchok | Blender Add-on for visual node programming with IFC | GPL-3.0-or-later | [![GitHub Unstable](https://img.shields.io/github/v/release/ifcopenshell/ifcopenshell?filter=ifcsverchok-*.*.*.*&label=GitHub-Unstable&color=f6f8fa)](https://github.com/IfcOpenShell/IfcOpenShell/releases?q=ifcsverchok&expanded=true)
| ifctester | Library, CLI and webapp for IDS model auditing | LGPL-3.0-or-later | [![PyPI](https://img.shields.io/pypi/v/ifctester?label=PyPI&color=006dad)](https://pypi.org/project/ifctester/) |
| [ifccityjson](https://docs.ifcopenshell.org/ifccityjson.html) | Convert CityJSON to IFC | LGPL-3.0-or-later | [![PyPI](https://img.shields.io/pypi/v/ifccityjson?label=PyPI&color=006dad)](https://pypi.org/project/ifccityjson/) |
| [ifcclash](https://docs.ifcopenshell.org/ifcclash.html) | Clash detection library and CLI app | LGPL-3.0-or-later | [![PyPI](https://img.shields.io/pypi/v/ifcclash?label=PyPI&color=006dad)](https://pypi.org/project/ifcclash/) |
| [ifcconvert](https://docs.ifcopenshell.org/ifcconvert.html) | CLI app to convert IFC to many other formats | LGPL-3.0-or-later\* | [![Official](https://img.shields.io/badge/IfcOpenShell.org-Download-70ba35)](https://docs.ifcopenshell.org/ifcconvert/installation.html) [![GitHub](https://img.shields.io/github/v/release/ifcopenshell/ifcopenshell?filter=ifcconvert-*&label=GitHub&color=f6f8fa)](https://github.com/IfcOpenShell/IfcOpenShell/releases?q=ifcconvert&expanded=true)
| [ifccsv](https://docs.ifcopenshell.org/ifccsv.html) | Library and CLI app to export and import schedules from IFC | LGPL-3.0-or-later | [![PyPI](https://img.shields.io/pypi/v/ifccsv?label=PyPI&color=006dad)](https://pypi.org/project/ifccsv/) |
| [ifcdiff](https://docs.ifcopenshell.org/ifcdiff.html) | Compare changes between IFC models | LGPL-3.0-or-later | [![PyPI](https://img.shields.io/pypi/v/ifcdiff?label=PyPI&color=006dad)](https://pypi.org/project/ifcdiff/) |
| [ifcfm](https://docs.ifcopenshell.org/ifcfm.html) | Extract IFC data for FM handover requirements | LGPL-3.0-or-later | [![PyPI](https://img.shields.io/pypi/v/ifcfm?label=PyPI&color=006dad)](https://pypi.org/project/ifcfm/) |
| [ifcmax](https://docs.ifcopenshell.org/ifcmax.html) | Historic extension for IFC support in 3DS Max | LGPL-3.0-or-later\* | [![Official](https://img.shields.io/badge/IfcOpenShell.org-Download-70ba35)](https://docs.ifcopenshell.org/ifcmax.html)
| [ifcopenshell-python](https://docs.ifcopenshell.org/ifcopenshell-python.html) | Python library for IFC manipulation | LGPL-3.0-or-later\* | [![Official](https://img.shields.io/badge/IfcOpenShell.org-Download-70ba35)](https://docs.ifcopenshell.org/ifcopenshell-python/installation.html) [![GitHub](https://img.shields.io/github/v/release/ifcopenshell/ifcopenshell?filter=ifcopenshell-python-*&label=GitHub&color=f6f8fa)](https://github.com/IfcOpenShell/IfcOpenShell/releases?q=ifcopenshell-python&expanded=true) [![PyPI](https://img.shields.io/pypi/v/ifcopenshell?label=PyPI&color=006dad)](https://pypi.org/project/ifcopenshell/) [![Anaconda](https://img.shields.io/conda/vn/conda-forge/ifcopenshell?label=Anaconda&color=43b02a)](https://anaconda.org/conda-forge/ifcopenshell) [![Anaconda](https://img.shields.io/conda/vn/ifcopenshell/ifcopenshell?label=Anaconda-Unstable&color=43b02a)](https://anaconda.org/ifcopenshell/ifcopenshell) [![Docker](https://img.shields.io/docker/pulls/aecgeeks/ifcopenshell?label=Docker&color=1D63ED)](https://hub.docker.com/r/aecgeeks/ifcopenshell) [![AUR](https://img.shields.io/aur/version/ifcopenshell?label=AUR&color=1793d1)](https://aur.archlinux.org/packages/ifcopenshell) [![AUR Unstable](https://img.shields.io/aur/version/ifcopenshell-git?label=AUR-Unstable&color=1793d1)](https://aur.archlinux.org/packages/ifcopenshell-git) [Pyodide WASM Wheels](https://github.com/IfcOpenShell/wasm-wheels#pyodide-test-wheels) |
| [ifcpatch](https://docs.ifcopenshell.org/ifcpatch.html) | Utility to run pre-packaged scripts to manipulate IFCs | LGPL-3.0-or-later | [![PyPI](https://img.shields.io/pypi/v/ifcpatch?label=PyPI&color=006dad)](https://pypi.org/project/ifcpatch/) |
| [ifcsverchok](https://docs.ifcopenshell.org/ifcsverchok.html) | Blender Add-on for visual node programming with IFC | GPL-3.0-or-later | [![GitHub Unstable](https://img.shields.io/github/v/release/ifcopenshell/ifcopenshell?filter=ifcsverchok-*.*.*.*&label=GitHub-Unstable&color=f6f8fa)](https://github.com/IfcOpenShell/IfcOpenShell/releases?q=ifcsverchok&expanded=true)
| [ifctester](https://docs.ifcopenshell.org/ifctester.html) | Library, CLI and webapp for IDS model auditing | LGPL-3.0-or-later | [![PyPI](https://img.shields.io/pypi/v/ifctester?label=PyPI&color=006dad)](https://pypi.org/project/ifctester/) |
The IfcOpenShell C++ codebase is split into multiple interal libraries:
+1 -1
View File
@@ -1 +1 @@
0.8.3
0.8.4
+316 -124
View File
@@ -27,20 +27,17 @@ endif()
set(CMAKE_CXX_STANDARD_REQUIRED ON) # not necessary, but encouraged
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
find_program(CCACHE_FOUND ccache)
if(CCACHE_FOUND)
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache)
endif()
add_definitions(-D_DISABLE_CONSTEXPR_MUTEX_CONSTRUCTOR)
cmake_policy(SET CMP0048 NEW)
cmake_policy(SET CMP0074 NEW)
cmake_policy(SET CMP0078 NEW)
cmake_policy(SET CMP0086 NEW)
if (POLICY CMP0144)
if(POLICY CMP0141) # 3.25+
cmake_policy(SET CMP0141 NEW) # Support for `CMAKE_MSVC_DEBUG_INFORMATION_FORMAT`.
endif()
if(POLICY CMP0144) # 3.27
cmake_policy(SET CMP0144 NEW) # find_package() uses upper-case <PACKAGENAME>_ROOT variables.
endif()
if(POLICY CMP0167) # 3.30
cmake_policy(SET CMP0167 OLD)
endif()
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Release")
@@ -69,7 +66,7 @@ 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_GEOMSERVER "Build IfcGeomServer executable." ON)
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
option(BUILD_PACKAGE "" OFF)
@@ -84,10 +81,18 @@ option(IFCXML_SUPPORT "Build IfcParse with ifcXML support (requires libxml2)." O
option(USD_SUPPORT "Build IfcConvert with USD support (requires pixar's USD library)." OFF)
option(CITYJSON_SUPPORT "Build IfcConvert with CityJSON support (requires CityJSON library)." OFF)
option(WITH_RELATIONSHIP_VALIDATION "Build IfcConvert with option to validate geometrical relationships." OFF)
option(WITH_ROCKSDB "Support a RocksDB key-value store as a file backend in IfcOpenShell" OFF)
option(WITH_ZSTD "Use Zstd compression in RocksDB writes" OFF)
option(USERSPACE_PYTHON_PREFIX "Installs IfcPython for the current user only instead of system-wide." OFF)
option(ADD_COMMIT_SHA "Add commit sha and branch in version number, warning results in many rebuilds, requires git" OFF)
option(VERSION_OVERRIDE "Override the version defined in IfcParse.h with the file VERSION in the repository root" OFF)
option(ADD_COMMIT_SHA "Add commit sha and branch in version number, requires git" OFF)
option(VERSION_OVERRIDE "Override the version defined in buildinfo.cpp with the file VERSION in the repository root" OFF)
set(
PYTHON_MODULE_INSTALL_DIR
"" CACHE PATH
"Directory to install IfcPython package to. By default package is installed in found Python's site-packages."
)
if (VERSION_OVERRIDE)
file(READ "../VERSION" "RELEASE_VERSION_")
@@ -116,6 +121,28 @@ if((BUILD_CONVERT OR BUILD_GEOMSERVER OR BUILD_IFCPYTHON) AND(NOT BUILD_IFCGEOM)
set(BUILD_IFCGEOM ON)
endif()
find_program(CCACHE_FOUND ccache)
if(CCACHE_FOUND)
message(STATUS "`ccache` is found, using it as a compiler launcher.")
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "${CCACHE_FOUND}")
if(MSVC)
# By default Visual Studio generators will use /Zi which is not compatible
# with ccache, so tell Visual Studio to use /Z7 instead.
set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "$<$<CONFIG:Debug,RelWithDebInfo>:Embedded>")
# Not needed for Ninja.
if(CMAKE_GENERATOR MATCHES "Visual Studio")
file(COPY_FILE
${CCACHE_FOUND} ${CMAKE_BINARY_DIR}/cl.exe
ONLY_IF_DIFFERENT)
set(CMAKE_VS_GLOBALS
"CLToolExe=cl.exe"
"CLToolPath=${CMAKE_BINARY_DIR}"
"UseMultiToolTask=true"
)
endif()
endif()
endif()
if(MSVC AND MSVC_PARALLEL_BUILD)
add_definitions("/MP")
endif()
@@ -181,6 +208,8 @@ if(NOT MINIMAL_BUILD)
UNIFY_ENVVARS_AND_CACHE(LIBXML2_INCLUDE_DIR)
UNIFY_ENVVARS_AND_CACHE(LIBXML2_LIBRARIES)
UNIFY_ENVVARS_AND_CACHE(PCRE_LIBRARY_DIR)
UNIFY_ENVVARS_AND_CACHE(PYTHON_INCLUDE_DIR)
UNIFY_ENVVARS_AND_CACHE(PYTHON_LIBRARY)
UNIFY_ENVVARS_AND_CACHE(PYTHON_EXECUTABLE)
UNIFY_ENVVARS_AND_CACHE(HDF5_INCLUDE_DIR)
UNIFY_ENVVARS_AND_CACHE(HDF5_LIBRARY_DIR)
@@ -222,6 +251,25 @@ set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
endmacro()
if(WITH_CGAL)
if(NOT CGAL_INCLUDE_DIR)
# CGAL is not respecting default Boost_USE_STATIC_LIBS value
# and sometiems it's getting in the way.
if(NOT DEFINED Boost_USE_STATIC_LIBS)
set(CGAL_Boost_USE_STATIC_LIBS OFF)
else()
set(CGAL_Boost_USE_STATIC_LIBS "${Boost_USE_STATIC_LIBS}")
endif()
find_package(CGAL REQUIRED)
if(NOT CGAL_DIR)
message(
FATAL_ERROR
"CGAL_SUPPORT enabled, but CGAL_INCLUDE_DIR wasn't provided and CGAL package couldn't be found."
)
endif()
message(STATUS "CGAL: found config at '${CGAL_DIR}'.")
link_libraries(CGAL::CGAL)
endif()
add_definitions(-DIFOPSH_WITH_CGAL)
set(SWIG_DEFINES ${SWIG_DEFINES} -DIFOPSH_WITH_CGAL)
@@ -240,22 +288,33 @@ endif()
if(GLTF_SUPPORT OR CITYJSON_SUPPORT)
UNIFY_ENVVARS_AND_CACHE(JSON_INCLUDE_DIR)
clear_wasm_sysroot()
find_path(json_header_path "nlohmann/json.hpp" HINTS ${JSON_INCLUDE_DIR})
restore_wasm_sysroot()
set(JSON_INCLUDE_DIR ${json_header_path})
if(NOT JSON_INCLUDE_DIR)
find_package(nlohmann_json CONFIG)
if(nlohmann_json_DIR)
link_libraries(nlohmann_json::nlohmann_json)
else()
message(STATUS "Unable to find nlohmann_json package, trying to find it as a header-only library.")
endif()
endif()
if(json_header_path)
message(STATUS "JSON for Modern C++ header file found in ${JSON_INCLUDE_DIR}")
else()
message(FATAL_ERROR "Unable to find JSON for Modern C++ header file, aborting")
if(NOT nlohmann_json_DIR)
clear_wasm_sysroot()
find_path(json_header_path "nlohmann/json.hpp" HINTS ${JSON_INCLUDE_DIR})
restore_wasm_sysroot()
set(JSON_INCLUDE_DIR ${json_header_path})
if(json_header_path)
message(STATUS "JSON for Modern C++ header file found in '${JSON_INCLUDE_DIR}'.")
else()
message(FATAL_ERROR "Unable to find JSON for Modern C++ header file / package, aborting")
endif()
endif()
add_definitions(-DWITH_GLTF)
set(SWIG_DEFINES ${SWIG_DEFINES} -DWITH_GLTF)
endif()
# Add USD support to serializers
# Add USD support to serializers
if(USD_SUPPORT)
UNIFY_ENVVARS_AND_CACHE(USD_INCLUDE_DIR)
UNIFY_ENVVARS_AND_CACHE(USD_LIBRARY_DIR)
@@ -278,13 +337,13 @@ if(USD_SUPPORT)
endif()
set(USD_LIBRARIES
usd_usd
usd_usd
usd_usdGeom
usd_usdShade
usd_usdLux
usd_vt
usd_sdf
usd_tf
usd_usdShade
usd_usdLux
usd_vt
usd_sdf
usd_tf
usd_gf
)
@@ -302,6 +361,38 @@ if(USD_SUPPORT)
set(SWIG_DEFINES ${SWIG_DEFINES} -DWITH_USD)
endif(USD_SUPPORT)
if (WITH_ROCKSDB)
# Temporaily mess with CMAKE_FIND_PACKAGE_PREFER_CONFIG to help RocksDB
# find it's zstd dependency on Windows.
# Only do it on Windows, otherwise it might create problems as
# findzstd and zstd-config target names do not match.
if(WIN32)
set(TEMP CMAKE_FIND_PACKAGE_PREFER_CONFIG)
set(CMAKE_FIND_PACKAGE_PREFER_CONFIG TRUE)
endif()
find_package(RocksDB CONFIG REQUIRED)
if(WIN32)
set(CMAKE_FIND_PACKAGE_PREFER_CONFIG ${TEMP})
endif()
message(STATUS "RocksDB: found at '${RocksDB_DIR}'.")
add_definitions(-DIFOPSH_WITH_ROCKSDB)
set(SWIG_DEFINES ${SWIG_DEFINES} -DIFOPSH_WITH_ROCKSDB)
link_libraries(RocksDB::rocksdb)
if (WITH_ZSTD)
# @todo do we actually need the zstd include dir or rather just pass
# the libzstd.a along with the rocksdb library when needed and feature
# detect based on rocksdb API?
find_package(zstd CONFIG REQUIRED)
message(STATUS "zstd: found at '${zstd_DIR}'.")
link_libraries(zstd::libzstd_static)
add_definitions(-DIFOPSH_WITH_ROCKSDB_ZSTD)
set(SWIG_DEFINES ${SWIG_DEFINES} -DIFOPSH_WITH_ROCKSDB_ZSTD)
endif()
endif()
# Find Boost: On win32 the (hardcoded) default is to use static libraries and
# runtime, when doing running conda-build we pick what conda prepared for us.
if(WIN32 AND("$ENV{CONDA_BUILD}" STREQUAL ""))
@@ -335,7 +426,7 @@ if(WASM_BUILD)
else()
# @todo review this, shouldn't this be all possible header-only now?
# ... or rewritten using C++17 features?
set(BOOST_COMPONENTS system program_options regex thread date_time)
set(BOOST_COMPONENTS system program_options regex thread date_time iostreams)
endif()
if(USE_MMAP)
@@ -358,7 +449,34 @@ message(STATUS "Boost libraries found in ${Boost_LIBRARY_DIRS}")
if(NOT MINIMAL_BUILD)
# libxml2 is required for IFCXML (optional) and SVGFILL (mandatory)
clear_wasm_sysroot()
find_package(LibXml2 REQUIRED)
if(IFCXML_SUPPORT)
if((NOT LIBXML2_INCLUDE_DIR AND NOT LIBXML2_LIBRARIES))
# First try config mode (probably works with vcpkg, Conan, macOS brew installs, but not on ubuntu 22.04)
# CONFIG is provided using root path, so no need to clear sysroot here.
restore_wasm_sysroot()
find_package(LibXml2 QUIET CONFIG)
clear_wasm_sysroot()
if(NOT LibXml2_FOUND)
# Fallback to CMake's builtin FindLibXml2 module (works on Ubuntu)
find_package(LibXml2 REQUIRED)
else()
message(STATUS "Found LibXml2 config: ${LibXml2_DIR}")
endif()
if(TARGET LibXml2::LibXml2)
# Config mode already gives us the target
set(LIBXML2_LIBRARIES LibXml2::LibXml2)
get_target_property(LIBXML2_INCLUDE_DIR LibXml2::LibXml2 INTERFACE_INCLUDE_DIRECTORIES)
else()
# Module mode (Ubuntu)
set(LIBXML2_LIBRARIES ${LibXml2_LIBRARIES})
set(LIBXML2_INCLUDE_DIR ${LibXml2_INCLUDE_DIRS})
endif()
else()
find_package(LibXml2 REQUIRED)
endif()
endif()
restore_wasm_sysroot()
endif()
@@ -368,50 +486,73 @@ if(IFCXML_SUPPORT)
endif()
if(BUILD_IFCGEOM)
if(MSVC)
if(MSVC AND NOT LibXml2_DIR)
add_debug_variants(LIBXML2_LIBRARIES "${LIBXML2_LIBRARIES}" d)
endif()
# Open CASCADE
if(WITH_OPENCASCADE)
if("${OCC_INCLUDE_DIR}" STREQUAL "")
clear_wasm_sysroot()
find_path(OCC_INCLUDE_DIR Standard_Version.hxx
PATHS
/usr/include/occt
/usr/include/oce
/usr/include/opencascade
REQUIRED
)
restore_wasm_sysroot()
if(OCC_INCLUDE_DIR)
message(STATUS "Found Open CASCADE include files in: ${OCC_INCLUDE_DIR}")
else()
message(FATAL_ERROR "Unable to find Open CASCADE include directory, specify OCC_INCLUDE_DIR manually.")
endif()
else()
if(OCC_INCLUDE_DIR)
set(OCC_INCLUDE_DIR ${OCC_INCLUDE_DIR} CACHE FILEPATH "Open CASCADE header files")
message(STATUS "Looking for Open CASCADE include files in: ${OCC_INCLUDE_DIR}")
endif()
if(OCC_INCLUDE_DIR)
if(OCC_LIBRARY_DIR)
set(OCC_LIBRARY_DIR ${OCC_LIBRARY_DIR} CACHE FILEPATH "Open CASCADE library files")
message(STATUS "Looking for Open CASCADE library files in: ${OCC_LIBRARY_DIR}")
endif()
# No specific paths specified, try to find package.
if(OCC_INCLUDE_DIR AND OCC_LIBRARY_DIR)
message(
STATUS
"Using provided OCC_INCLUDE_DIR ('${OCC_INCLUDE_DIR}') "
"and OCC_LIBRARY_DIR ('${OCC_LIBRARY_DIR}')."
)
# Parse OCC_VERSION_STRING.
file(STRINGS ${OCC_INCLUDE_DIR}/Standard_Version.hxx OCC_MAJOR
REGEX "#define OCC_VERSION_MAJOR.*"
)
string(REGEX MATCH "[0-9]+" OCC_MAJOR ${OCC_MAJOR})
file(STRINGS ${OCC_INCLUDE_DIR}/Standard_Version.hxx OCC_MINOR
REGEX "#define OCC_VERSION_MINOR.*"
REGEX "#define OCC_VERSION_MINOR.*"
)
string(REGEX MATCH "[0-9]+" OCC_MINOR ${OCC_MINOR})
file(STRINGS ${OCC_INCLUDE_DIR}/Standard_Version.hxx OCC_MAINT
REGEX "#define OCC_VERSION_MAINTENANCE.*"
REGEX "#define OCC_VERSION_MAINTENANCE.*"
)
string(REGEX MATCH "[0-9]+" OCC_MAINT ${OCC_MAINT})
set(OCC_VERSION_STRING "${OCC_MAJOR}.${OCC_MINOR}.${OCC_MAINT}")
endif(OCC_INCLUDE_DIR)
elseif(NOT OCC_INCLUDE_DIR AND NOT OCC_LIBRARY_DIR)
# OCE is not supported for find_package, because it's using a different name (`oce`)
# and also has an odd directory structure (install/lib/oce-0.18/*.cmake).
find_package(OpenCASCADE CONFIG REQUIRED)
set(OCC_INCLUDE_DIR ${OpenCASCADE_INCLUDE_DIR})
# Do not use OpenCASCADE_LIBRARY_DIR for OCC_LIBRARY_DIR - check target property explicitly.
# On Windows there is a case with OpenCASCADE_LIBRARY_DIR points to `lib` folder,
# while TKernel is actually in `libi`.
get_target_property(TKERNEL_LIB_PATH TKernel LOCATION)
get_filename_component(OCC_LIBRARY_DIR "${TKERNEL_LIB_PATH}" DIRECTORY)
set(OCC_VERSION_STRING ${OpenCASCADE_VERSION})
message(
STATUS
"Found Open CASCADE package at '${OpenCASCADE_DIR}', "
"deducing from it OCC_INCLUDE_DIR: '${OCC_INCLUDE_DIR}' "
"and OCC_LIBRARY_DIR: '${OCC_LIBRARY_DIR}'."
)
else()
message(
FATAL_ERROR
"Couldn't find Open CASCADE installation. "
"Either both OCC_INCLUDE_DIR ('${OCC_INCLUDE_DIR}') and OCC_LIBRARY_DIR ('${OCC_LIBRARY_DIR}') "
"must be specified or OpenCASCADE package should be discoverable. "
"If you're using OCE, then providing a package is not available "
"and you need to provide OCE_INCLUDE_DIR and OCE_LIBRARY_DIR directly."
)
endif()
set(OPENCASCADE_LIBRARY_NAMES
set(
OPENCASCADE_LIBRARY_NAMES
TKernel TKMath TKBRep TKGeomBase TKGeomAlgo TKG3d TKG2d TKShHealing TKTopAlgo TKMesh TKPrim TKBool TKBO
TKFillet TKXSBase TKOffset TKHLR
@@ -425,24 +566,6 @@ if(BUILD_IFCGEOM)
list(APPEND OPENCASCADE_LIBRARY_NAMES TKDESTEP TKDEIGES)
endif(OCC_VERSION_STRING VERSION_LESS 7.8.0)
if("${OCC_LIBRARY_DIR}" STREQUAL "")
find_library(OCC_LIBRARY TKernel
PATHS
/usr/lib
REQUIRED
)
if(OCC_LIBRARY)
GET_FILENAME_COMPONENT(OCC_LIBRARY_DIR ${OCC_LIBRARY} PATH)
message(STATUS "Found Open CASCADE library files in: ${OCC_LIBRARY_DIR}")
else()
message(FATAL_ERROR "Unable find Open CASCADE library directory, specify OCC_LIBRARY_DIR manually.")
endif()
else()
set(OCC_LIBRARY_DIR ${OCC_LIBRARY_DIR} CACHE FILEPATH "Open CASCADE library files")
message(STATUS "Looking for Open CASCADE library files in: ${OCC_LIBRARY_DIR}")
endif()
clear_wasm_sysroot()
find_library(libTKernel NAMES TKernel TKerneld PATHS ${OCC_LIBRARY_DIR} NO_DEFAULT_PATH)
restore_wasm_sysroot()
@@ -450,7 +573,10 @@ if(BUILD_IFCGEOM)
if(libTKernel)
message(STATUS "Required Open Cascade Library files found")
else()
message(FATAL_ERROR "Unable to find Open Cascade library files, aborting")
message(
FATAL_ERROR
"Unable to find Open Cascade library files in OCC_LIBRARY_DIR ('${OCC_LIBRARY_DIR}'), aborting"
)
endif()
# Use the found libTKernel as a template for all other OCC libraries
@@ -481,7 +607,7 @@ if(BUILD_IFCGEOM)
if(OCCT_STATIC)
find_package(Threads)
if(WASM_BUILD)
set(OPENCASCADE_LIBRARIES ${OPENCASCADE_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT})
else()
@@ -493,7 +619,7 @@ if(BUILD_IFCGEOM)
set(OPENCASCADE_LIBRARIES -Wl,--start-group ${OPENCASCADE_LIBRARIES} -Wl,--end-group ${CMAKE_THREAD_LIBS_INIT})
endif()
endif()
if(NOT APPLE AND NOT WIN32)
set(OPENCASCADE_LIBRARIES ${OPENCASCADE_LIBRARIES} "rt")
endif()
@@ -504,7 +630,18 @@ if(BUILD_IFCGEOM)
endif(WITH_OPENCASCADE)
endif(BUILD_IFCGEOM)
if(COLLADA_SUPPORT)
if(COLLADA_SUPPORT AND (NOT OPENCOLLADA_INCLUDE_DIR AND NOT OPENCOLLADA_LIBRARY_DIR))
# If package is found, automatically sets
# OPENCOLLADA_INCLUDE_DIRS and OPENCOLLADA_LIBRARIES (list of targets, not paths).
find_package(OpenCOLLADA CONFIG)
if(OpenCOLLADA_DIR)
message(STATUS "Found OpenCOLLADA: '${OpenCOLLADA_DIR}'.")
set(OPENCOLLADA_FOUND TRUE)
else()
message(STATUS "OpenCOLLADA package not found, falling back to manual search.")
endif()
endif()
if(COLLADA_SUPPORT AND NOT OpenCOLLADA_DIR)
# Find OpenCOLLADA
if("${OPENCOLLADA_INCLUDE_DIR}" STREQUAL "")
message(STATUS "No OpenCOLLADA include directory specified")
@@ -537,8 +674,7 @@ if(COLLADA_SUPPORT)
if(COLLADASWStreamWriter_h)
message(STATUS "OpenCOLLADA header files found")
add_definitions(-DWITH_OPENCOLLADA)
set(SWIG_DEFINES ${SWIG_DEFINES} -DWITH_OPENCOLLADA)
set(OPENCOLLADA_FOUND TRUE)
set(OPENCOLLADA_LIBRARY_NAMES
GeneratedSaxParser MathMLSolver OpenCOLLADABaseUtils OpenCOLLADAFramework OpenCOLLADASaxFrameworkLoader
@@ -586,7 +722,12 @@ if(COLLADA_SUPPORT)
message(FATAL_ERROR "COLLADA_SUPPORT enabled, but unable to find OpenCOLLADA headers. "
"Disable COLLADA_SUPPORT or fix OpenCOLLADA paths to proceed.")
endif()
endif(COLLADA_SUPPORT)
endif(COLLADA_SUPPORT AND NOT OpenCOLLADA_DIR)
if(COLLADA_SUPPORT AND OPENCOLLADA_FOUND)
add_definitions(-DWITH_OPENCOLLADA)
set(SWIG_DEFINES ${SWIG_DEFINES} -DWITH_OPENCOLLADA)
endif()
if(HDF5_SUPPORT)
if("${HDF5_INCLUDE_DIR}" STREQUAL "")
@@ -653,15 +794,26 @@ if(HDF5_SUPPORT)
endif()
endif()
if(NOT HDF5_LIBRARIES)
# debian default
set(HDF5_LIBRARIES
/usr/lib/x86_64-linux-gnu/hdf5/serial/libhdf5_cpp.so
/usr/lib/x86_64-linux-gnu/hdf5/serial/libhdf5.so
/usr/lib/x86_64-linux-gnu/libsz.so
/usr/lib/x86_64-linux-gnu/libaec.so
z dl
)
if(NOT HDF5_INCLUDE_DIR OR NOT HDF5_LIBRARY_DIR)
# First try to find it as a config.
find_package(HDF5 CONFIG)
if(HDF5_DIR)
message(STATUS "HDF5: found config at '${HDF5_DIR}'.")
set(HDF5_LIBRARIES hdf5_cpp-static)
else()
# If it failed, still try to find as a module.
# E.g. on Ubuntu `libhdf5-dev` doesn't provie hdf5-config.cmake.
# Will automatically fill HDF5_LIBRARIES and HDF5_INCLUDE_DIR.
find_package(HDF5 COMPONENTS CXX)
if(NOT HDF5_INCLUDE_DIR)
message(
FATAL_ERROR
"HDF5_INCLUDE_DIR is not provided (current value: '${HDF5_INCLUDE_DIR}'). "
"HDF5_LIBRARY_DIR is not provided (current value: '${HDF5_LIBRARY_DIR}'). "
"Also could not find HDF5 package (neither module or config)."
)
endif()
endif()
endif()
add_definitions(-DWITH_HDF5)
@@ -778,6 +930,23 @@ else()
endif()
endif(MSVC)
# Ensure other dependencies are provided.
if(NOT EXISTS "${EIGEN_DIR}")
find_package(Eigen3 CONFIG)
if(Eigen3_DIR)
message(STATUS "Eigen3: found config at '${Eigen3_DIR}'.")
else()
message(
FATAL_ERROR
"EIGEN_DIR is not provided or provided folder doesn't exist (current value: '${EIGEN_DIR}'). "
"Also couldn't find Eigen3 as a package."
)
endif()
link_libraries(Eigen3::Eigen)
endif()
include_directories(${INCLUDE_DIRECTORIES} ${OCC_INCLUDE_DIR} ${OPENCOLLADA_INCLUDE_DIRS}
${Boost_INCLUDE_DIRS} ${LIBXML2_INCLUDE_DIR} ${JSON_INCLUDE_DIR} ${HDF5_INCLUDE_DIR}
${EIGEN_DIR} ${CGAL_INCLUDE_DIR} ${GMP_INCLUDE_DIR} ${MPFR_INCLUDE_DIR} ${USD_INCLUDE_DIR}
@@ -787,7 +956,7 @@ include_directories(${INCLUDE_DIRECTORIES} ${OCC_INCLUDE_DIR} ${OPENCOLLADA_INCL
if(NOT SCHEMA_VERSIONS)
if(WASM_BUILD)
# super arbitrarily try to keep size down at least a little bit
set(SCHEMA_VERSIONS "2x3" "4")
set(SCHEMA_VERSIONS "2x3" "4" "4x3_add2")
else()
set(SCHEMA_VERSIONS "2x3" "4" "4x1" "4x2" "4x3" "4x3_tc1" "4x3_add1" "4x3_add2")
endif()
@@ -875,11 +1044,7 @@ if(BUILD_IFCGEOM)
foreach(schema ${SCHEMA_VERSIONS})
set(IFCGEOM_SCHEMA_LIBRARIES ${IFCGEOM_SCHEMA_LIBRARIES} geometry_mapping_ifc${schema})
endforeach()
if(WASM_BUILD)
set(IFCOPENSHELL_LIBRARIES ${IFCOPENSHELL_LIBRARIES} IfcGeom ${IFCGEOM_SCHEMA_LIBRARIES})
else()
set(IFCOPENSHELL_LIBRARIES ${IFCOPENSHELL_LIBRARIES} IfcGeom ${IFCGEOM_SCHEMA_LIBRARIES} IfcGeom ${IFCGEOM_SCHEMA_LIBRARIES})
endif()
set(IFCOPENSHELL_LIBRARIES ${IFCOPENSHELL_LIBRARIES} IfcGeom ${IFCGEOM_SCHEMA_LIBRARIES})
endif()
if(BUILD_CONVERT OR BUILD_IFCPYTHON)
@@ -893,12 +1058,14 @@ if(BUILD_CONVERT OR BUILD_IFCPYTHON)
set(GEOM_SERIALIZER_SCHEMA_LIBRARIES ${GEOM_SERIALIZER_SCHEMA_LIBRARIES} GeometrySerializers_ifc${schema})
add_library(geometry_serializer_ifc${schema} STATIC ../src/ifcgeom/Serialization/schema/Serialization.cpp)
set_target_properties(geometry_serializer_ifc${schema} PROPERTIES COMPILE_FLAGS "-DIFC_GEOM_EXPORTS -DIfcSchema=Ifc${schema}")
set_target_properties(geometry_serializer_ifc${schema} PROPERTIES COMPILE_FLAGS "-DIFC_GEOMSERIALIZATION_EXPORTS -DIfcSchema=Ifc${schema}")
target_link_libraries(geometry_serializer_ifc${schema} ${OPENCASCADE_LIBRARIES})
list(APPEND geometry_serializer_libraries geometry_serializer_ifc${schema})
endforeach()
add_library(geometry_serializer STATIC ../src/ifcgeom/Serialization/Serialization.cpp)
target_link_libraries(geometry_serializer ${geometry_serializer_libraries})
add_library(geometry_serializer STATIC ../src/ifcgeom/Serialization/Serialization.h ../src/ifcgeom/Serialization/Serialization.cpp)
set_target_properties(geometry_serializer PROPERTIES COMPILE_FLAGS "-DIFC_GEOMSERIALIZATION_EXPORTS")
target_link_libraries(geometry_serializer ${geometry_serializer_libraries} IfcParse)
set(IFCOPENSHELL_LIBRARIES ${IFCOPENSHELL_LIBRARIES} geometry_serializer ${geometry_serializer_libraries})
endif()
endif()
@@ -937,8 +1104,12 @@ endforeach()
set(IFCPARSE_FILES ${IFCPARSE_CPP_FILES} ${IFCPARSE_H_FILES})
add_library(IfcParse ${IFCPARSE_FILES})
target_link_libraries(IfcParse ${STDCPPFS})
set_target_properties(IfcParse PROPERTIES COMPILE_FLAGS -DIFC_PARSE_EXPORTS VERSION "${PROJECT_VERSION}" SOVERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}")
if(LibXml2_DIR)
target_compile_definitions(IfcParse PRIVATE ${LIBXML2_DEFINITIONS})
endif()
if(WASM_BUILD)
target_link_libraries(IfcParse ${BCRYPT_LIBRARIES} ${LIBXML2_LIBRARIES})
else()
@@ -946,7 +1117,11 @@ else()
endif()
if(BUILD_IFCGEOM)
if(WITH_CGAL)
# CGAL::CGAL target already has dependencies resolved.
if(WITH_CGAL AND CGAL_DIR)
set(CGAL_LIBRARIES CGAL::CGAL)
message(STATUS "Using found CGAL package at '${CGAL_DIR}'")
elseif(WITH_CGAL AND NOT CGAL_DIR)
clear_wasm_sysroot()
find_library(libGMP NAMES gmp mpir PATHS ${GMP_LIBRARY_DIR} NO_DEFAULT_PATH)
find_library(libMPFR NAMES mpfr PATHS ${MPFR_LIBRARY_DIR} NO_DEFAULT_PATH)
@@ -967,24 +1142,24 @@ if(BUILD_IFCGEOM)
file(GLOB IFCGEOM_H_FILES ../src/ifcgeom/kernels/${kernel}/*.h)
file(GLOB IFCGEOM_CPP_FILES ../src/ifcgeom/kernels/${kernel}/*.cpp)
set(IFCGEOM_FILES ${IFCGEOM_CPP_FILES} ${IFCGEOM_H_FILES})
add_library(geometry_kernel_${kernel} ${IFCGEOM_FILES})
set_property(TARGET geometry_kernel_${kernel} APPEND PROPERTY COMPILE_FLAGS "-DIFC_GEOM_EXPORTS")
add_library(geometry_kernel_${kernel} ${IFCGEOM_FILES} ../src/ifcgeom/kernels/ifc_geomlibrary_api.h)
set_property(TARGET geometry_kernel_${kernel} APPEND PROPERTY COMPILE_FLAGS "-DIFC_GEOMLIBRARY_EXPORTS")
# needed?
# if(NOT WASM_BUILD)
# endif()
target_link_libraries(geometry_kernel_${kernel} ${${KERNEL_UPPER}_LIBRARIES})
target_link_libraries(geometry_kernel_${kernel} ${${KERNEL_UPPER}_LIBRARIES} IfcGeom IfcParse)
list(APPEND kernel_libraries geometry_kernel_${kernel})
if(${kernel} STREQUAL "cgal")
set_property(TARGET geometry_kernel_${kernel} APPEND_STRING PROPERTY COMPILE_FLAGS " -DCGAL_HAS_THREADS")
add_library(geometry_kernel_${kernel}_simple ${IFCGEOM_FILES})
set_target_properties(geometry_kernel_${kernel}_simple PROPERTIES COMPILE_FLAGS "-DIFC_GEOM_EXPORTS -DIFOPSH_SIMPLE_KERNEL -DCGAL_HAS_THREADS")
set_target_properties(geometry_kernel_${kernel}_simple PROPERTIES COMPILE_FLAGS "-DIFC_GEOMLIBRARY_EXPORTS -DIFOPSH_SIMPLE_KERNEL -DCGAL_HAS_THREADS")
# needed?
# if(NOT WASM_BUILD)
# endif()
target_link_libraries(geometry_kernel_${kernel}_simple ${${KERNEL_UPPER}_LIBRARIES})
target_link_libraries(geometry_kernel_${kernel}_simple ${${KERNEL_UPPER}_LIBRARIES} IfcGeom IfcParse)
list(APPEND kernel_libraries geometry_kernel_${kernel}_simple)
endif()
endforeach()
@@ -995,10 +1170,13 @@ if(BUILD_IFCGEOM)
file(GLOB IFCGEOM_H_FILES ../src/ifcgeom/mapping/*.h)
file(GLOB IFCGEOM_CPP_FILES ../src/ifcgeom/mapping/*.cpp)
set(IFCGEOM_FILES ${IFCGEOM_CPP_FILES} ${IFCGEOM_H_FILES} ${IFCGEOM_I_FILES})
add_library(geometry_mapping_ifc${schema} STATIC ${IFCGEOM_FILES})
set_target_properties(geometry_mapping_ifc${schema} PROPERTIES COMPILE_FLAGS "-DIFC_GEOM_EXPORTS -DIfcSchema=Ifc${schema}")
target_link_libraries(geometry_mapping_ifc${schema} IfcParse)
if (NOT BUILD_SHARED_LIBS)
target_link_libraries(geometry_mapping_ifc${schema} IfcGeom)
endif()
list(APPEND mapping_libraries geometry_mapping_ifc${schema})
endforeach()
@@ -1014,11 +1192,7 @@ if(BUILD_IFCGEOM)
find_package(Threads)
endif()
if(WASM_BUILD)
target_link_libraries(IfcGeom ${kernel_libraries} ${mapping_libraries} ${CMAKE_THREAD_LIBS_INIT})
else()
target_link_libraries(IfcGeom IfcParse ${kernel_libraries} ${mapping_libraries} ${CMAKE_THREAD_LIBS_INIT})
endif()
target_link_libraries(IfcGeom IfcParse ${mapping_libraries} ${CMAKE_THREAD_LIBS_INIT})
endif(BUILD_IFCGEOM)
@@ -1033,8 +1207,8 @@ if(BUILD_CONVERT OR BUILD_IFCPYTHON)
foreach(schema ${SCHEMA_VERSIONS})
add_library(Serializers_ifc${schema} STATIC ${SERIALIZERS_S_FILES})
set_target_properties(Serializers_ifc${schema} PROPERTIES COMPILE_FLAGS "-DIFC_GEOM_EXPORTS -DIfcSchema=Ifc${schema}")
set_target_properties(Serializers_ifc${schema} PROPERTIES COMPILE_FLAGS "-DSERIALIZERS_EXPORTS -DIfcSchema=Ifc${schema}")
if(WASM_BUILD)
target_link_libraries(Serializers_ifc${schema} ${HDF5_LIBRARIES})
else()
@@ -1043,7 +1217,7 @@ if(BUILD_CONVERT OR BUILD_IFCPYTHON)
endforeach()
add_library(Serializers ${SERIALIZERS_FILES})
set_target_properties(Serializers PROPERTIES COMPILE_FLAGS "-DIFC_GEOM_EXPORTS" VERSION "${PROJECT_VERSION}" SOVERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}")
set_target_properties(Serializers PROPERTIES COMPILE_FLAGS "-DSERIALIZERS_EXPORTS" VERSION "${PROJECT_VERSION}" SOVERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}")
if(WITH_PROJ)
target_compile_definitions(Serializers PRIVATE "WITH_PROJ")
@@ -1054,7 +1228,7 @@ if(BUILD_CONVERT OR BUILD_IFCPYTHON)
target_link_libraries(Serializers ${PROJ_LIBRARIES})
endif()
target_link_libraries(Serializers ${SERIALIZER_SCHEMA_LIBRARIES} ${OPENCOLLADA_LIBRARIES} ${USD_LIBRARIES})
target_link_libraries(Serializers ${SERIALIZER_SCHEMA_LIBRARIES} ${OPENCOLLADA_LIBRARIES} ${USD_LIBRARIES} IfcGeom ${OPENCASCADE_LIBRARIES} ${kernel_libraries} IfcParse)
endif(BUILD_CONVERT OR BUILD_IFCPYTHON)
@@ -1101,7 +1275,7 @@ if(BUILD_CONVERT)
set(IFCCONVERT_FILES ${IFCCONVERT_CPP_FILES} ${IFCCONVERT_H_FILES})
add_executable(IfcConvert ${IFCCONVERT_FILES})
target_link_libraries(IfcConvert ${IFCOPENSHELL_LIBRARIES} ${OPENCASCADE_LIBRARIES} ${Boost_LIBRARIES} ${HDF5_LIBRARIES} ${USD_LIBRARIES})
target_link_libraries(IfcConvert IfcGeom IfcParse Serializers ${kernel_libraries} ${OPENCASCADE_LIBRARIES} ${Boost_LIBRARIES} ${HDF5_LIBRARIES} ${USD_LIBRARIES})
if (WITH_RELATIONSHIP_VALIDATION)
set_property(TARGET IfcConvert APPEND_STRING PROPERTY COMPILE_FLAGS " -DWITH_RELATIONSHIP_VALIDATION")
endif()
@@ -1126,11 +1300,16 @@ endif(BUILD_CONVERT)
# IfcGeomServer
if(BUILD_GEOMSERVER)
if(NOT WITH_OPENCASCADE)
message(FATAL_ERROR "Open CASCADE is required to build IfcGeomServer.")
endif()
file(GLOB CPP_FILES ../src/ifcgeomserver/*.cpp)
file(GLOB H_FILES ../src/ifcgeomserver/*.h)
set(SOURCE_FILES ${CPP_FILES} ${H_FILES})
add_executable(IfcGeomServer ${SOURCE_FILES})
target_link_libraries(IfcGeomServer ${IFCOPENSHELL_LIBRARIES} ${OPENCASCADE_LIBRARIES} ${Boost_LIBRARIES})
target_link_libraries(IfcGeomServer IfcGeom IfcParse Serializers ${kernel_libraries} ${OPENCASCADE_LIBRARIES} ${Boost_LIBRARIES})
if((NOT WIN32) AND BUILD_SHARED_LIBS)
SET_INSTALL_RPATHS(IfcGeomServer "${IFCOPENSHELL_LIBRARY_DIR};${OCC_LIBRARY_DIR};${Boost_LIBRARY_DIRS}")
@@ -1146,6 +1325,10 @@ endif(BUILD_GEOMSERVER)
if(ADD_COMMIT_SHA)
find_package(Git)
if(NOT GIT_FOUND)
message(FATAL_ERROR "Failed to find Git for ADD_COMMIT_SHA option.")
endif()
if(GIT_FOUND)
if (VERSION_OVERRIDE)
set (git_branch ${RELEASE_VERSION})
@@ -1183,8 +1366,10 @@ if(ADD_COMMIT_SHA)
message(FATAL_ERROR "Unable to determine commit sha and/or branch")
endif()
add_definitions(-DIFCOPENSHELL_BRANCH=${git_branch})
add_definitions(-DIFCOPENSHELL_COMMIT=${git_sha})
target_compile_definitions(IfcParse PRIVATE
-DIFCOPENSHELL_BRANCH=${git_branch}
-DIFCOPENSHELL_COMMIT=${git_sha}
)
endif()
endif(ADD_COMMIT_SHA)
@@ -1214,7 +1399,7 @@ if(BUILD_IFCMAX)
endif()
if(WITH_CGAL)
add_subdirectory(../src/svgfill svgfill)
add_subdirectory(../src/svgfill svgfill)
endif()
if(BUILD_QTVIEWER)
@@ -1241,6 +1426,11 @@ if(BUILD_IFCGEOM)
DESTINATION ${INCLUDEDIR}/ifcgeom
)
file(GLOB SERIALIZATION_H_FILES ../src/ifcgeom/serialization/*.h)
install(FILES ${SERIALIZATION_H_FILES}
DESTINATION ${INCLUDEDIR}/ifcgeom/serialization
)
foreach(kernel ${GEOMETRY_KERNELS})
file(GLOB IFCGEOM_H_FILES ../src/ifcgeom/kernels/${kernel}/*.h)
install(FILES ${IFCGEOM_H_FILES}
@@ -1272,11 +1462,13 @@ if(BUILD_CONVERT)
endif(BUILD_CONVERT)
if(BUILD_CONVERT OR BUILD_IFCPYTHON)
install(TARGETS geometry_serializer ${geometry_serializer_libraries}
ARCHIVE DESTINATION ${LIBDIR}
LIBRARY DESTINATION ${LIBDIR}
RUNTIME DESTINATION ${BINDIR}
)
if(WITH_OPENCASCADE)
install(TARGETS geometry_serializer ${geometry_serializer_libraries}
ARCHIVE DESTINATION ${LIBDIR}
LIBRARY DESTINATION ${LIBDIR}
RUNTIME DESTINATION ${BINDIR}
)
endif()
endif(BUILD_CONVERT OR BUILD_IFCPYTHON)
# Cmake uninstall target
+114
View File
@@ -0,0 +1,114 @@
{
"version": 6,
"configurePresets": [
{
"name": "shared",
"generator": "Ninja",
"hidden": true,
"cacheVariables": {
"BUILD_IFCPYTHON": "ON",
"BUILD_IFCGEOM": "ON",
"COLLADA_SUPPORT": "OFF",
"BUILD_EXAMPLES": "OFF",
"BUILD_GEOMSERVER": "OFF",
"GLTF_SUPPORT": "ON",
"BUILD_CONVERT": "ON",
"BUILD_IFCMAX": "OFF",
"IFCXML_SUPPORT": "ON",
"HDF5_SUPPORT": "ON",
"SCHEMA_VERSIONS": "4x3_add2",
"CITYJSON_SUPPORT": "OFF",
"CMAKE_GENERATOR_PLATFORM": "",
"CMAKE_GENERATOR_TOOLSET": ""
}
},
{
"name": "win-shared",
"inherits": [
"shared"
],
"hidden": true,
"environment": {
"CONDA_BUILD": "ON",
"CONDA_PY": "312"
},
"cacheVariables": {
"Boost_USE_STATIC_LIBS": "OFF",
"CMAKE_INSTALL_PREFIX": "$env{LIBRARY_PREFIX}",
"PYTHON_EXECUTABLE": "$env{PREFIX}/python.exe",
"PYTHON_INCLUDE_DIR": "$env{PREFIX}/include",
"PYTHON_LIBRARY": "$env{PREFIX}/libs/python$env{CONDA_PY}.lib",
"CMAKE_FIND_ROOT_PATH": "$env{LIBRARY_PREFIX}",
"CMAKE_PREFIX_PATH": "$env{LIBRARY_PREFIX}",
"LIBXML2_LIBRARIES": "$env{LIBRARY_PREFIX}/lib/libxml2.lib",
"OCC_INCLUDE_DIR": "$env{LIBRARY_PREFIX}/include/opencascade",
"OCC_LIBRARY_DIR": "$env{LIBRARY_PREFIX}/lib",
"CGAL_INCLUDE_DIR": "$env{LIBRARY_PREFIX}/include",
"EIGEN_DIR": "$env{LIBRARY_PREFIX}/include/eigen3",
"JSON_INCLUDE_DIR": "$env{LIBRARY_PREFIX}/include",
"GMP_INCLUDE_DIR": "$env{LIBRARY_PREFIX}/include",
"GMP_LIBRARY_DIR": "$env{LIBRARY_PREFIX}/lib",
"MPFR_LIBRARY_DIR": "$env{LIBRARY_PREFIX}/lib",
"Boost_LIBRARY_DIR": "$env{LIBRARY_PREFIX}/lib",
"Boost_INCLUDE_DIR": "$env{LIBRARY_PREFIX}/include",
"HDF5_INCLUDE_DIR": "$env{LIBRARY_PREFIX}/include",
"HDF5_LIBRARY_DIR": "$env{LIBRARY_PREFIX}/lib",
"ZLIB_INCLUDE_DIR": "$env{LIBRARY_PREFIX}/include"
}
},
{
"name": "win-release",
"inherits": [
"win-shared"
],
"hidden": false,
"warnings": {
"dev": false
},
"environment": {
"PREFIX": "${sourceDir}/../.pixi/envs/prod",
"LIBRARY_PREFIX": "${sourceDir}/../.pixi/envs/prod/Library"
},
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release"
}
},
{
"name": "win-debug",
"inherits": [
"win-shared"
],
"hidden": false,
"binaryDir": "${sourceDir}/../build/win-debug",
"warnings": {
"dev": false
},
"environment": {
"PREFIX": "${sourceDir}/../.pixi/envs/dev",
"LIBRARY_PREFIX": "${sourceDir}/../.pixi/envs/dev/Library"
},
"cacheVariables": {
"CMAKE_BUILD_TYPE": "RelWithDebInfo"
}
},
{
"name": "win-test",
"inherits": [
"win-shared"
],
"hidden": false,
"binaryDir": "${sourceDir}/../build/win-test",
"warnings": {
"dev": false
},
"environment": {
"PREFIX": "${sourceDir}/../.pixi/envs/tests",
"LIBRARY_PREFIX": "${sourceDir}/../.pixi/envs/tests/Library"
},
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release",
"SCHEMA_VERSIONS": "2x3;4;4x3_add2"
}
}
]
}
+1 -1
View File
@@ -121,4 +121,4 @@ function(files_for_ifc_version IFC_VERSION RESULT_NAME)
${IFC_PARSE_DIR}/Ifc${IFC_VERSION}.cpp
PARENT_SCOPE
)
endfunction()
endfunction()
+827 -319
View File
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,13 @@
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")
@@ -0,0 +1,13 @@
diff --git a/OpenCOLLADAConfig.cmake.in b/OpenCOLLADAConfig.cmake.in
index d765b108..6800c2a7 100644
--- a/OpenCOLLADAConfig.cmake.in
+++ b/OpenCOLLADAConfig.cmake.in
@@ -31,7 +31,7 @@ set(OPENCOLLADA_INCLUDE_DIRS
include("@PACKAGE_OPENCOLLADA_INST_CMAKECONFIG@/OpenCOLLADATargets.cmake")
# Set the library variable
-if(UNIX)
+if(0)
set(OPENCOLLADA_LIBRARIES
ftoa_shared
buffer_shared
+8645
View File
File diff suppressed because it is too large Load Diff
+84
View File
@@ -0,0 +1,84 @@
[project]
name = "IfcOpenShell"
version = "0.8.4"
description = "IfcOpenShell is a library to support the IFC file format"
channels = ["conda-forge"]
platforms = ["win-64", "linux-64", "osx-64"]
[environments]
common = { features = ["common"], no-default-feature = true }
prod = { features = ["prod", "common"], no-default-feature = true }
dev = { features = ["dev", "common"], no-default-feature = true }
lint = { features = ["lint"], no-default-feature = true }
tests = { features = ["tests", "common"], no-default-feature = true }
[feature.lint.dependencies]
ruff = "*"
black = "*"
[feature.common.dependencies]
# Build deps
cmake = "==3.30.5"
ninja = "*"
swig = "*"
c-compiler = "*"
cxx-compiler = "*"
# Runtime deps
python = "3.12.*"
libboost-devel = "*"
occt = { version = "*", build = "*novtk*" }
cgal-cpp = "*"
numpy = "*"
lark = "*"
hdf5 = "*"
eigen = "*"
mpfr = "*"
gmp = "*"
nlohmann_json = "*"
zlib = "*"
# Not strictly necessary
pythonocc-core = "*"
[feature.tests.dependencies]
pytest = "*"
shapely = "*"
tabulate = "*"
isodate = "*"
python-dateutil = "*"
xmlschema = "*"
xsdata = "*"
lxml = "*"
networkx = "*"
[feature.common.target.win-64.dependencies]
vs2022_win-64 = "*"
#vs_win-64 = "*" # Visual Studio
#vswhere = "*" # Visual Studio
[feature.common.tasks]
init-submodules = { cmd = "git submodule update --init --recursive", outputs =["$PIXI_PROJECT_ROOT/src/svgfill/3rdparty/svgpp/*"]}
[feature.prod.target.win-64.tasks]
configure-release = { cmd = ["cmake", "--preset", "win-release", "-B", "build/win-release", "cmake"], description = "Configure the project", depends-on=[{ task="init-submodules", environment = "common" }] }
build-release = { cmd = ["cmake", "--build", "build/win-release", "--config", "Release"], description = "Build the project" }
[feature.dev.target.win-64.tasks]
configure-debug = { cmd = ["cmake", "--preset", "win-debug", "-B", "build/win-debug", "cmake"], description = "Configure the project", depends-on=[{ task="init-submodules", environment = "common" }], outputs=["build/win-debug/CMakeCache.txt"] }
build-debug = { cmd = ["cmake", "--build", "build/win-debug", "--config", "Debug"], description = "Build the project", depends-on = ["configure-debug"] }
install-debug = { cmd = ["cmake", "--install", "build/win-debug", "--config", "Debug"], description = "Install the project" } # Optionally Install files to your desired env using --prefix
vsdebug = { cmd = ["python"], description = "Run a python script with vs debugger attached" }
[feature.tests.tasks]
configure-test = { cmd = ["cmake", "--preset", "win-test", "-B", "build/win-test", "cmake"], description = "Configure the project", depends-on=[{ task="init-submodules", environment = "common" }], outputs=["build/win-test/CMakeCache.txt"] }
build-test = { cmd = ["cmake", "--build", "build/win-test", "--config", "Release"], description = "Build the project", depends-on = ["configure-test"], outputs=["build/win-test/IfcGeom.lib"] }
install-test = { cmd = ["cmake", "--install", "build/win-test", "--config", "Release"], description = "Install the project", depends-on = ["build-test"] } # Optionally Install files to your desired env using --prefix
test = { cmd = "pytest .", cwd="src/ifcopenshell-python/test", depends-on=["install-test"], env = {PYTHONPATH="$PIXI_PROJECT_ROOT/src/ifcpatch"}}
[feature.lint.tasks]
lint = { cmd = "ruff check && black --diff --check ."}
[feature.common.target.win-64.activation]
#scripts = ["cmake/activate.bat"]
+32
View File
@@ -0,0 +1,32 @@
There are two ways to build pyodide ifcopenshell Python wrapper wheel.
1. Using pyodide build system (`build_pyodide.yml` does it):
- install prebuilt pyodide build and emscripten environment (see `build_pyodide.sh`)
- clone IfcOpenShell to `IfcOpenShell` folder
- create `packages/ifcopenshell` folder that will be used by pyodide build system
- from `IfcOpenShell` move building recipe `pyodide/meta.yaml` to `packages/ifcopenshell`
- run `pyodide build-recipes ifcopenshell --install`, it will
- execute `meta.yaml` recipe - it will:
- copy IfcOpenShell source to build folder `packages/ifcopenhell/build/ifcopenshell-0.8.0`
- build ifcopenshell and its dependencies
- note that rerunning `pyodide build-recipes` will remove previous build folder and rebuild all dependencies.
The way to avoid it, if build fails, is to use `pyodide build-recipes-no-deps ifcopenshell --continue` instead.
- run `setup.py` in `IfcOpenShell` root, producing a wheel in `IfcOpenShell/dist`
- copy that wheel to `packages/ifcopenshell/dist`
- `--install` it to current build envrionment
- copy the wheel next to `dist` folder (in root directory, next to `packages`)
- add wheel to `dist/pyodide-lock.json`
2. Build it outside of pyodide build system.
Building inside pyodide build system should be preferred, option to build it outside is useful for debugging purposes,
since it's pure cmake without any additional moving parts.
- setup pyodide environment, see above
- clone IfcOpenShell repo next to it to `IfcOpenShell` folder
- run `python nix/build-all.py -wasm -py-313` in `IfcOpenShell`
- it will produce Python package in `IfcOpenShell/ifcopenshell`
- run `pyodide build`
- it will produce a wheel in `IfcOpenShell/dist`
+36
View File
@@ -0,0 +1,36 @@
#!/usr/bin/bash
set -ex
# Install uv.
curl -LsSf https://astral.sh/uv/install.sh | sh
uv venv --python 3.13
source .venv/bin/activate
# Install pyodide cross build environment.
# Instructions: https://pyodide.org/en/stable/development/building-packages.html
uv pip install pyodide-build
# `uv run` is required, so xbuildenv would skip using `pip`.
uv run pyodide xbuildenv install
# Emscripten doesn't come with xbuildenv.
git clone https://github.com/emscripten-core/emsdk
pushd emsdk
PYODIDE_EMSCRIPTEN_VERSION=$(pyodide config get emscripten_version)
./emsdk install ${PYODIDE_EMSCRIPTEN_VERSION}
./emsdk activate ${PYODIDE_EMSCRIPTEN_VERSION}
source emsdk_env.sh
which emcc
popd
mkdir -p packages/ifcopenshell
VERSION=`cat IfcOpenShell/VERSION`
cp IfcOpenShell/pyodide/meta.yaml packages/ifcopenshell
sed -i s/0.8.0/$VERSION/g packages/ifcopenshell/meta.yaml
# Use custom build ifcopenshell directory in build-all to make caching simpler
# Otherwise pyodide build path typically includes package version, so cached cmake configs might break.
export BUILD_DIR=`readlink -f ifcopenshell_build`
# Use build-recipes-no-deps first, so logs would be printed to stdout.
pyodide build-recipes-no-deps ifcopenshell
pyodide build-recipes ifcopenshell --install
+64
View File
@@ -0,0 +1,64 @@
"""
Cache built dependencies for builds.
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.
Usage: python cache_dependencies.py [pack|unpack]
"""
import tarfile
import sys
from pathlib import Path
from typing import Literal
CACHE_PREFIX = "cache-"
def get_install_dir() -> Path:
for data in Path.cwd().glob("*/*/install"):
return data
raise Exception("No install dir found")
def pack_dependencies(install_dir: Path) -> None:
# Process each install_dir
for dependency_path in install_dir.iterdir():
if not dependency_path.is_dir():
continue
dependency_name = dependency_path.name
tar_path = install_dir / f"{CACHE_PREFIX}{dependency_name}.tar.gz"
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)
print(f"Created cache: '{tar_path}'")
def unpack_dependencies(install_dir: Path) -> None:
# `filter` argument was fully introduced in 3.12
# and results in deprecation warnings in 3.12-3.13, if not provided.
tar_filter: dict[Literal["filter"], Literal["data"]] = (
{"filter": "data"} if bool(sys.version_info >= (3, 12)) else {}
)
for tar_path in install_dir.glob(f"{CACHE_PREFIX}*.tar.gz"):
with tarfile.open(tar_path, "r:gz") as tar:
tar.extractall(path=install_dir, **tar_filter)
print(f"Extracted cache: '{tar_path.name}'.")
if __name__ == "__main__":
if len(sys.argv) != 2 or (action := sys.argv[1].lower()) not in ("pack", "unpack"):
print(__doc__)
sys.exit(1)
install_dir = get_install_dir()
print(f"Found install dir: '{install_dir}'")
if action == "pack":
pack_dependencies(install_dir)
else:
unpack_dependencies(install_dir)
+2 -3
View File
@@ -3,13 +3,12 @@ package:
version: 0.8.0
source:
# meta.yaml is placed as `packages/ifcopenshell/meta.yaml`.
path: ../../IfcOpenShell
build:
script: |
BUILD_CFG=Release python nix/build-all.py --without-hdf5 --without-opencollada --without-swig --without-pcre -v --wasm --py313 IfcOpenShell-Python
mv package/ifcopenshell .
cp pyodide/setup.py .
BUILD_CFG=Release python nix/build-all.py -v --wasm --py313
about:
home: http://ifcopenshell.org
+45 -9
View File
@@ -1,11 +1,47 @@
from setuptools import setup, find_packages
# setup.py is getting deprecated, but we still use it,
# because `tool.setuptools.ext-modules` is still experimental in pyproject.toml
# and we need it to get the wheel suffix right.
import os
from pathlib import Path
setup(name='ifcopenshell',
version='0.8.0',
description='IfcOpenShell is an open source (LGPL) software library for working with the Industry Foundation Classes (IFC) file format.',
author='Thomas Krijnen',
author_email='thomas@aecgeeks.com',
url='http://ifcopenshell.org',
packages=find_packages(),
package_data={'': ['*.so', '*.json']},
import tomllib
from setuptools import Extension, find_packages, setup
REPO_FOLDER = Path(__file__).parent
def get_version() -> str:
if "PKG_VERSION" in os.environ:
# Inside pyodide build environment.
return os.environ["PKG_VERSION"]
return (REPO_FOLDER / "VERSION").read_text().strip()
# Read dependencies from pyproject.toml
def get_dependencies() -> list[str]:
pyproject_toml = REPO_FOLDER / "src" / "ifcopenshell-python" / "pyproject.toml"
pyproject_data = tomllib.loads(pyproject_toml.read_text())
dependencies = pyproject_data["project"]["dependencies"]
return dependencies
setup(
name="ifcopenshell",
version=get_version(),
description=(
"IfcOpenShell is an open source (LGPL) software library "
"for working with the Industry Foundation Classes (IFC) file format."
),
author="Thomas Krijnen",
author_email="thomas@aecgeeks.com",
url="https://ifcopenshell.org",
install_requires=get_dependencies(),
packages=find_packages(include=["ifcopenshell", "ifcopenshell.*"]),
package_data={
# "*.so" is needed to include prebuilt binary extension. Otherwise it would try to build it and fail.
"ifcopenshell": ["util/schema/*.json", "util/schema/*.ifc", "*.so"],
"": ["*.json", "*.ifc"],
},
# Has to provide extension to get the correct wheel suffix.
ext_modules=[Extension("ifcopenshell._ifcopenshell_wrapper", sources=[])],
)
+27
View File
@@ -0,0 +1,27 @@
from pathlib import Path
WHEEL_FILENAME = next(
p.name for p in (Path.cwd() / "pyodide").iterdir() if p.name.startswith("ifcopenshell-") and p.suffix == ".whl"
)
def test_ifcopenshell_import(selenium):
selenium.load_package("micropip")
# Important to test it with `micropip.install`
# without any dependencies loaded to ensure micropip will load them automatically.
selenium.run_async(
f"""
import micropip
await micropip.install(f"./{WHEEL_FILENAME}")
import ifcopenshell
ifc_file = ifcopenshell.file()
wall = ifc_file.create_entity("IfcWall")
wall1 = ifc_file.by_type("IfcWall")[0]
print(wall, wall1)
assert wall == wall1, "Wall entity doesn't match"
wall.Name = "Test"
assert wall.Name == "Test", f"Entity name wasn't changed: {{wall}}"
print(wall)
"""
)
+18 -6
View File
@@ -1,6 +1,9 @@
[tool.black]
line-length = 120
include = "src/.*.pyi?$"
include = '''
src/.*.pyi?$
|nix/.*.pyi?$
'''
extend-exclude = '''
src/ifcopenshell-python/ifcopenshell/express/*
|src/ifcopenshell-python/ifcopenshell/mvd/*
@@ -16,8 +19,6 @@ extend-exclude = '''
reportInvalidTypeForm = false
disableBytesTypePromotions = true
reportUnnecessaryTypeIgnoreComment = true
# Just to add a quick insert of `# pyright: ignore[xxx]` comments in Pylance.
enableTypeIgnoreComments = false
# Define here general ruff settings,
# then they will be inherited projects .toml files.
@@ -37,6 +38,7 @@ exclude = [
"src/ifc2ca/templates",
]
[tool.ruff.lint]
preview = true
select = [
# Default Ruff rules.
# "E4", # imports
@@ -47,17 +49,27 @@ select = [
"FA", # future annotations
"UP", # pyupgrade
"RUF015", # next() > list_comprehension[0]
"RUF022", # sort __all__
]
ignore = [
"FA100", # Conflicts with Blender using annotations for props definitions.
# Maybe will enable later:
"UP007", # Optional to X | Y
"UP045", # Optional to X | None
"UP015", # Unnecessary mode argument
"UP028", # yield for -> yield from
"UP030", # implicit references for positional format fields
"UP031", # Replace % with .format
"UP032", # Replace .format with f-string
# Deprecated Ruff rules.
"UP038", # Use X | Y in isinstance
]
[tool.poe.tasks]
ruff-main = "ruff check --extend-exclude nix/build-all.py"
# It's actually Python 3.6, but ruff only supports 3.7+, but it should do.
ruff-old = "ruff check nix/build-all.py --target-version py37"
ruff.sequence = ["ruff-main", "ruff-old"]
black = "black ."
format.sequence = ["black", "ruff-main", "ruff-old"]
+3 -12
View File
@@ -6,7 +6,7 @@ from numpy.typing import NDArray
def camera_vectors_from_element_placement(
elem_placement: NDArray[np.float64],
) -> tuple[NDArray[np.float64], NDArray[np.float64], NDArray[np.float64]]:
) -> tuple[list[float], list[float], list[float]]:
"""
Calculate the vectors of a camera pointing to an element.
@@ -22,7 +22,7 @@ def camera_vectors_from_element_placement(
def camera_vectors_from_target_position(
target_position: NDArray[np.float64], offset: Optional[NDArray[np.float64]] = None
) -> tuple[NDArray[np.float64], NDArray[np.float64], NDArray[np.float64]]:
) -> tuple[list[float], list[float], list[float]]:
"""
Calculate the vectors of a camera pointing to a target point.
@@ -38,16 +38,7 @@ def camera_vectors_from_target_position(
camera_direction = unit_vector(-camera_offset) # pylint: disable=invalid-unary-operand-type
camera_right = unit_vector(np.cross(np.array([0.0, 0.0, 1.0]), camera_direction))
camera_up = unit_vector(np.cross(camera_direction, camera_right))
return camera_position, camera_direction, camera_up
# rotation_transform = np.eye(4)
# rotation_transform[0, :3] = camera_right
# rotation_transform[1, :3] = camera_up
# rotation_transform[2, :3] = camera_direction
# translation_transform = np.eye(4)
# translation_transform[:3, -1] = -camera_position
# look_at_transform = np.matmul(rotation_transform, translation_transform)
# mat = np.linalg.inv(look_at_transform)
# return camera_position, -mat[:3, 2], mat[:3, 1]
return camera_position.tolist(), camera_direction.tolist(), camera_up.tolist()
def unit_vector(v: NDArray[np.float64]) -> NDArray[np.float64]:
+12 -12
View File
@@ -36,20 +36,10 @@ from bcf.v2.model.visinfo import (
__all__ = [
"BimSnippet",
"Comment",
"CommentViewpoint",
"Header",
"HeaderFile",
"Markup",
"Topic",
"TopicDocumentReference",
"TopicRelatedTopic",
"ViewPoint",
"Project",
"ProjectExtension",
"Version",
"BitmapFormat",
"ClippingPlane",
"Comment",
"CommentViewpoint",
"Component",
"ComponentColoring",
"ComponentColoringColor",
@@ -58,10 +48,20 @@ __all__ = [
"ComponentVisibilityExceptions",
"Components",
"Direction",
"Header",
"HeaderFile",
"Line",
"Markup",
"OrthogonalCamera",
"PerspectiveCamera",
"Point",
"Project",
"ProjectExtension",
"Topic",
"TopicDocumentReference",
"TopicRelatedTopic",
"Version",
"ViewPoint",
"ViewSetupHints",
"VisualizationInfo",
"VisualizationInfoBitmap",
+2
View File
@@ -192,6 +192,8 @@ class TopicHandler:
bcf_zip: The BCF zip file to save to.
"""
topic_dir = self.guid
# simulating directory creation (ZipFile in python < 3.11 doesn't have mkdir)
destination_zip.writestr(f"{topic_dir}/", "")
self._save_xml(destination_zip, self._markup, "markup.bcf")
self._save_viewpoints(destination_zip, topic_dir)
self._save_bim_snippet(destination_zip)
+2 -4
View File
@@ -319,9 +319,7 @@ def build_viewpoint(element: entity_instance) -> mdl.VisualizationInfo:
ifc_file = element.wrapped_data.file
unit_scale = ifcopenshell.util.unit.calculate_unit_scale(ifc_file)
elem_placement = ifcopenshell.util.placement.get_local_placement(element.ObjectPlacement)
elem_placement[0][3] *= unit_scale
elem_placement[1][3] *= unit_scale
elem_placement[2][3] *= unit_scale
elem_placement[:3, 3] *= unit_scale
return mdl.VisualizationInfo(
guid=str(uuid.uuid4()),
@@ -381,7 +379,7 @@ def build_camera(elem_placement: NDArray[np.float64]) -> mdl.PerspectiveCamera:
def build_camera_from_vectors(
camera_position: NDArray[np.float64], camera_dir: NDArray[np.float64], camera_up: NDArray[np.float64]
camera_position: list[float], camera_dir: list[float], camera_up: list[float]
) -> mdl.PerspectiveCamera:
"""
Return a BCF camera for an IFC element placement matrix.
+30 -30
View File
@@ -55,40 +55,12 @@ from bcf.v3.model.visinfo import (
)
__all__ = [
"Document",
"DocumentInfo",
"DocumentInfoDocuments",
"Extensions",
"ExtensionsPriorities",
"ExtensionsSnippetTypes",
"ExtensionsStages",
"ExtensionsTopicLabels",
"ExtensionsTopicStatuses",
"ExtensionsTopicTypes",
"ExtensionsUsers",
"BimSnippet",
"Comment",
"CommentViewpoint",
"DocumentReference",
"File",
"Header",
"HeaderFiles",
"Markup",
"Topic",
"TopicComments",
"TopicDocumentReferences",
"TopicLabels",
"TopicReferenceLinks",
"TopicRelatedTopics",
"TopicRelatedTopicsRelatedTopic",
"TopicViewpoints",
"ViewPoint",
"Project",
"ProjectInfo",
"Version",
"Bitmap",
"BitmapFormat",
"ClippingPlane",
"Comment",
"CommentViewpoint",
"Component",
"ComponentColoring",
"ComponentColoringColor",
@@ -98,10 +70,38 @@ __all__ = [
"ComponentVisibilityExceptions",
"Components",
"Direction",
"Document",
"DocumentInfo",
"DocumentInfoDocuments",
"DocumentReference",
"Extensions",
"ExtensionsPriorities",
"ExtensionsSnippetTypes",
"ExtensionsStages",
"ExtensionsTopicLabels",
"ExtensionsTopicStatuses",
"ExtensionsTopicTypes",
"ExtensionsUsers",
"File",
"Header",
"HeaderFiles",
"Line",
"Markup",
"OrthogonalCamera",
"PerspectiveCamera",
"Point",
"Project",
"ProjectInfo",
"Topic",
"TopicComments",
"TopicDocumentReferences",
"TopicLabels",
"TopicReferenceLinks",
"TopicRelatedTopics",
"TopicRelatedTopicsRelatedTopic",
"TopicViewpoints",
"Version",
"ViewPoint",
"ViewSetupHints",
"VisualizationInfo",
"VisualizationInfoBitmaps",
+2
View File
@@ -179,6 +179,8 @@ class TopicHandler:
bcf_zip: The BCF zip file to save to.
"""
topic_dir = self.guid
# simulating directory creation (ZipFile in python < 3.11 doesn't have mkdir)
destination_zip.writestr(f"{topic_dir}/", "")
self._save_xml(destination_zip, self._markup, "markup.bcf")
self._save_viewpoints(destination_zip, topic_dir)
self._save_bim_snippet(destination_zip)
+2 -4
View File
@@ -319,9 +319,7 @@ def build_viewpoint(element: entity_instance) -> mdl.VisualizationInfo:
ifc_file = element.wrapped_data.file
unit_scale = ifcopenshell.util.unit.calculate_unit_scale(ifc_file)
elem_placement = ifcopenshell.util.placement.get_local_placement(element.ObjectPlacement)
elem_placement[0][3] *= unit_scale
elem_placement[1][3] *= unit_scale
elem_placement[2][3] *= unit_scale
elem_placement[:3, 3] *= unit_scale
return mdl.VisualizationInfo(
guid=str(uuid.uuid4()),
@@ -381,7 +379,7 @@ def build_camera(elem_placement: NDArray[np.float64]) -> mdl.PerspectiveCamera:
def build_camera_from_vectors(
camera_position: NDArray[np.float64], camera_dir: NDArray[np.float64], camera_up: NDArray[np.float64]
camera_position: list[float], camera_dir: list[float], camera_up: list[float]
) -> mdl.PerspectiveCamera:
"""
Return a BCF camera for an IFC element placement matrix.
+4 -2
View File
@@ -87,7 +87,7 @@ BLENDER_PLATFORM:=windows-x64
endif
# Current build commit hash.
OLD:=ec13294
OLD:=6924012
.PHONY: bump
bump:
ifndef NEW
@@ -127,7 +127,7 @@ endif
cd build && . env/$(VENV_ACTIVATE) && $(PIP) download GitPython --dest=./wheels
# Provides audio playback for costing
# This is a REALLY IMPORTANT feature
cd build && . env/$(VENV_ACTIVATE) && $(PIP) wheel git+https://github.com/Andrej730/aud.git --wheel-dir=./wheels
cd build && . env/$(VENV_ACTIVATE) && $(PIP) wheel git+https://github.com/zdhoward/aud --wheel-dir=./wheels
# IfcOpenShell dependency - support for new typing features
cd build && . env/$(VENV_ACTIVATE) && $(PIP) download typing_extensions --dest=./wheels
# Required by IfcCSV
@@ -192,6 +192,8 @@ else ifeq ($(PLATFORM), macos)
else
cd build && . env/$(VENV_ACTIVATE) && $(PIP) download pyradiance $(PYPI_PLATFORM) --python-version $(PYPI_VERSION) --implementation $(PYPI_IMP) --only-binary=:all: --dest=./wheels
endif
# Required by ifctester web ui.
cd build && . env/$(VENV_ACTIVATE) && $(PIP) download flask $(PYPI_PLATFORM) --python-version $(PYPI_VERSION) --implementation $(PYPI_IMP) --only-binary=:all: --dest=./wheels
# jQuery is required for web UI functionality
cd build/bonsai/bim/data/webui/static/js/ && wget https://cdn.jsdelivr.net/npm/jquery@3.7.1/dist/jquery.min.js
+6 -4
View File
@@ -97,7 +97,6 @@ for name in modules.keys():
classes = [
operator.AddIfcFile,
operator.BIM_OT_add_section_plane,
operator.BIM_OT_delete_object,
operator.BIM_OT_remove_section_plane,
@@ -106,9 +105,12 @@ classes = [
operator.BIM_OT_select_object,
operator.BIM_OT_show_description,
operator.BIM_OT_multiple_file_selector,
operator.BIM_OT_attribute_add_subitem,
operator.BIM_OT_attribute_remove_subitem,
operator.ClippingPlaneCutWithCappings,
operator.CloseBlendWarning,
operator.CloseError,
operator.CreateMacBonsaiApp,
operator.CopyTextToClipboard,
operator.EditBlenderCollection,
operator.FileAssociate,
@@ -117,7 +119,6 @@ classes = [
operator.OpenUpstream,
operator.OpenUri,
operator.ReloadIfcFile,
operator.RemoveIfcFile,
operator.RevertClippingPlaneCut,
operator.SelectDir,
operator.SelectIfcFile,
@@ -127,15 +128,16 @@ classes = [
operator.ShowSystemInfo,
prop.StrProperty,
operator.BIM_OT_enum_property_search, # /!\ Register AFTER prop.StrProperty
operator.BIM_OT_attribute_search_values,
prop.ObjProperty,
prop.MultipleFileSelect,
prop.Attribute,
prop.ISODuration,
prop.BIMAreaProperties,
prop.BIMTabProperties,
prop.BIMProperties,
prop.IfcParameter,
prop.PsetQto,
prop.GlobalId,
prop.BIMObjectProperties,
prop.BIMCollectionProperties,
prop.BIMMeshProperties,
@@ -145,7 +147,7 @@ classes = [
prop.BIMSnapGroups,
ui.BIM_UL_clipping_plane,
ui.BIM_UL_generic,
ui.BIM_UL_topics,
ui.DocPreferences,
ui.BIM_ADDON_preferences,
# Tabs panel
ui.BIM_PT_tabs,
File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 69 KiB

After

Width:  |  Height:  |  Size: 70 KiB

@@ -499,6 +499,10 @@
0.05087608844041824,
0.05087608844041824
],
"scene.eevee.use_shadows": true,
"scene.eevee.shadow_ray_count": 1,
"scene.eevee.shadow_step_count": 6,
"scene.eevee.shadow_resolution_scale": 1.0,
"scene.render.bake_bias": 0.0010000000474974513,
"scene.render.bake_margin": 16,
"scene.render.bake_margin_type": "ADJACENT_FACES",
Binary file not shown.

After

Width:  |  Height:  |  Size: 301 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 215 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 336 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 217 B

@@ -13,10 +13,10 @@ DATA;
#6=IFCSIMPLEPROPERTYTEMPLATE('0AK5C2UpL4$eaac2LszAx$',$,'HasUnderlay','',.P_SINGLEVALUE.,'IfcBoolean',$,$,$,$,$,.READWRITE.);
#7=IFCSIMPLEPROPERTYTEMPLATE('2j2ZEZR8X5tONm7kli5hM6',$,'HasLinework','',.P_SINGLEVALUE.,'IfcBoolean',$,$,$,$,$,.READWRITE.);
#8=IFCSIMPLEPROPERTYTEMPLATE('1ttChRysH9UuEX2FeMj5Hu',$,'HasAnnotation','',.P_SINGLEVALUE.,'IfcBoolean',$,$,$,$,$,.READWRITE.);
#9=IFCSIMPLEPROPERTYTEMPLATE('2NPPxuABv1huDTVh32TFgw',$,'GlobalReferencing','',.P_SINGLEVALUE.,'IfcBoolean',$,$,$,$,$,.READWRITE.);
#9=IFCSIMPLEPROPERTYTEMPLATE('2NPPxuABv1huDTVh32TFgw',$,'GlobalReferencing','Whether or not this drawing can be referenced in other drawings.',.P_SINGLEVALUE.,'IfcBoolean',$,$,$,$,$,.READWRITE.);
#10=IFCSIMPLEPROPERTYTEMPLATE('10hT_1zrzEbRRKMXYAWvtD',$,'Metadata','Comma separated list of selector expressions to evaluate for each drawing elementand add results to their ''class'' attribute.\X2\000A\X0\E.g. ''Name, id'' would add to ''class'' value similar to ''Name-Wall id-1220''.\X2\000A\X0\Then it can be used to applied css styles based on the resulting class.\X2\000A\X0\If attribute is not present on the element, then it won''t be added to it''s ''class''.',.P_SINGLEVALUE.,'IfcText',$,$,$,$,$,.READWRITE.);
#11=IFCSIMPLEPROPERTYTEMPLATE('3Z0BXPSG5CWgtI33ioV7aj',$,'Include','Selector expression to include ifc elements in the drawing',.P_SINGLEVALUE.,'IfcText',$,$,$,$,$,.READWRITE.);
#12=IFCSIMPLEPROPERTYTEMPLATE('1RVts_g3PAw98PJA2yL3bO',$,'Exclude','Selector expression to exclude ifc elements in the drawing',.P_SINGLEVALUE.,'IfcText',$,$,$,$,$,.READWRITE.);
#11=IFCSIMPLEPROPERTYTEMPLATE('3Z0BXPSG5CWgtI33ioV7aj',$,'Include','Selector expression to include elements in the drawing',.P_SINGLEVALUE.,'IfcText',$,$,$,$,$,.READWRITE.);
#12=IFCSIMPLEPROPERTYTEMPLATE('1RVts_g3PAw98PJA2yL3bO',$,'Exclude','Selector expression to exclude elements in the drawing',.P_SINGLEVALUE.,'IfcText',$,$,$,$,$,.READWRITE.);
#13=IFCSIMPLEPROPERTYTEMPLATE('0c1$8NpYDEaBiJrj16jHIo',$,'Stylesheet','',.P_SINGLEVALUE.,'IfcText',$,$,$,$,$,.READWRITE.);
#14=IFCSIMPLEPROPERTYTEMPLATE('3mRF52q81FQB$h4oTh7M45',$,'Markers','',.P_SINGLEVALUE.,'IfcText',$,$,$,$,$,.READWRITE.);
#15=IFCSIMPLEPROPERTYTEMPLATE('1rhr_0N3LDtuORcEJP0KXM',$,'Symbols','',.P_SINGLEVALUE.,'IfcText',$,$,$,$,$,.READWRITE.);
@@ -5,10 +5,10 @@ FILE_NAME('Psets_BBIM_Annotation.ifc','2020-01-01T00:00:00',$,$,'Psets_BBIM_Anno
FILE_SCHEMA(('IFC4'));
ENDSEC;
DATA;
#1=IFCPROPERTYSETTEMPLATE('3VuPUwdCD2Qx3XDDRs0R1N',$,'EPset_Annotation','',.PSET_TYPEDRIVENOVERRIDE.,'IfcAnnotation,IfcTypeProduct',(#2,#3,#4,#29));
#1=IFCPROPERTYSETTEMPLATE('3VuPUwdCD2Qx3XDDRs0R1N',$,'EPset_Annotation','',.PSET_TYPEDRIVENOVERRIDE.,'IfcAnnotation,IfcTypeProduct',(#4,#33,#29,#32,#3,#2));
#2=IFCSIMPLEPROPERTYTEMPLATE('2P7JN79n96Q9pElZ83LKe4',$,'ZIndex','',.P_SINGLEVALUE.,'IfcInteger',$,$,$,$,$,.READWRITE.);
#3=IFCSIMPLEPROPERTYTEMPLATE('1Wpx_r2xj1_9w5JpI0QRJy',$,'Symbol','',.P_SINGLEVALUE.,'IfcLabel',$,$,$,$,$,.READWRITE.);
#4=IFCSIMPLEPROPERTYTEMPLATE('3q0oxMUKP47vZ4jnyG$dDb',$,'Classes','Classes separarated by spaces that end up in classes for this element in svg. Can be used to specify the text font size: small - 1.8mm; regular - 2.5mm; large - 3.5mm; header - 5mm; title - 7mm. By default regular size is used.',.P_SINGLEVALUE.,'IfcLabel',$,$,$,$,$,.READWRITE.);
#4=IFCSIMPLEPROPERTYTEMPLATE('3q0oxMUKP47vZ4jnyG$dDb',$,'Classes','Classes separated by spaces that end up in classes for this element in svg. Can be used to specify the text font size: small - 1.8mm; regular - 2.5mm; large - 3.5mm; header - 5mm; title - 7mm. By default regular size is used.',.P_SINGLEVALUE.,'IfcLabel',$,$,$,$,$,.READWRITE.);
#5=IFCPROPERTYSETTEMPLATE('0iKwujnQL9IevVQato8f7Z',$,'BBIM_Batting','',.PSET_TYPEDRIVENOVERRIDE.,'IfcAnnotation/BATTING,IfcTypeProduct',(#6,#7));
#6=IFCSIMPLEPROPERTYTEMPLATE('0t2LEesGT1QRQtrIZUAR8L',$,'Thickness','Batting thickness',.P_SINGLEVALUE.,'IfcPositiveLengthMeasure',$,$,$,$,$,.READWRITE.);
#7=IFCSIMPLEPROPERTYTEMPLATE('082PndS6v2kBOiJoSboMnh',$,'Reverse pattern direction','Reverse batting pattern (swap starting and ending points)',.P_SINGLEVALUE.,'IfcBoolean',$,$,$,$,$,.READWRITE.);
@@ -36,5 +36,7 @@ DATA;
#29=IFCSIMPLEPROPERTYTEMPLATE('2pJmUDpB50VBdCOib1zcJJ',$,'Newline_At','',.P_SINGLEVALUE.,'IfcInteger',$,$,$,$,$,.READWRITE.);
#30=IFCSIMPLEPROPERTYTEMPLATE('2TJn72t_v2cvBUG916Dpev',$,'CustomUnit','Dimension''s custom unit',.P_ENUMERATEDVALUE.,'IfcText',$,#31,$,$,$,.READWRITE.);
#31=IFCPROPERTYENUMERATION('CustomUnit',(IFCTEXT('Feet and Inches - Fractional'),IFCTEXT('Feet - Decimal'),IFCTEXT('Inches - Fractional'),IFCTEXT('Inches - Decimal'),IFCTEXT('Meters'),IFCTEXT('Decimeters'),IFCTEXT('Centimeters'),IFCTEXT('Millimeters')),$);
#32=IFCSIMPLEPROPERTYTEMPLATE('0gjJzDYBX8P85qn1xcAOOo',$,'Reverse_List','',.P_SINGLEVALUE.,'IfcBoolean',$,$,$,$,$,.READWRITE.);
#33=IFCSIMPLEPROPERTYTEMPLATE('22TrcxF8jFNB4buSmzjGEF',$,'List_Separator','',.P_SINGLEVALUE.,'IfcText',$,$,$,$,$,.READWRITE.);
ENDSEC;
END-ISO-10303-21;
@@ -0,0 +1 @@
SVG [mustache](https://mustache.github.io/) templates that will be used for sheets and fill be filled with infromation from the sheet's IfcDocumentInformation attributes (e.g. Identification, Name, Revision, etc).
+19 -5
View File
@@ -36,6 +36,7 @@ from bonsai.bim.ifc import IfcStore
from mathutils import Vector
from typing import Union
from logging import Logger
from math import radians
class IfcExporter:
@@ -74,12 +75,12 @@ class IfcExporter:
json.dump(jsonData, outfile, indent=None if self.ifc_export_settings.json_compact else 4)
def set_header(self):
self.file.wrapped_data.header.file_name.name = os.path.basename(self.ifc_export_settings.output_file)
self.file.wrapped_data.header.file_name.time_stamp = (
self.file.header.file_name.name = os.path.basename(self.ifc_export_settings.output_file)
self.file.header.file_name.time_stamp = (
datetime.datetime.utcnow().replace(tzinfo=datetime.UTC).astimezone().replace(microsecond=0).isoformat()
)
self.file.wrapped_data.header.file_name.preprocessor_version = "IfcOpenShell {}".format(ifcopenshell.version)
self.file.wrapped_data.header.file_name.originating_system = "{} {}".format(
self.file.header.file_name.preprocessor_version = "IfcOpenShell {}".format(ifcopenshell.version)
self.file.header.file_name.originating_system = "{} {}".format(
self.get_application_name(), tool.Blender.get_bonsai_version()
)
@@ -104,7 +105,16 @@ class IfcExporter:
def sync_object_placement(self, obj: bpy.types.Object) -> Union[ifcopenshell.entity_instance, None]:
element = self.file.by_id(tool.Blender.get_object_bim_props(obj).ifc_definition_id)
if tool.Geometry.is_scaled(obj):
# Handle camera scales specially
if obj.type == "CAMERA":
# Check if this is a reflected ceiling plan camera
camera = tool.Ifc.get_entity(obj)
if ifcopenshell.util.element.get_pset(camera, "EPset_Drawing", "TargetView") == "REFLECTED_PLAN_VIEW":
# Ensure reflected ceiling cameras have the correct scale
if obj.scale != (-1, -1, -1):
obj.scale = (-1, -1, -1)
# Skip all other scale handling for cameras
elif tool.Geometry.is_scaled(obj):
bpy.ops.bim.update_representation(obj=obj.name)
# update_representation might not apply scale if the object has openings
# reset it, so let user know that the scale wasn't saved.
@@ -139,6 +149,10 @@ class IfcExporter:
class IfcExportSettings:
"""
Initialize only using `IfcExportSettings.factory()`.
"""
def __init__(self):
self.logger: Logger = None
self.output_file: str = None
+13 -8
View File
@@ -30,7 +30,7 @@ from bonsai.bim.ifc import IfcStore
from bonsai.bim.module.model.data import AuthoringData
from bonsai.bim.module.aggregate.decorator import AggregateDecorator
from bonsai.bim.module.georeference.decorator import GeoreferenceDecorator
from bonsai.bim.module.model.decorator import WallAxisDecorator, SlabDirectionDecorator
from bonsai.bim.module.model.decorator import WallAxisDecorator, SlabDirectionDecorator, BoundingBoxDecorator
from bonsai.bim.module.nest.decorator import NestDecorator
from mathutils import Vector
from math import cos
@@ -219,12 +219,10 @@ def refresh_ui_data():
except AttributeError:
pass
if isinstance(tool.Ifc.get(), ifcopenshell.sqlite):
tool.Ifc.get().clear_cache()
if isinstance(ifc_file := tool.Ifc.get(), ifcopenshell.sqlite):
ifc_file.clear_cache()
props = tool.Drawing.get_document_props()
props.should_draw_decorations = props.should_draw_decorations
if bpy.context.scene.WebProperties.is_connected:
if tool.Web.get_web_props().is_connected:
tool.Web.send_webui_data()
@@ -287,14 +285,17 @@ def get_application(ifc: ifcopenshell.file) -> ifcopenshell.entity_instance:
# Use only main part from the version to avoid flooding advanced users projects with IfcApplications.
version = tool.Blender.get_bonsai_version().split("-")[0]
identifier = f"Bonsai-{version}"
for element in ifc.by_type("IfcApplication"):
if element.ApplicationIdentifier == "Bonsai" and element.Version == version:
if element.ApplicationIdentifier == identifier:
return element
application_developer = next((org for org in ifc.by_type("IfcOrganization") if org.Name == "IfcOpenShell"), None)
application = ifcopenshell.api.owner.add_application(
ifc,
application_developer=application_developer,
version=version,
application_full_name="Bonsai",
application_identifier="Bonsai",
application_identifier=identifier,
)
SettingsCache.APPLICATION_ID = application.id()
SettingsCache.set_file(ifc)
@@ -406,9 +407,13 @@ def load_post(scene):
WallAxisDecorator.install(bpy.context)
if model_props.show_slab_direction:
SlabDirectionDecorator.install(bpy.context)
if model_props.show_bounding_box:
BoundingBoxDecorator.install(bpy.context)
if preferences.should_use_snap and (scene := bpy.context.scene):
# Snapping is off by default in Blender, but in BIM, it's more useful to be on
scene.tool_settings.use_snap = True
# Match default Bonsai snaps
scene.tool_settings.snap_elements_base = {"EDGE", "EDGE_PERPENDICULAR", "VERTEX", "EDGE_MIDPOINT", "FACE"}
tool.Blender.sync_old_preferences()
+110 -26
View File
@@ -27,8 +27,9 @@ import ifcopenshell.util.element
import ifcopenshell.util.unit
from ifcopenshell.util.doc import get_attribute_doc, get_predefined_type_doc, get_property_doc
import bonsai.tool as tool
from types import EllipsisType
from typing import Optional, Any, Union, TYPE_CHECKING
from collections.abc import Callable, Iterable
from collections.abc import Callable, Iterable, Sequence
if TYPE_CHECKING:
import bonsai.bim.prop
@@ -39,6 +40,9 @@ if TYPE_CHECKING:
# - None - property should be imported by default workflow
# - True - setting value for imported attribute should be skipped
# - False - property should be skipped entirely from import
# Second argument is optional,
# because ImportCallback might be called for attributes that are not created by default
# (e.g. IFC entity attributes).
ImportCallback = Callable[[str, Optional[bonsai.bim.prop.Attribute], dict[str, Any]], Union[bool, None]]
# ExportCallback return values:
# - True - property should be skipped entirely from export
@@ -47,36 +51,67 @@ if TYPE_CHECKING:
def draw_attributes(
props: bpy.types.bpy_prop_collection_idprop[Attribute],
props: Union[bpy.types.bpy_prop_collection_idprop[Attribute], Sequence[Attribute]],
layout: bpy.types.UILayout,
copy_operator: Optional[str] = None,
popup_active_attribute: Optional[bonsai.bim.prop.Attribute] = None,
callback: Optional[Callable[[bonsai.bim.prop.Attribute, bpy.types.UILayout], None]] = None,
*,
enable_search: Union[bool, EllipsisType] = ...,
) -> None:
"""Draw editable UI for prop.Attributes.
You can set attribute active in popup with `active_attribute`
meaning you will be able to type into attribute's field without having to click
on it first
:param enable_search: Add search button to string, integer, and float attributes
Possible values:
- ``...`` (default value) -
add search if possible. If it's not possible, there will be no warnings or errors.
- ``True`` - always add search, if it's not possible it will result in errors.
- ``False`` - never add search.
"""
for attribute in props:
row = layout.row(align=True)
if attribute == popup_active_attribute:
row.activate_init = True
draw_attribute(attribute, row, copy_operator)
draw_attribute(attribute, row, copy_operator, enable_search=enable_search)
if callback:
callback(attribute, row)
def draw_attribute(
attribute: bonsai.bim.prop.Attribute, layout: bpy.types.UILayout, copy_operator: Optional[str] = None
attribute: bonsai.bim.prop.Attribute,
layout: bpy.types.UILayout,
copy_operator: Optional[str] = None,
enable_search: Union[bool, EllipsisType] = ...,
) -> None:
value_name = attribute.get_value_name(display_only=True)
if value_name == "enum_value":
prop_with_search(layout, attribute, "enum_value", text=attribute.name)
elif value_name == "filepath_value":
attribute.filepath_value.layout_file_select(layout, filter_glob=attribute.filter_glob, text=attribute.name)
elif attribute.name in ("ScheduleDuration", "ActualDuration", "FreeFloat", "TotalFloat"):
elif value_name == "subitems_values":
col = layout.column()
layout = col.row(align=True)
layout.label(text=f"{attribute.name}:")
data_path = tool.Blender.get_full_data_path(attribute, value_name)
for i, item in enumerate(attribute.subitems_values, 1):
row = col.row(align=True)
row.alignment = "EXPAND"
row.prop(item, "name", text=f"# {i}")
op = row.operator("bim.attribute_remove_subitem", text="", icon="X")
op.data_path = data_path
op.index = i - 1
op = layout.operator("bim.attribute_add_subitem", icon="ADD", text="")
op.data_path = data_path
elif attribute.special_type == "DURATION":
props = tool.Sequence.get_work_schedule_props()
for item in props.durations_attributes:
if item.name == attribute.name:
@@ -96,17 +131,34 @@ def draw_attribute(
text=attribute.display_name,
)
if attribute.is_uri:
if attribute.special_type == "URI":
op = layout.operator("bim.select_uri_attribute", text="", icon="FILE_FOLDER")
op.data_path = attribute.path_from_id("string_value")
op.attribute_data_path = tool.Blender.get_full_data_path(attribute)
elif attribute.special_type in ("DATE", "DATETIME"):
op = layout.operator("bim.datepicker", text="", icon="TIME")
op.target_prop = attribute.path_from_id("string_value")
op.include_time = attribute.special_type == "DATETIME"
if attribute.data_type in ("string", "integer", "float") and (
enable_search is True or (enable_search is ... and attribute.ifc_class)
):
op = layout.operator("bim.attribute_search_values", text="", icon="VIEWZOOM")
op.attribute_name = attribute.name
op.attribute_ifc_class = attribute.ifc_class
op.data_path = tool.Blender.get_full_data_path(attribute, value_name)
op.data_type = attribute.data_type
if attribute.is_optional:
layout.prop(attribute, "is_null", icon="RADIOBUT_OFF" if attribute.is_null else "RADIOBUT_ON", text="")
if attribute.use_explorer_ui:
op = layout.operator("bim.explorer_show_ui_popup", text="", icon="ZOOM_SELECTED")
op.ifc_class = attribute.ifc_class
op.attribute_name = attribute.name
op.data_path = tool.Blender.get_full_data_path(attribute, value_name)
if ifc_id := attribute.get_value():
op.preselect_ifc_id = int(ifc_id)
if attribute.name == "GlobalId":
layout.operator("bim.generate_global_id", icon="FILE_REFRESH", text="")
elif copy_operator:
@@ -115,23 +167,14 @@ def draw_attribute(
def import_attributes(
ifc_class: str,
props: bpy.types.bpy_prop_collection_idprop[Attribute],
data: dict[str, Any],
callback: Optional[ImportCallback] = None,
) -> None:
schema = tool.Ifc.schema()
assert (entity := schema.declaration_by_name(ifc_class).as_entity())
for attribute in entity.all_attributes():
import_attribute(attribute, props, data, callback=callback)
# A more elegant attribute importer signature, intended to supersede import_attributes
def import_attributes2(
element: Union[str, ifcopenshell.entity_instance],
props: bpy.types.bpy_prop_collection_idprop[Attribute],
callback: Optional[ImportCallback] = None,
) -> None:
"""
:param element: Entity or IFC class string.
"""
info: dict[str, Any]
if isinstance(element, str):
assert (entity := tool.Ifc.schema().declaration_by_name(element).as_entity())
attributes = entity.all_attributes()
@@ -153,15 +196,19 @@ def import_attribute(
) -> None:
data_type = ifcopenshell.util.attribute.get_primitive_type(attribute)
# Complex data types (aggregates and entities) are handled only by callback.
if data_type == ("list", "string"):
data_type = "list[string]"
if isinstance(data_type, tuple) or data_type == "entity":
callback(attribute.name(), None, data) if callback else None
return
new: bonsai.bim.prop.Attribute = props.add()
new = props.add()
new.name = attribute.name()
new.is_null = data[attribute.name()] is None
new.is_optional = attribute.optional()
new.data_type = data_type if isinstance(data_type, str) else ""
new.ifc_class = data["type"]
is_handled_by_callback = callback(attribute.name(), new, data) if callback else None
data_type = new.data_type # Allow callback to override data type.
@@ -171,8 +218,9 @@ def import_attribute(
props.remove(len(props) - 1)
elif data_type == "string":
new.string_value = "" if new.is_null else str(data[attribute.name()]).replace("\n", "\\n")
if attribute.type_of_attribute().declared_type().name() == "IfcURIReference":
new.is_uri = True
attribute_type = attribute.type_of_attribute()
if attribute_type._is("IfcURIReference"):
new.special_type = "URI"
elif attribute.type_of_attribute()._is("IfcDate"):
new.special_type = "DATE"
elif attribute.type_of_attribute()._is("IfcDateTime"):
@@ -206,6 +254,12 @@ def import_attribute(
if enum_value is not None:
new.enum_value = enum_value
elif data_type == "list[string]":
value: Union[list[str], None] = data[attribute.name()]
if value:
for item in value:
new.subitems_values.add().name = str(item).replace("\n", "\\n")
add_attribute_description(new, data)
add_attribute_min_max(attribute, new)
@@ -242,7 +296,13 @@ def add_attribute_enum_items_descriptions(
new_enum_description.name = description
def add_attribute_description(attribute_blender: bonsai.bim.prop.Attribute, attribute_ifc=None):
def add_attribute_description(
attribute_blender: bonsai.bim.prop.Attribute,
attribute_ifc: Union[ifcopenshell.entity_instance, None] = None,
) -> None:
"""
:param attribute_ifc: IFC Entity to use as a fallback source of description (using "Description" attribute).
"""
if not attribute_blender.name:
return
version = tool.Ifc.get_schema()
@@ -273,6 +333,16 @@ def export_attributes(
return attributes
def process_exported_entity_attribute(attributes: dict[str, Any], attribute_names: list[str]) -> None:
for attribute_name in attribute_names:
entity_id = attributes[attribute_name]
if entity_id is None:
# Maybe it was removed by now and enum is invalid.
del attributes[attribute_name]
else:
attributes[attribute_name] = tool.Ifc.get().by_id(int(entity_id))
ENUM_ITEMS_DATA = Union[bpy.types.PropertyGroup, bpy.types.ID, bpy.types.Operator, bpy.types.OperatorProperties]
@@ -296,22 +366,35 @@ def prop_with_search(
prop_name: str,
should_click_ok: bool = False,
original_operator_path: Optional[str] = None,
*,
enable_relating_type_suggestions: bool = False,
search_threshold: int = 10,
button_kwargs: Union[dict[str, Any], None] = None,
**kwargs: Any,
) -> bpy.types.UILayout:
"""
Draw a row with enum prop and enum search operator.
Search operator appears only in case if there's more than `search_threshold` items in enum.
:arg button_kwargs: kwargs to pass to ``UILayout.operator()``.
:arg kwargs: kwargs to pass to ``UILayout.prop()``.
:arg enable_relating_type_suggestions: Enable additional suggestions for relating type properties.
:arg search_threshold: Minimum number of enum items required to show search button.
:return: Added row.
"""
# kwargs are layout.prop arguments (text, icon, etc.)
row = layout.row(align=True)
row.prop(data, prop_name, **kwargs)
try:
if len(get_enum_items(data, prop_name, original_operator_path=original_operator_path)) > 10:
if len(get_enum_items(data, prop_name, original_operator_path=original_operator_path)) > search_threshold:
# Magick courtesy of https://blender.stackexchange.com/a/203443/86891
row.context_pointer_set(name="data", data=data)
op = row.operator("bim.enum_property_search", text="", icon="VIEWZOOM")
op = row.operator("bim.enum_property_search", text="", icon="VIEWZOOM", **(button_kwargs or {}))
op.prop_name = prop_name
op.should_click_ok = should_click_ok
op.original_operator_path = original_operator_path or ""
op.enable_relating_type_suggestions = enable_relating_type_suggestions
except TypeError: # Prop is not iterable
pass
return row
@@ -473,6 +556,7 @@ def draw_filter(
elif ifc_filter.type == "query":
row = box.row(align=True)
row.prop(ifc_filter, "name", text="", icon="POINTCLOUD_DATA")
row.prop(ifc_filter, "comparison", text="")
row.prop(ifc_filter, "value", text="")
elif ifc_filter.type == "instance":
row = box.row(align=True)
+61 -21
View File
@@ -64,7 +64,11 @@ class TransactionStep(TypedDict):
class IfcStore:
path: str = ""
"""Should be set only using ``tool.Ifc.set_path``."""
file: Optional[ifcopenshell.file] = None
"""Should be set only using ``tool.Ifc.set``."""
schema: Optional[ifcopenshell.ifcopenshell_wrapper.schema_definition] = None
cache: Optional[ifcopenshell.ifcopenshell_wrapper.HdfSerializer] = None
cache_path: Optional[str] = None
@@ -105,32 +109,45 @@ class IfcStore:
IfcStore.session_files = {}
@staticmethod
def get_file():
def get_file() -> ifcopenshell.file | None:
if IfcStore.file is None:
props = tool.Blender.get_bim_props()
IfcStore.set_path(props.ifc_file)
if IfcStore.path:
try:
IfcStore.load_file(IfcStore.path)
tool.Ifc.after_file_loaded()
except Exception as e:
print(f"Failed to load file {IfcStore.path}. Error details: {e}")
return IfcStore.file
@staticmethod
def set_path(value):
def set_path(value: str) -> None:
IfcStore.path = value
# Interpret relative paths as relative to .blend file.
if IfcStore.path and not os.path.isabs(IfcStore.path):
IfcStore.path = os.path.abspath(os.path.join(bpy.path.abspath("//"), IfcStore.path))
@staticmethod
def get_cache():
def generate_cache_path() -> str:
"""Generate cache path based on the active file and it's path."""
assert IfcStore.file
ifc_key = IfcStore.path + IfcStore.file.header.file_name.time_stamp
ifc_hash = hashlib.md5(ifc_key.encode("utf-8")).hexdigest()
prefs = tool.Blender.get_addon_preferences()
cache_path = os.path.join(prefs.cache_dir, f"{ifc_hash}.h5")
return cache_path
@staticmethod
def get_cache() -> ifcopenshell.geom.serializers.hdf5 | None:
"""Get existing cache for the current file or create a new one.
.h5 cache name reflects IFC filepath and it's current header's timestamp.
"""
if IfcStore.cache is None and IfcStore.path:
props = tool.Blender.get_bim_props()
ifc_key = IfcStore.path + IfcStore.file.wrapped_data.header.file_name.time_stamp
ifc_hash = hashlib.md5(ifc_key.encode("utf-8")).hexdigest()
os.makedirs(props.cache_dir, exist_ok=True)
IfcStore.cache_path = os.path.join(props.cache_dir, f"{ifc_hash}.h5")
cache_path = IfcStore.generate_cache_path()
os.makedirs(os.path.dirname(cache_path), exist_ok=True)
IfcStore.cache_path = cache_path
cache_path = Path(IfcStore.cache_path)
cache_settings = ifcopenshell.geom.settings()
serializer_settings = ifcopenshell.geom.serializer_settings()
@@ -163,15 +180,12 @@ class IfcStore:
return IfcStore.cache
@staticmethod
def update_cache():
def update_cache() -> None:
"""Update cache filename after timestamp was updated."""
if not IfcStore.cache:
return
assert IfcStore.cache_path
assert IfcStore.file
ifc_key = IfcStore.path + IfcStore.file.wrapped_data.header.file_name.time_stamp
ifc_hash = hashlib.md5(ifc_key.encode("utf-8")).hexdigest()
props = tool.Blender.get_bim_props()
new_cache_path = os.path.join(props.cache_dir, f"{ifc_hash}.h5")
new_cache_path = IfcStore.generate_cache_path()
IfcStore.cache = None
try:
shutil.move(IfcStore.cache_path, new_cache_path)
@@ -183,11 +197,11 @@ class IfcStore:
IfcStore.get_cache()
@staticmethod
def load_file(path) -> None:
def load_file(path: str) -> None:
if not os.path.isfile(path):
return
extension = path.split(".")[-1]
props = tool.Project.get_project_props()
prefs = tool.Blender.get_addon_preferences()
if extension.lower() == "ifczip":
with tempfile.TemporaryDirectory() as unzipped_path:
with zipfile.ZipFile(path, "r") as zip_ref:
@@ -197,10 +211,11 @@ class IfcStore:
return
elif extension.lower() == "ifcxml":
IfcStore.file = ifcopenshell.file(ifcopenshell.ifcopenshell_wrapper.parse_ifcxml(path))
elif props.should_stream:
elif prefs.should_stream:
IfcStore.file = ifcopenshell.open(path, should_stream=True)
else:
IfcStore.file = ifcopenshell.open(path)
tool.Ifc.after_file_loaded()
@staticmethod
def get_schema() -> ifcopenshell.ifcopenshell_wrapper.schema_definition:
@@ -445,8 +460,11 @@ class IfcStore:
return callback
@staticmethod
modal_in_progress = False
@classmethod
def execute_ifc_operator(
cls,
operator: tool.Ifc.Operator,
context: bpy.types.Context,
event=None,
@@ -456,16 +474,33 @@ class IfcStore:
props = tool.Blender.get_bim_props()
props.is_dirty = True
# Modals don't nest, and Blender handles the loop that continuously calls modal()
is_top_level_operator = not bool(IfcStore.current_transaction) or (method == "MODAL")
# So for modal operators we emulate nesting - first modal call is starting transaction
# and modal call with FINISHED/CANCELLED result finishes it.
# Example call chain for modal operators:
# Operator1.execute called
# -> Operator.execute called nested Operator2
# -> Operator2.execute returned RUNNING_MODAL
# -> Operator2.execute is finished
# -> Operator1.execute is finished
# -> Operator2.modal is called and returned PASS_THROUGH (going to another modal loop)
# -> Operator2.modal is finished
# -> Operator2.modal called again and last two steps repeat until FINISHED or CANCELLED
is_top_level_operator = not bool(IfcStore.current_transaction) and not cls.modal_in_progress
if is_top_level_operator:
IfcStore.begin_transaction(operator)
if tool.Ifc.get():
tool.Ifc.get().begin_transaction()
if ifc_file := tool.Ifc.get():
assert (
ifc_file.transaction is None
), "Trying to override existing transaction, possible IFC undo data loss."
ifc_file.begin_transaction()
if BrickStore.graph is not None: # `if BrickStore.graph` by itself takes ages.
BrickStore.begin_transaction()
# This empty transaction ensures that each operator has at least one transaction
IfcStore.add_transaction_operation(operator, rollback=lambda data: True, commit=lambda data: True)
if method == "MODAL":
cls.modal_in_progress = True
else:
operator.transaction_key = IfcStore.current_transaction
@@ -483,6 +518,9 @@ class IfcStore:
IfcStore.end_transaction(operator)
bonsai.bim.handler.refresh_ui_data()
if method == "MODAL":
cls.modal_in_progress = False
try:
if method == "EXECUTE":
result = getattr(operator, "_execute")(context)
@@ -503,8 +541,10 @@ class IfcStore:
if method == "MODAL":
if result == {"FINISHED"}:
is_top_level_operator = True
end_top_level_operator()
elif result == {"CANCELLED"}:
is_top_level_operator = True
# Please read the docs: https://docs.blender.org/api/current/bpy.types.Operator.html
# > "when an operator returns {'CANCELLED'}, no undo step will be created".
# This means that if your modal edits IFC data, then the user
+106 -30
View File
@@ -29,6 +29,7 @@ import numpy.typing as npt
import multiprocessing
import ifcopenshell
import ifcopenshell.geom
import ifcopenshell.ifcopenshell_wrapper as W
import ifcopenshell.util.unit
import ifcopenshell.util.element
import ifcopenshell.util.geolocation
@@ -218,9 +219,7 @@ class IfcImporter:
self.gross_elements: set[ifcopenshell.entity_instance] = set()
self.element_types: set[ifcopenshell.entity_instance] = set()
self.spatial_elements: set[ifcopenshell.entity_instance] = set()
self.type_products = {}
self.meshes: dict[str, OBJECT_DATA_TYPE] = {}
self.mesh_shapes = {}
self.time = 0
self.unit_scale = 1.0
# ifc definition ids to blender elements mapping
@@ -230,7 +229,8 @@ class IfcImporter:
self.progress = 0
self.material_creator = MaterialCreator(ifc_import_settings, self)
classes_to_wireframe_str = tool.Drawing.get_document_props().classes_to_wireframe
prefs = tool.Blender.get_addon_preferences()
classes_to_wireframe_str = prefs.doc.classes_to_wireframe
self.classes_to_wireframe_list = [word.strip() for word in classes_to_wireframe_str.split(",")]
def profile_code(self, message: str) -> None:
@@ -283,6 +283,7 @@ class IfcImporter:
self.place_objects_in_collections()
self.profile_code("Place objects in collections")
self.setup_arrays()
self.update_linked_aggregates()
self.profile_code("Setup arrays")
tool.Project.load_linked_models_from_ifc()
self.profile_code("Load linked models")
@@ -461,6 +462,10 @@ class IfcImporter:
return False
def calculate_model_offset(self) -> None:
# TODO:
if isinstance(self.file, ifcopenshell.sqlite):
print("WARNING. Calculating model offset for IFCSQLite is not supported.")
return
props = tool.Georeference.get_georeference_props()
if self.ifc_import_settings.false_origin_mode == "MANUAL":
tool.Loader.set_manual_blender_offset(self.file)
@@ -514,11 +519,52 @@ class IfcImporter:
self.set_matrix_world(obj, tool.Loader.apply_blender_offset_to_matrix_world(obj, grid_placement))
def create_element_types(self):
# TODO:
if isinstance(self.file, ifcopenshell.sqlite):
self.create_element_types_sqlite(self.element_types)
return
for element_type in self.element_types:
if not element_type:
continue
self.create_element_type(element_type)
def create_element_types_sqlite(self, element_types: set[ifcopenshell.entity_instance]) -> None:
assert isinstance(self.file, ifcopenshell.sqlite)
geometry_cache = self.file.get_geometry([e.id() for e in element_types])
geometry_meshes: dict[str, bpy.types.Mesh] = {}
for geometry_id, geometry in geometry_cache["geometry"].items():
verts = geometry["verts"]
fake_geometry = type("Geometry", (), {"id": geometry_id})
mesh_name = tool.Loader.get_mesh_name_from_shape(fake_geometry) # pyright: ignore[reportArgumentType]
mesh = bpy.data.meshes.new(mesh_name)
if geometry["faces"].size:
mesh = tool.Loader.create_mesh_from_shape(
mesh=mesh, faces=geometry["faces"].reshape(-1, 3), verts=verts.reshape(-1, 3)
)
else:
vertices = verts.reshape(-1, 3).tolist()
edges = geometry["edges"].reshape(-1, 2).tolist()
mesh.from_pydata(vertices, edges, [])
tool.Loader.link_mesh(fake_geometry, mesh) # pyright: ignore[reportArgumentType]
mesh["ios_materials"] = geometry["materials"]
mesh["ios_material_ids"] = geometry["material_ids"]
self.meshes[mesh_name] = mesh
geometry_meshes[geometry_id] = mesh
shapes = geometry_cache["shapes"]
for element in element_types:
# Allow missing element types to accomodate older ifcsqlite files
# that didn't store element types geometry.
shape = shapes.get(element.id())
if shape:
geometry_id = shapes[element.id()]["geometry"]
else:
geometry_id = None
mesh = None if geometry_id is None else geometry_meshes[geometry_id]
obj = bpy.data.objects.new(tool.Loader.get_name(element), mesh)
self.link_element(element, obj)
self.material_creator.create(element, obj, mesh, False)
def create_element_type(self, element: ifcopenshell.entity_instance) -> None:
self.ifc_import_settings.logger.info("Creating object %s", element)
mesh = None
@@ -545,7 +591,6 @@ class IfcImporter:
obj = bpy.data.objects.new(tool.Loader.get_name(element), mesh)
self.link_element(element, obj)
self.material_creator.create(element, obj, mesh, False)
self.type_products[element.GlobalId] = obj
def create_native_elements(self):
if not self.ifc_import_settings.should_load_geometry:
@@ -580,18 +625,13 @@ class IfcImporter:
print("Done creating geometry")
def create_spatial_elements(self) -> None:
if tool.Blender.get_addon_preferences().spatial_elements_unselectable:
self.create_generic_elements(self.spatial_elements, unselectable=True)
else:
self.create_generic_elements(self.spatial_elements, unselectable=False)
self.create_generic_elements(self.spatial_elements)
def create_elements(self) -> None:
self.create_generic_elements(self.elements)
self.create_generic_elements(self.gross_elements, is_gross=True)
def create_generic_elements(
self, elements: set[ifcopenshell.entity_instance], unselectable=False, is_gross=False
) -> None:
def create_generic_elements(self, elements: set[ifcopenshell.entity_instance], is_gross=False) -> None:
if isinstance(self.file, ifcopenshell.sqlite):
return self.create_generic_sqlite_elements(elements)
@@ -615,10 +655,6 @@ class IfcImporter:
print("{} / {} elements processed ...".format(i, total))
objects.add(self.create_product(element))
if unselectable:
for obj in objects:
obj.hide_select = True
def create_generic_sqlite_elements(self, elements: set[ifcopenshell.entity_instance]) -> None:
assert isinstance(self.file, ifcopenshell.sql.sqlite)
self.geometry_cache = self.file.get_geometry([e.id() for e in elements])
@@ -629,15 +665,13 @@ class IfcImporter:
verts = geometry["verts"]
mesh["has_cartesian_point_offset"] = False
if geometry["faces"]:
if geometry["faces"].size:
mesh = tool.Loader.create_mesh_from_shape(
mesh=mesh, faces=geometry["faces"].reshape(-1, 3), verts=verts.reshape(-1, 3)
)
else:
e = geometry["edges"]
v = verts
vertices = [[v[i], v[i + 1], v[i + 2]] for i in range(0, len(v), 3)]
edges = [[e[i], e[i + 1]] for i in range(0, len(e), 2)]
vertices = verts.reshape(-1, 3).tolist()
edges = geometry["edges"].reshape(-1, 2).tolist()
mesh.from_pydata(vertices, edges, [])
mesh["ios_materials"] = geometry["materials"]
@@ -661,7 +695,7 @@ class IfcImporter:
settings: Optional[ifcopenshell.geom.main.settings] = None,
) -> set[ifcopenshell.entity_instance]:
checkpoint = time.time()
results = set()
results: set[ifcopenshell.entity_instance] = set()
if not products:
return results
@@ -882,7 +916,8 @@ class IfcImporter:
for material in self.material_creator.materials.values():
bpy.data.materials.remove(material)
def add_project_to_scene(self):
def add_project_to_scene(self) -> None:
assert bpy.context.scene
try:
bpy.context.scene.collection.children.link(self.project["blender"])
except:
@@ -907,6 +942,7 @@ class IfcImporter:
bpy.ops.mesh.normals_make_consistent()
bpy.ops.object.editmode_toggle()
assert bpy.context.view_layer
bpy.context.view_layer.objects.active = last_obj
IfcStore.edited_objs.clear()
@@ -916,6 +952,9 @@ class IfcImporter:
if not props.ifc_file:
props.ifc_file = self.ifc_import_settings.input_file
self.file = tool.Ifc.get()
# IFC4 Reference View shall have no booleans https://github.com/BuildingSMART/IFC4-CV/issues/14
if self.file.schema == "IFC4" and "ReferenceView" in str(self.file.header.file_description.description):
self.ifc_import_settings.void_limit = 0
def calculate_unit_scale(self):
self.unit_scale = ifcopenshell.util.unit.calculate_unit_scale(self.file)
@@ -925,6 +964,7 @@ class IfcImporter:
if not (assignment := self.file.by_type("IfcProject")[0].UnitsInContext):
return # Geometry is optional in IFC
props = tool.Blender.get_bim_props()
assert bpy.context.scene
for unit in assignment.Units:
if unit.is_a("IfcNamedUnit") and unit.UnitType == "LENGTHUNIT":
if unit.is_a("IfcSIUnit"):
@@ -972,6 +1012,7 @@ class IfcImporter:
)
obj = self.create_product(self.project["ifc"])
obj.hide_select = True
obj.hide_viewport = True
self.project["blender"].objects.link(obj)
self.project["blender"].BIMCollectionProperties.obj = obj
props = tool.Blender.get_object_bim_props(obj)
@@ -1032,9 +1073,9 @@ class IfcImporter:
def create_curve(
self,
element: ifcopenshell.entity_instance,
shape: Union[ifcopenshell.geom.ShapeElementType, ifcopenshell.geom.ShapeType],
shape: Union[W.Triangulation, W.TriangulationElement],
) -> bpy.types.Curve:
if isinstance(shape, ifcopenshell.geom.ShapeElementType):
if isinstance(shape, W.TriangulationElement):
geometry = shape.geometry
else:
geometry = shape
@@ -1063,11 +1104,11 @@ class IfcImporter:
def create_mesh(
self,
element: ifcopenshell.entity_instance,
shape: Union[ifcopenshell.geom.ShapeElementType, ifcopenshell.geom.ShapeType],
shape: Union[W.Triangulation, W.TriangulationElement],
cartesian_point_offset: Union[npt.NDArray[np.float64], Literal[False]] = None,
) -> Union[bpy.types.Mesh, None]:
try:
if isinstance(shape, ifcopenshell.geom.ShapeElementType):
if isinstance(shape, W.TriangulationElement):
# shape is ShapeElementType
geometry = shape.geometry
else:
@@ -1173,10 +1214,44 @@ class IfcImporter:
tool.Blender.Modifier.Array.set_children_lock_state(element, i, True)
tool.Blender.Modifier.Array.constrain_children_to_parent(element)
def update_linked_aggregates(self):
# TODO Remove this after a while. See commit 17d6b8a
# https://github.com/IfcOpenShell/IfcOpenShell/commit/17d6b8af61c8dd7cd82f6e72b2fb3831d851a33d#commitcomment-163151609
groups = self.file.by_type("IfcGroup")
target_groups = [group for group in groups if group.Name == "BBIM_Linked_Aggregate"]
if not target_groups:
return
for i, group in enumerate(target_groups):
name = "Default"
elements = ifcopenshell.util.element.get_grouped_by(self.file.by_id(group.id()), is_recursive=True)
for j, element in enumerate(elements):
split = element.Name.rsplit("_")
name = split[0]
try:
aggregate_index = int(split[1])
except:
aggregate_index = 0
pset = ifcopenshell.util.element.get_pset(element, "BBIM_Linked_Aggregate", should_inherit=False)
if not pset:
return
if "Aggregate_Index" not in pset.keys():
ifcopenshell.api.run(
"pset.edit_pset",
self.file,
pset=self.file.by_id(pset["id"]),
properties={"Aggregate_Index": aggregate_index, "Name": name},
)
class IfcImportSettings:
"""
Initialize only using `IfcImportSettings.factory()`.
"""
input_file: Union[str, None] = None
logger: Union[logging.Logger, None] = None
logger: logging.Logger
def __init__(self):
self.diff_file = None
@@ -1213,6 +1288,7 @@ class IfcImportSettings:
context=None, input_file: Optional[str] = None, logger: Optional[logging.Logger] = None
) -> IfcImportSettings:
scene_diff = tool.Blender.get_diff_props()
prefs = tool.Blender.get_addon_preferences()
props = tool.Project.get_project_props()
settings = IfcImportSettings()
settings.input_file = input_file
@@ -1225,7 +1301,7 @@ class IfcImportSettings:
settings.should_merge_materials_by_colour = props.should_merge_materials_by_colour
settings.should_load_geometry = props.should_load_geometry
settings.should_clean_mesh = props.should_clean_mesh
settings.should_cache = props.should_cache
settings.should_cache = prefs.should_always_cache or props.should_cache
settings.deflection_tolerance = props.deflection_tolerance
settings.angular_tolerance = props.angular_tolerance
settings.void_limit = props.void_limit
@@ -71,11 +71,14 @@ class AggregateData:
@classmethod
def total_linked_aggregate(cls) -> Union[int, None]:
element = tool.Ifc.get_entity(bpy.context.active_object)
aggregate = ifcopenshell.util.element.get_aggregate(element)
if not aggregate:
return
if not element:
return
aggregate = ifcopenshell.util.element.get_aggregate(element)
parts = ifcopenshell.util.element.get_parts(element)
if not aggregate and not parts:
return
if parts:
aggregate = element
product_linked_agg_group = next(
(
@@ -19,6 +19,7 @@
import bpy
import ifcopenshell
import ifcopenshell.api
import ifcopenshell.api.group
import ifcopenshell.api.pset
import ifcopenshell.util.element
import bonsai.tool as tool
@@ -93,6 +94,9 @@ class BIM_OT_aggregate_unassign_object(bpy.types.Operator, tool.Ifc.Operator):
bl_options = {"REGISTER", "UNDO"}
def _execute(self, context):
aggregates_to_check = set()
# First pass: unassign all parts and track their aggregates
for obj in tool.Blender.get_selected_objects():
element = tool.Ifc.get_entity(obj)
if not element:
@@ -100,6 +104,10 @@ class BIM_OT_aggregate_unassign_object(bpy.types.Operator, tool.Ifc.Operator):
aggregate = ifcopenshell.util.element.get_aggregate(element)
if not aggregate:
continue
# Track this aggregate for later checking
aggregates_to_check.add(aggregate)
core.unassign_object(
tool.Ifc,
tool.Aggregate,
@@ -115,6 +123,29 @@ class BIM_OT_aggregate_unassign_object(bpy.types.Operator, tool.Ifc.Operator):
pset = tool.Ifc.get().by_id(pset["id"])
ifcopenshell.api.pset.remove_pset(tool.Ifc.get(), product=element, pset=pset)
# Second pass: delete aggregates that now have no parts
deleted_aggregates = []
for aggregate in aggregates_to_check:
related_objects = ifcopenshell.util.element.get_parts(aggregate)
if len(related_objects) == 0:
aggregate_name = aggregate.Name or f"{aggregate.is_a()} #{aggregate.id()}"
deleted_aggregates.append(aggregate_name)
aggregate_obj = tool.Ifc.get_object(aggregate)
if aggregate_obj:
ifcopenshell.api.root.remove_product(tool.Ifc.get(), product=aggregate)
bpy.data.objects.remove(aggregate_obj, do_unlink=True)
# Show info message if aggregates were deleted
if deleted_aggregates:
if len(deleted_aggregates) == 1:
self.report(
{"INFO"}, f"Aggregate '{deleted_aggregates[0]}' was deleted because it had no remaining parts"
)
else:
aggregate_list = ", ".join(f"'{name}'" for name in deleted_aggregates)
self.report({"INFO"}, f"Aggregates {aggregate_list} were deleted because they had no remaining parts")
class BIM_OT_enable_editing_aggregate(bpy.types.Operator):
"""Enable editing aggregation relationship"""
@@ -224,16 +255,25 @@ class BIM_OT_select_aggregate(bpy.types.Operator):
bl_idname = "bim.select_aggregate"
bl_label = "Select Aggregate"
bl_options = {"REGISTER", "UNDO"}
obj: bpy.props.StringProperty()
select_parts: bpy.props.BoolProperty(default=False)
one_level_deep: bpy.props.BoolProperty(
name="One Level Deep", description="Select only immediate children, not recursively", default=False
)
@classmethod
def description(cls, context, properties):
if properties.select_parts:
return "Select Aggregate and Parts"
return "Select Aggregate and Parts.\n\nCtrl+click to select only one level deep"
else:
return "Select Aggregate"
def invoke(self, context, event):
if event.type == "LEFTMOUSE" and event.ctrl:
self.one_level_deep = True
return self.execute(context)
def execute(self, context):
all_parts = []
for obj in context.selected_objects:
@@ -249,14 +289,27 @@ class BIM_OT_select_aggregate(bpy.types.Operator):
obj.select_set(False)
if self.select_parts:
all_objs = []
selected_parts = []
for part in all_parts:
if part.IsDecomposedBy:
for subpart in part.IsDecomposedBy[0].RelatedObjects:
all_parts.append(subpart)
all_objs.append(part)
for rel in part.IsDecomposedBy:
for subpart in rel.RelatedObjects:
selected_parts.append(subpart)
for element in all_objs:
# If not limited to one level, traverse deeper
if not self.one_level_deep:
def add_descendants(elem):
if elem.IsDecomposedBy:
for rel in elem.IsDecomposedBy:
for deeper in rel.RelatedObjects:
selected_parts.append(deeper)
add_descendants(deeper)
add_descendants(subpart)
for element in set(selected_parts + all_parts):
obj = tool.Ifc.get_object(element)
if obj:
obj.select_set(True)
@@ -264,9 +317,11 @@ class BIM_OT_select_aggregate(bpy.types.Operator):
else:
for aggregate_element in all_parts:
aggregate_obj = tool.Ifc.get_object(aggregate_element)
aggregate_obj.select_set(True)
bpy.context.view_layer.objects.active = aggregate_obj
if aggregate_obj:
aggregate_obj.select_set(True)
bpy.context.view_layer.objects.active = aggregate_obj
self.one_level_deep = False # <-- forcibly reset
return {"FINISHED"}
@@ -301,6 +356,7 @@ class BIM_OT_break_link_to_other_aggregates(bpy.types.Operator, tool.Ifc.Operato
bl_options = {"REGISTER", "UNDO"}
def _execute(self, context):
ifc_file = tool.Ifc.get()
element = tool.Ifc.get_entity(bpy.context.active_object)
aggregate = ifcopenshell.util.element.get_aggregate(element)
if not aggregate:
@@ -312,8 +368,8 @@ class BIM_OT_break_link_to_other_aggregates(bpy.types.Operator, tool.Ifc.Operato
for part in parts:
pset = ifcopenshell.util.element.get_pset(part, "BBIM_Linked_Aggregate")
pset = tool.Ifc.get().by_id(pset["id"])
ifcopenshell.api.pset.remove_pset(tool.Ifc.get(), product=part, pset=pset)
pset = ifc_file.by_id(pset["id"])
ifcopenshell.api.pset.remove_pset(ifc_file, product=part, pset=pset)
linked_aggregate_group = next(
r.RelatingGroup
@@ -321,7 +377,7 @@ class BIM_OT_break_link_to_other_aggregates(bpy.types.Operator, tool.Ifc.Operato
if r.is_a("IfcRelAssignsToGroup")
if "BBIM_Linked_Aggregate" in r.RelatingGroup.Name
)
tool.Ifc.run("group.unassign_group", group=linked_aggregate_group, products=[aggregate])
ifcopenshell.api.group.unassign_group(ifc_file, group=linked_aggregate_group, products=[aggregate])
return {"FINISHED"}
+1 -1
View File
@@ -136,7 +136,7 @@ class BIM_PT_linked_aggregate(Panel):
assert (element := tool.Ifc.get_entity(obj))
row = layout.row(align=True)
if element.Decomposes:
if element.Decomposes or element.IsDecomposedBy:
Number_Linked_Aggregates = AggregateData.data["total_linked_aggregate"]
if not Number_Linked_Aggregates:
row.label(text="Not a Linked Aggregate")
@@ -21,7 +21,6 @@
import os
import ifcopenshell.api.alignment
import ifcopenshell.api.alignment.add_stationing_to_alignment
import bpy
import json
@@ -62,9 +61,7 @@ class ImportAlignmentCSV(bpy.types.Operator, tool.Ifc.Operator, ImportHelper):
def _execute(self, context):
self.file = tool.Ifc.get()
start = time.time()
alignment = ifcopenshell.api.alignment.create_alignment_from_csv(self.file, self.filepath)
ifcopenshell.api.alignment.create_geometric_representation(self.file, alignment)
ifcopenshell.api.alignment.add_stationing_to_alignment(self.file, alignment=alignment, start_station=0.0)
alignment = ifcopenshell.api.alignment.create_from_csv(self.file, self.filepath)
# IFC 4.1.5.1 alignments cannot be contained in spatial structures, but can be referenced into them
sites = self.file.by_type("IfcSite")
@@ -25,13 +25,23 @@ classes = (
operator.EditAttributes,
operator.GenerateGlobalId,
operator.CopyAttributeToSelection,
operator.ExplorerAddEntity,
operator.ExplorerEnableEditingEntity,
operator.ExplorerDisableEditingEntity,
operator.ExplorerEditEntity,
operator.ExplorerShowUIPopup,
prop.BIMAttributeProperties,
prop.ExplorerEntity,
prop.BIMExplorerProperties,
ui.BIM_PT_object_attributes,
ui.BIM_PT_explorer,
ui.BIM_UL_explorer,
)
def register():
bpy.types.Object.BIMAttributeProperties = bpy.props.PointerProperty(type=prop.BIMAttributeProperties)
bpy.types.Scene.BIMExplorerProperties = bpy.props.PointerProperty(type=prop.BIMExplorerProperties)
def unregister():
@@ -26,7 +26,11 @@ import bonsai.bim.helper
import bonsai.tool as tool
import bonsai.core.attribute as core
import bonsai.core.spatial
from typing import TYPE_CHECKING
from typing import TYPE_CHECKING, Any, Union, Literal
if TYPE_CHECKING:
from bonsai.bim.prop import Attribute
import bpy.stub_internal.rna_enums as rna_enums
def get_objs_for_operation(
@@ -75,7 +79,9 @@ class EnableEditingAttributes(bpy.types.Operator, AttributesOperator):
None,
)
def callback(name, prop, data):
lookup_attrs = tool.Attribute.does_ifc_class_support_explorer_lookup(element.is_a())
def callback(name: str, prop: Union["Attribute", None], data: dict[str, Any]) -> None | Literal[True]:
if name in ("RefLatitude", "RefLongitude"):
new = props.attributes.add()
new.name = name
@@ -89,8 +95,19 @@ class EnableEditingAttributes(bpy.types.Operator, AttributesOperator):
if name in ("PredefinedType", "ObjectType") and has_inherited_predefined_type:
props.attributes.remove(len(props.attributes) - 1)
return True
if lookup_attrs and (name in lookup_attrs):
new = props.attributes.add()
new.name = name
new.ifc_class = data["type"]
new.data_type = "enum"
new.is_optional = True
new.enum_items_dynamic = lookup_attrs[name]
new.use_explorer_ui = True
value: Union[ifcopenshell.entity_instance, None] = data[name]
if value is not None:
new.enum_value = str(value.id())
bonsai.bim.helper.import_attributes2(element, props.attributes, callback=callback)
bonsai.bim.helper.import_attributes(element, props.attributes, callback=callback)
props.is_editing_attributes = True
def execute(self, context):
@@ -107,7 +124,8 @@ class DisableEditingAttributes(bpy.types.Operator, AttributesOperator):
def disable_editing_attributes_on_obj(self, obj: bpy.types.Object) -> None:
props = tool.Blender.get_object_attribute_props(obj)
props.is_editing_attributes = False
props.attributes.clear()
props.property_unset("is_editing_attributes")
def execute(self, context):
for obj in get_objs_for_operation(self, context):
@@ -127,7 +145,7 @@ class EditAttributes(bpy.types.Operator, tool.Ifc.Operator):
if not obj or not (element := tool.Ifc.get_entity(obj)):
return
def callback(attributes, prop):
def callback(attributes: dict[str, Any], prop: "Attribute") -> None | Literal[True]:
if prop.name in ("RefLatitude", "RefLongitude"):
if not prop.is_null:
try:
@@ -138,6 +156,9 @@ class EditAttributes(bpy.types.Operator, tool.Ifc.Operator):
props = tool.Blender.get_object_attribute_props(obj)
attributes = bonsai.bim.helper.export_attributes(props.attributes, callback=callback)
lookup_attrs = tool.Attribute.does_ifc_class_support_explorer_lookup(element.is_a())
if lookup_attrs:
bonsai.bim.helper.process_exported_entity_attribute(attributes, list(lookup_attrs))
ifcopenshell.api.attribute.edit_attributes(self.file, product=element, attributes=attributes)
tool.Root.set_object_name(obj, element)
@@ -204,3 +225,139 @@ class CopyAttributeToSelection(bpy.types.Operator, tool.Ifc.Operator):
tool.Ifc, tool.Blender, tool.Root, tool.Spatial, name=self.name, value=value
)
self.report({"INFO"}, f"Attribute was successfully copied to {total} elements.")
class ExplorerAddEntity(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.explorer_add_entity"
bl_label = "Add Entity"
bl_options = {"REGISTER", "UNDO"}
def _execute(self, context) -> None:
props = tool.Attribute.get_explorer_props()
ifc_file = tool.Ifc.get()
entity = ifc_file.create_entity(props.ifc_class)
tool.Attribute.refresh_uilist_entities()
tool.Attribute.enable_editing_entity(entity)
tool.Attribute.import_entity_attributes(entity)
class ExplorerEnableEditingEntity(bpy.types.Operator):
bl_idname = "bim.explorer_enable_editing_entity"
bl_label = "Enable Editing Entity"
bl_options = {"REGISTER", "UNDO"}
def execute(self, context) -> "set[rna_enums.OperatorReturnItems]":
props = tool.Attribute.get_explorer_props()
ifc_file = tool.Ifc.get()
assert (active_entity := props.active_entity)
entity = ifc_file.by_id(active_entity.ifc_definition_id)
tool.Attribute.disable_editing_entity()
tool.Attribute.enable_editing_entity(entity)
tool.Attribute.import_entity_attributes(entity)
return {"FINISHED"}
class ExplorerDisableEditingEntity(bpy.types.Operator):
bl_idname = "bim.explorer_disable_editing_entity"
bl_label = "Disable Editing Entity"
bl_options = {"REGISTER", "UNDO"}
def execute(self, context) -> set["rna_enums.OperatorReturnItems"]:
tool.Attribute.disable_editing_entity()
return {"FINISHED"}
class ExplorerEditEntity(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.explorer_edit_entity"
bl_label = "Edit Entity"
bl_options = {"REGISTER", "UNDO"}
def _execute(self, context) -> None:
ifc_file = tool.Ifc.get()
props = tool.Attribute.get_explorer_props()
entity = ifc_file.by_id(props.editing_entity_id)
attrs = tool.Attribute.export_entity_attributes()
for attr, value in attrs.items():
setattr(entity, attr, value)
tool.Attribute.refresh_uilist_entities()
tool.Attribute.disable_editing_entity()
class ExplorerShowUIPopup(bpy.types.Operator):
bl_idname = "bim.explorer_show_ui_popup"
bl_label = "Show Explorer UI"
bl_description = "Show Explorer UI to select element as attribute value or edit it."
bl_options = {"REGISTER", "UNDO"}
ifc_class: bpy.props.StringProperty() # pyright: ignore[reportRedeclaration]
"""Element IFC class."""
attribute_name: bpy.props.StringProperty() # pyright: ignore[reportRedeclaration]
"""IFC class attribute name."""
data_path: bpy.props.StringProperty() # pyright: ignore[reportRedeclaration]
"""Full data path"""
preselect_ifc_id: bpy.props.IntProperty(options={"SKIP_SAVE"}) # pyright: ignore[reportRedeclaration]
"""IFC id to preselect in the popup."""
if TYPE_CHECKING:
ifc_class: str
attribute_name: str
data_path: str
preselect_ifc_id: int
def invoke(self, context, event) -> "set[rna_enums.OperatorReturnItems]":
assert context.window_manager
assert self.ifc_class and self.attribute_name and self.data_path
props = tool.Attribute.get_explorer_props()
props.is_loaded = True
props.ifc_class = self.get_attribute_type()
if self.preselect_ifc_id:
props.active_entity_index = next(
i for i, e in enumerate(props.entities) if e.ifc_definition_id == self.preselect_ifc_id
)
return context.window_manager.invoke_props_dialog(self, width=400)
def get_attribute_type(self) -> str:
schema = tool.Ifc.schema()
entity = schema.declaration_by_name(self.ifc_class).as_entity()
assert entity
i = entity.attribute_index(self.attribute_name)
attr = entity.all_attributes()[i]
named_type = attr.type_of_attribute().as_named_type()
assert named_type
declared = named_type.declared_type()
return declared.name()
def draw(self, context) -> None:
from bonsai.bim.module.attribute.ui import BIM_PT_explorer
BIM_PT_explorer.draw(self, context, is_popup=True)
def execute(self, context) -> "set[rna_enums.OperatorReturnItems]":
props = tool.Attribute.get_explorer_props()
active_entity = props.active_entity
if active_entity is None:
self.report({"WARNING"}, "No entity selected.")
return {"FINISHED"}
# Apply pending changes for convenience.
if props.editing_entity_id:
if props.editing_entity_id == active_entity.ifc_definition_id:
bpy.ops.bim.explorer_edit_entity()
else:
bpy.ops.bim.explorer_disable_editing_entity()
# Very important to do it after changes applied, otherwise enum might update
# and index will be pointing to a different element.
exec(f"{self.data_path} = '{active_entity.ifc_definition_id}'")
return {"FINISHED"}
def cancel(self, context: bpy.types.Context) -> None:
props = tool.Attribute.get_explorer_props()
if props.editing_entity_id:
bpy.ops.bim.explorer_disable_editing_entity()
+61 -1
View File
@@ -17,6 +17,7 @@
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
import bpy
import bonsai.tool as tool
from bonsai.bim.prop import StrProperty, Attribute
from bpy.types import PropertyGroup
from bpy.props import (
@@ -29,7 +30,7 @@ from bpy.props import (
FloatVectorProperty,
CollectionProperty,
)
from typing import TYPE_CHECKING
from typing import TYPE_CHECKING, Union
class BIMAttributeProperties(PropertyGroup):
@@ -39,3 +40,62 @@ class BIMAttributeProperties(PropertyGroup):
if TYPE_CHECKING:
attributes: bpy.types.bpy_prop_collection_idprop[Attribute]
is_editing_attributes: bool
class ExplorerEntity(PropertyGroup):
ifc_definition_id: bpy.props.IntProperty() # pyright: ignore[reportRedeclaration]
if TYPE_CHECKING:
ifc_definition_id: int
class BIMExplorerProperties(PropertyGroup):
def update_is_loaded(self, context: object) -> None:
if self.is_loaded:
# Trigger refresh.
self.ifc_class = self.ifc_class
else:
self.property_unset("is_loaded")
self.property_unset("ifc_class")
self.entities.clear()
self.property_unset("active_entity_index")
self.property_unset("editing_entity_id")
self.entity_attributes.clear()
is_loaded: BoolProperty( # pyright: ignore[reportRedeclaration]
name="Toggle Explorer UI",
update=update_is_loaded,
)
def get_ifc_class(self, context: object) -> tool.Blender.BLENDER_ENUM_ITEMS:
# TODO: Add more entities.
classes = [
"IfcPostalAddress",
"IfcTelecomAddress",
]
return [(c, c, "") for c in classes]
def update_ifc_class(self, context: object) -> None:
tool.Attribute.refresh_uilist_entities()
ifc_class: EnumProperty( # pyright: ignore[reportRedeclaration]
name="IFC Class To Search",
items=get_ifc_class,
update=update_ifc_class,
)
entities: CollectionProperty(type=ExplorerEntity) # pyright: ignore[reportRedeclaration]
active_entity_index: IntProperty() # pyright: ignore[reportRedeclaration]
editing_entity_id: IntProperty() # pyright: ignore[reportRedeclaration]
entity_attributes: CollectionProperty(type=Attribute) # pyright: ignore[reportRedeclaration]
if TYPE_CHECKING:
is_loaded: bool
ifc_class: str
entities: bpy.types.bpy_prop_collection_idprop[ExplorerEntity]
active_entity_index: int
editing_entity_id: int
entity_attributes: bpy.types.bpy_prop_collection_idprop[Attribute]
@property
def active_entity(self) -> Union[ExplorerEntity, None]:
return tool.Blender.get_active_uilist_element(self.entities, self.active_entity_index)
+78 -1
View File
@@ -16,11 +16,16 @@
# 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
import bonsai.bim.helper
import bpy.types
from bpy.types import Panel
from bonsai.bim.module.attribute.data import AttributesData
import bonsai.tool as tool
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from bonsai.bim.module.attribute.prop import BIMExplorerProperties, ExplorerEntity
def draw_ui(context: bpy.types.Context, layout: bpy.types.UILayout, attributes) -> None:
@@ -33,7 +38,9 @@ def draw_ui(context: bpy.types.Context, layout: bpy.types.UILayout, attributes)
row.operator("bim.edit_attributes", icon="CHECKMARK", text="Save Attributes")
row.operator("bim.disable_editing_attributes", icon="CANCEL", text="")
bonsai.bim.helper.draw_attributes(props.attributes, layout, copy_operator="bim.copy_attribute_to_selection")
bonsai.bim.helper.draw_attributes(
props.attributes, layout, copy_operator="bim.copy_attribute_to_selection", enable_search=True
)
else:
row = layout.row()
op = row.operator("bim.enable_editing_attributes", icon="GREASEPENCIL", text="Edit")
@@ -66,3 +73,73 @@ class BIM_PT_object_attributes(Panel):
if not AttributesData.is_loaded:
AttributesData.load()
draw_ui(context, self.layout, AttributesData.data["attributes"])
class BIM_PT_explorer(Panel):
bl_label = "Explorer"
bl_idname = "BIM_PT_explorer"
bl_options = {"DEFAULT_CLOSED"}
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "scene"
bl_parent_id = "BIM_PT_tab_project_setup"
def draw(self, context, *, is_popup=False):
assert (layout := self.layout)
props = tool.Attribute.get_explorer_props()
if is_popup:
layout.label(text=props.ifc_class)
else:
if not props.is_loaded:
row = layout.row(align=True)
row.label(text="Explorer UI is not Loaded.")
row.prop(props, "is_loaded", text="", icon="IMPORT")
return
row = layout.row(align=True)
row.prop(props, "ifc_class", text="")
row.prop(props, "is_loaded", text="", icon="CANCEL")
active_entity = props.active_entity
row = layout.row(align=True)
row.label(text=f"{len(props.entities)} entities found")
row.operator("bim.explorer_add_entity", text="", icon="ADD")
if active_entity:
if active_entity.ifc_definition_id == props.editing_entity_id:
row.operator("bim.explorer_disable_editing_entity", icon="CANCEL", text="")
else:
row.operator("bim.explorer_enable_editing_entity", icon="GREASEPENCIL", text="")
# TODO: 'Remove' button?
layout.template_list("BIM_UL_explorer", "", props, "entities", props, "active_entity_index")
if props.editing_entity_id:
box = self.layout.box()
# In popup we accept edits automatically for the convenience.
# Othrewise it seems very unintuitive, when you need to click confirmation twice.
if not is_popup:
row = box.row(align=True)
row.operator("bim.explorer_edit_entity", icon="CHECKMARK")
row.operator("bim.explorer_disable_editing_entity", icon="CANCEL", text="")
bonsai.bim.helper.draw_attributes(props.entity_attributes, box, enable_search=True)
class BIM_UL_explorer(bpy.types.UIList):
def draw_item(
self,
context: bpy.types.Context,
layout: bpy.types.UILayout,
data: BIMExplorerProperties,
item: ExplorerEntity,
icon,
active_data,
active_propname,
) -> None:
row = layout.row(align=True)
if item.ifc_definition_id == data.editing_entity_id:
row.label(text=item.name, icon="GREASEPENCIL")
else:
row.label(text=item.name)
@@ -71,6 +71,7 @@ classes = (
ui.BIM_PT_bcf,
ui.BIM_PT_bcf_metadata,
ui.BIM_PT_bcf_comments,
ui.BIM_UL_topics,
)
+8 -3
View File
@@ -1208,12 +1208,14 @@ class ActivateBcfViewpoint(bpy.types.Operator):
self.file = tool.Ifc.get()
bcfxml = bcfstore.BcfStore.get_bcfxml()
assert bcfxml
assert context.scene
props = tool.Bcf.get_bcf_props()
blender_topic = props.active_topic
assert blender_topic
topic = bcfxml.topics[blender_topic.name]
if self.viewpoint_guid:
viewpoint_guid = self.viewpoint_guid
viewpoint_guid = self.viewpoint_guid + ".bcfv"
if viewpoint_guid not in topic.viewpoints:
self.report({"ERROR"}, f"No such viewpoint in the active topic: '{viewpoint_guid}'.")
return {"CANCELLED"}
@@ -1234,6 +1236,7 @@ class ActivateBcfViewpoint(bpy.types.Operator):
cam_height = context.scene.render.resolution_y
cam_aspect = cam_width / cam_height
assert isinstance(obj.data, bpy.types.Camera)
obj.data.background_images.clear()
if viewpoint.snapshot:
obj.data.show_background_images = True
@@ -1273,7 +1276,7 @@ class ActivateBcfViewpoint(bpy.types.Operator):
if tool.Bcf.get_viewpoint_bitmaps(viewpoint):
self.create_bitmaps(bcfxml, viewpoint, topic)
self.setup_camera(viewpoint, obj, cam_aspect, context)
self.setup_camera(viewpoint, obj, cam_aspect, context, cam_height, cam_width)
return {"FINISHED"}
def setup_camera(
@@ -1282,6 +1285,8 @@ class ActivateBcfViewpoint(bpy.types.Operator):
obj: bpy.types.Object,
cam_aspect: float,
context: bpy.types.Context,
cam_height: float,
cam_width: float,
) -> None:
assert isinstance(obj.data, bpy.types.Camera)
if viewpoint.visualization_info.orthogonal_camera:
@@ -1308,7 +1313,7 @@ class ActivateBcfViewpoint(bpy.types.Operator):
x_axis = y_axis.cross(z_axis).normalized()
rotation = Matrix((x_axis, y_axis, z_axis))
rotation.invert()
matrix = np.matrix(
matrix = np.array(
(
[x_axis[0], y_axis[0], z_axis[0], camera.camera_view_point.x],
[x_axis[1], y_axis[1], z_axis[1], camera.camera_view_point.y],
+26
View File
@@ -16,11 +16,16 @@
# 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
import os
import bpy
import bonsai.tool as tool
from . import bcfstore
from bpy.types import Panel
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from bonsai.bim.module.bcf.prop import BcfTopic, BCFProperties
class BIM_PT_bcf(Panel):
@@ -33,6 +38,7 @@ class BIM_PT_bcf(Panel):
bl_parent_id = "BIM_PT_tab_collaboration"
def draw(self, context):
assert self.layout
layout = self.layout
layout.use_property_split = True
layout.use_property_decorate = False
@@ -125,6 +131,7 @@ class BIM_PT_bcf_metadata(Panel):
# without adding them to specific topic.
# Currently we just handle it the same way as in v2
# documents are accessed and managed from topics.
assert self.layout
layout = self.layout
layout.use_property_split = True
layout.use_property_decorate = False
@@ -139,6 +146,7 @@ class BIM_PT_bcf_metadata(Panel):
bcf_v3 = bcf_verison.startswith("3")
topic = props.active_topic
assert topic
bcf_topic = bcfxml.topics[topic.name]
layout.label(text="Header Files:")
@@ -303,6 +311,7 @@ class BIM_PT_bcf_comments(Panel):
row.prop(props, "comment_text_width")
topic = props.active_topic
assert topic
for comment in topic.comments:
box = self.layout.box()
@@ -341,3 +350,20 @@ class BIM_PT_bcf_comments(Panel):
row.prop(props, "has_related_viewpoint")
row = layout.row()
row.operator("bim.add_bcf_comment")
class BIM_UL_topics(bpy.types.UIList):
def draw_item(
self,
context,
layout: bpy.types.UILayout,
data: BCFProperties,
item: BcfTopic,
icon,
active_data,
active_propname,
) -> None:
if item:
layout.prop(item, "title", text="", emboss=False)
else:
layout.label(text="", translate=False)
@@ -40,6 +40,7 @@ from mathutils import Vector, Matrix
from bonsai.bim.ifc import IfcStore
from bonsai.bim.module.model.decorator import ProfileDecorator
from bonsai.bim.module.boundary.decorator import BoundaryDecorator
from ifcopenshell.util.shape_builder import ShapeBuilder
import bonsai.core
import bonsai.core.geometry
from typing import Union, Optional
@@ -984,7 +985,7 @@ class AddBoundary(bpy.types.Operator, tool.Ifc.Operator):
continue
connection_geometry = self.create_connection_geometry_from_polygon(opening_polygon, target_face_matrix)
boundary = tool.Ifc.run("root.create_entity", ifc_class=props.boundary_class)
boundary = ifcopenshell.api.root.create_entity(ifc_file, ifc_class=props.boundary_class)
boundary.RelatingSpace = space
boundary.RelatedBuildingElement = filling
boundary.ConnectionGeometry = connection_geometry
@@ -1058,15 +1059,11 @@ class AddBoundary(bpy.types.Operator, tool.Ifc.Operator):
self.unit_scale = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get())
tool.Model.unit_scale = self.unit_scale
builder = ShapeBuilder(tool.Ifc.get())
surface = tool.Ifc.get().createIfcCurveBoundedPlane()
surface.BasisSurface = tool.Ifc.get().createIfcPlane(
tool.Ifc.get().createIfcAxis2Placement3D(
tool.Ifc.get().createIfcCartesianPoint([o / self.unit_scale for o in p1]),
tool.Ifc.get().createIfcDirection([float(o) for o in z_axis]),
tool.Ifc.get().createIfcDirection([float(o) for o in x_axis]),
)
)
placement = builder.create_axis2_placement_3d([o / self.unit_scale for o in p1], z_axis, x_axis)
surface.BasisSurface = tool.Ifc.get().create_entity("IfcPlane", placement)
if tool.Ifc.get().schema != "IFC2X3":
points = [tool.Model.convert_si_to_unit(list(co)) for co in polygon.exterior.coords]
@@ -25,6 +25,7 @@ classes = (
operator.LoadBSDDDictionaries,
operator.SearchBSDDClassifications,
operator.SearchBSDDProperties,
operator.BIM_OT_show_bsdd_description,
prop.BSDDDictionary,
prop.BSDDClassification,
prop.BSDDProperty,
+2 -3
View File
@@ -38,8 +38,7 @@ class BSDDData:
cls.data["active_dictionary"] = cls.active_dictionary()
@classmethod
def active_dictionary(cls):
props = tool.Bsdd.get_bsdd_props()
def active_dictionary(cls) -> tool.Blender.BLENDER_ENUM_ITEMS:
results = [("ALL", "All Dictionaries", "All active dictionaries")]
results.extend([(d.uri, d.name, f"{d.status} - {d.version}") for d in props.dictionaries if d.is_active])
results.extend(tool.Bsdd.get_active_bsdd_enum_items())
return results
+47 -7
View File
@@ -15,13 +15,14 @@
#
# You should have received a copy of the GNU General Public License
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
import textwrap
import bpy
import bsdd
import bonsai.tool as tool
import ifcopenshell.api.pset
import ifcopenshell.util.element
from bonsai.core import bsdd as core
from typing import Any
class LoadBSDDDictionaries(bpy.types.Operator):
@@ -41,7 +42,7 @@ class SearchBSDDClassifications(bpy.types.Operator):
bl_options = {"REGISTER", "UNDO"}
def execute(self, context):
total = core.search_bsdd_class(tool.Bsdd, context.scene.BIMBSDDProperties.keyword)
total = core.search_bsdd_class(tool.Bsdd, tool.Bsdd.get_bsdd_props().keyword)
self.report({"INFO"}, f"{total} bSDD classes found.")
return {"FINISHED"}
@@ -71,7 +72,7 @@ class SearchBSDDProperties(bpy.types.Operator):
def execute(self, context):
props = tool.Bsdd.get_bsdd_props()
core.search_bsdd_properties(tool.Bsdd, context.scene.BIMBSDDProperties.keyword, self.obj, self.obj_type)
core.search_bsdd_properties(tool.Bsdd, tool.Bsdd.get_bsdd_props().keyword, self.obj, self.obj_type)
self.report({"INFO"}, f"{len(props.properties)} bSDD properties found.")
return {"FINISHED"}
@@ -79,23 +80,30 @@ class SearchBSDDProperties(bpy.types.Operator):
class AddBSDDProperties(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.add_bsdd_properties"
bl_label = "Add bSDD Properties"
bl_description = "Add selected bSDD properties"
bl_description = "Add selected bSDD properties to the active object"
bl_options = {"REGISTER", "UNDO"}
obj: bpy.props.StringProperty()
obj_type: bpy.props.StringProperty()
@classmethod
def poll(cls, context):
props = tool.Bsdd.get_bsdd_props()
if not props.selected_properties:
cls.poll_message_set("No properties selected to add.")
return False
return True
def _execute(self, context):
self.file = tool.Ifc.get()
bprops = tool.Bsdd.get_bsdd_props()
psets = {}
psets: dict[str, dict[str, Any]] = {}
for selected_property in bprops.selected_properties:
psets.setdefault(selected_property.metadata, {})[selected_property.name] = selected_property.get_value()
props = tool.Pset.get_pset_props(self.obj, self.obj_type)
ifc_definition_id = tool.Blender.get_obj_ifc_definition_id(self.obj, self.obj_type, context)
assert ifc_definition_id
element = tool.Ifc.get().by_id(ifc_definition_id)
properties = {}
current_psets = ifcopenshell.util.element.get_psets(element, verbose=True)
for pset_name, properties in psets.items():
@@ -104,3 +112,35 @@ class AddBSDDProperties(bpy.types.Operator, tool.Ifc.Operator):
else:
pset = ifcopenshell.api.pset.add_pset(self.file, product=element, name=pset_name)
ifcopenshell.api.pset.edit_pset(self.file, pset=pset, properties=properties)
class BIM_OT_show_bsdd_description(bpy.types.Operator):
bl_idname = "bim.show_bsdd_description"
bl_label = "bSDD Description"
url: bpy.props.StringProperty()
def invoke(self, context, event):
wm = context.window_manager
return wm.invoke_props_dialog(self, width=450)
def execute(self, context):
return {"FINISHED"}
def draw(self, context):
WIDTH = 80
layout = self.layout
wrapper = textwrap.TextWrapper(width=WIDTH)
result = tool.Bsdd.get_bsdd_property(self.url)
description = result.get("description") or ""
definition = result.get("definition") or ""
if description != definition:
text = wrapper.wrap(f"Description : {description}")
text.append("-" * (WIDTH - 15))
text += wrapper.wrap(f"Definition : {definition}")
else:
text = wrapper.wrap(f"Description : {description}")
for line in text:
layout.label(text=line)
if self.url:
url_op = layout.operator("bim.open_uri", icon="URL", text="Online bSDD Documentation")
url_op.uri = self.url
+67 -17
View File
@@ -20,6 +20,7 @@ import bpy
import bonsai.tool as tool
from bpy.types import PropertyGroup
from bonsai.bim.module.bsdd.data import BSDDData
from bonsai.bim.module.classification.data import ClassificationsData
from bonsai.bim.prop import Attribute, StrProperty
from bpy.props import (
PointerProperty,
@@ -31,17 +32,34 @@ from bpy.props import (
FloatVectorProperty,
CollectionProperty,
)
from typing import Union
from typing import Union, TYPE_CHECKING, Literal
def get_active_dictionary(self, context):
def get_active_dictionary(self: "BIMBSDDProperties", context: object) -> tool.Blender.BLENDER_ENUM_ITEMS:
if not BSDDData.is_loaded:
BSDDData.load()
return BSDDData.data["active_dictionary"]
def update_is_active(self: "BSDDDictionary", context: bpy.types.Context) -> None:
tool.Bsdd.save_active_bsdd_to_ifc()
BSDDData.data["active_dictionary"] = BSDDData.active_dictionary()
if ClassificationsData.is_loaded:
props = tool.Classification.get_classification_props()
# Preserve original enum value.
classification_source = props.classification_source
ClassificationsData.data["classification_source"] = ClassificationsData.classification_source()
# Try to restore enum value.
if "classification_source" not in props:
# It's already on the default value, nothing to restore.
return
try:
props.classification_source = classification_source
except TypeError:
# Item is no longer active and not present in enum, fallback to the default.
del props["classification_source"]
def update_is_selected(self: "BSDDProperty", context: bpy.types.Context) -> None:
@@ -54,27 +72,41 @@ def update_active_class_index(self: "BIMBSDDProperties", context: bpy.types.Cont
class BSDDDictionary(PropertyGroup):
name: StringProperty(name="Name")
uri: StringProperty(name="URI")
default_language_code: StringProperty(name="Language")
organization_name_owner: StringProperty(name="Organization")
status: StringProperty(name="Status")
version: StringProperty(name="Version")
is_active: BoolProperty(
name="Is Active", description="Enable to search with this dictionary", default=False, update=update_is_active
name="Is Active",
description="Enable to search with this dictionary",
default=False,
update=update_is_active,
)
if TYPE_CHECKING:
uri: str
default_language_code: str
organization_name_owner: str
status: str
version: str
is_active: bool
class BSDDClassification(PropertyGroup):
name: StringProperty(name="Name")
reference_code: StringProperty(name="Reference Code")
uri: StringProperty(name="URI")
dictionary_name: StringProperty(name="Dictionary Name")
dictionary_namespace_uri: StringProperty(name="Dictionary Namespace URI")
if TYPE_CHECKING:
reference_code: str
uri: str
dictionary_name: str
dictionary_namespace_uri: str
class BSDDProperty(PropertyGroup):
name: StringProperty(name="Name")
code: StringProperty(name="Code")
uri: StringProperty(name="URI")
pset: StringProperty(name="Pset")
@@ -82,14 +114,22 @@ class BSDDProperty(PropertyGroup):
name="Is Selected", description="Select to add or edit this property", default=False, update=update_is_selected
)
if TYPE_CHECKING:
code: str
uri: str
pset: str
is_selected: bool
class BSDDPset(PropertyGroup):
name: StringProperty(name="Name")
properties: CollectionProperty(name="Properties", type=Attribute)
if TYPE_CHECKING:
properties: bpy.types.bpy_prop_collection_idprop[Attribute]
class BIMBSDDProperties(PropertyGroup):
active_dictionary: StringProperty(name="Active Dictionary")
# TODO: `active_dictionary` is not used anywhere?
active_dictionary: EnumProperty(items=get_active_dictionary, name="Active Dictionary")
active_uri: StringProperty(name="Active URI")
dictionaries: CollectionProperty(name="Dictionaries", type=BSDDDictionary)
@@ -120,17 +160,27 @@ class BIMBSDDProperties(PropertyGroup):
description="Whether to display and assign only properties from IFC dictionary",
default=False,
)
load_preview_dictionaries: BoolProperty(
name="Load Preview Dictionaries", description="Load dictionaries marked as Preview status", default=False
)
load_inactive_dictionaries: BoolProperty(
name="Load Inactive Dictionaries", description="Load dictionaries marked as Inactive status", default=False
)
load_test_dictionaries: BoolProperty(
name="Load Test Dictionaries", description="Load dictionaries that are for testing only", default=False
)
classification_psets: CollectionProperty(name="Classification Psets", type=BSDDPset)
if TYPE_CHECKING:
active_dictionary: str
active_dictionary: str
active_uri: str
dictionaries: bpy.types.bpy_prop_collection_idprop[BSDDDictionary]
active_dictionary_index: int
classifications: bpy.types.bpy_prop_collection_idprop[BSDDClassification]
active_classification_index: int
property_filter_mode: Literal["CLASS", "KEYWORD"]
classes: bpy.types.bpy_prop_collection_idprop[BSDDClassification]
active_class_index: int
properties: bpy.types.bpy_prop_collection_idprop[BSDDProperty]
active_property_index: int
selected_properties: bpy.types.bpy_prop_collection_idprop[Attribute]
keyword: str
should_filter_ifc_class: bool
use_only_ifc_properties: bool
classification_psets: bpy.types.bpy_prop_collection_idprop[BSDDPset]
@property
def active_class(self) -> Union[BSDDClassification, None]:
return tool.Blender.get_active_uilist_element(self.classes, self.active_class_index)
+49 -6
View File
@@ -16,9 +16,15 @@
# 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
import bpy
import bonsai.tool as tool
from bonsai.bim.module.bsdd.data import BSDDData
from bpy.types import Panel, UIList
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from bonsai.bim.module.bsdd.prop import BIMBSDDProperties, BSDDDictionary, BSDDClassification, BSDDProperty
class BIM_PT_bsdd(Panel):
@@ -33,7 +39,8 @@ class BIM_PT_bsdd(Panel):
def draw(self, context):
if not BSDDData.is_loaded:
BSDDData.load()
props = context.scene.BIMBSDDProperties
props = tool.Bsdd.get_bsdd_props()
assert self.layout
layout = self.layout
if len(props.dictionaries):
row = self.layout.row()
@@ -70,9 +77,17 @@ class BIM_PT_bsdd(Panel):
class BIM_UL_bsdd_dictionaries(UIList):
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
def draw_item(
self,
context,
layout: bpy.types.UILayout,
data: BIMBSDDProperties,
item: BSDDDictionary,
icon,
active_data,
active_propname,
) -> None:
if item:
props = context.scene.BIMBSDDProperties
row = layout.row(align=True)
if item.status != "Active":
row.label(
@@ -86,7 +101,16 @@ class BIM_UL_bsdd_dictionaries(UIList):
class BIM_UL_bsdd_classifications(UIList):
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
def draw_item(
self,
context,
layout: bpy.types.UILayout,
data: BIMBSDDProperties,
item: BSDDClassification,
icon,
active_data,
active_propname,
) -> None:
if item:
row = layout.row(align=True)
row.label(text=item.reference_code)
@@ -95,7 +119,16 @@ class BIM_UL_bsdd_classifications(UIList):
class BIM_UL_bsdd_classes(UIList):
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
def draw_item(
self,
context,
layout: bpy.types.UILayout,
data: BIMBSDDProperties,
item: BSDDClassification,
icon,
active_data,
active_propname,
) -> None:
if item:
row = layout.row(align=True)
row.label(text=item.name)
@@ -103,8 +136,18 @@ class BIM_UL_bsdd_classes(UIList):
class BIM_UL_bsdd_properties(UIList):
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
def draw_item(
self,
context,
layout: bpy.types.UILayout,
data: BIMBSDDProperties,
item: BSDDProperty,
icon,
active_data,
active_propname,
) -> None:
if item:
layout.context_pointer_set("active_bsdd_property", item) # used for context menu
row = layout.row(align=True)
name = item.name
if name != item.code:
@@ -48,6 +48,7 @@ classes = (
ui.BIM_PT_classification_references,
ui.BIM_PT_material_classifications,
ui.BIM_PT_cost_classifications,
ui.BIM_PT_zone_classifications,
ui.BIM_UL_classifications,
)
@@ -21,19 +21,20 @@ import ifcopenshell
import ifcopenshell.util.date
import ifcopenshell.util.classification
import bonsai.tool as tool
from typing import Any
from typing import Any, Literal, Union
from bonsai.bim.ifc import IfcStore
def refresh():
ClassificationsData.is_loaded = False
ClassificationReferencesData.is_loaded = False
ObjectClassificationsData.is_loaded = False
MaterialClassificationsData.is_loaded = False
CostClassificationsData.is_loaded = False
ZoneClassificationsData.is_loaded = False
class ClassificationsData:
data = {}
data: dict[str, Any] = {}
is_loaded = False
@classmethod
@@ -55,6 +56,7 @@ class ClassificationsData:
data = element.get_info()
if tool.Ifc.get().schema == "IFC2X3" and element.EditionDate:
data["EditionDate"] = ifcopenshell.util.date.ifc2datetime(data["EditionDate"])
data["Name"] = data["Name"] or "Unnamed"
results.append(data)
return results
@@ -65,13 +67,12 @@ class ClassificationsData:
return [(str(e.id()), e.Name, "") for e in IfcStore.classification_file.by_type("IfcClassification")]
@classmethod
def classification_source(cls):
def classification_source(cls) -> tool.Blender.BLENDER_ENUM_ITEMS:
items = [
("FILE", "IFC File", ""),
("MANUAL", "Manual Entry", ""),
]
bprops = tool.Bsdd.get_bsdd_props()
dictionaries = [(d.uri, f"bSDD: {d.name}", "") for d in bprops.dictionaries if d.is_active]
dictionaries = tool.Bsdd.get_active_bsdd_enum_items()
if dictionaries:
items.append(("BSDD", "All Active bSDDs", ""))
items.extend(dictionaries)
@@ -79,11 +80,39 @@ class ClassificationsData:
class ReferencesData:
data: dict[str, Any]
is_loaded = False
obj_type: Literal["Object", "Material", "Cost", "Zone"]
@classmethod
def load(cls):
cls.is_loaded = True
cls.data = {}
cls.data["references"] = cls.references()
cls.data["active_classification_library"] = cls.active_classification_library()
cls.data["classifications"] = cls.classifications()
@classmethod
def get_element(cls) -> Union[ifcopenshell.entity_instance, None]:
"""Get element to get classification references from."""
raise NotImplementedError
@classmethod
def references(cls) -> list[dict[str, Any]]:
results = []
element = cls.get_element()
if element:
for reference in ifcopenshell.util.classification.get_references(element):
data = reference.get_info()
del data["ReferencedSource"]
results.append(data)
return results
@classmethod
def active_classification_library(cls):
if not IfcStore.classification_file or not IfcStore.classification_file.by_type("IfcClassification"):
return False
props = bpy.context.scene.BIMClassificationProperties
props = tool.Classification.get_classification_props()
name = IfcStore.classification_file.by_id(int(props.available_classifications)).Name
if name in [e.Name for e in tool.Ifc.get().by_type("IfcClassification")]:
return name
@@ -93,81 +122,44 @@ class ReferencesData:
return [(str(e.id()), e.Name, "") for e in tool.Ifc.get().by_type("IfcClassification")]
class ClassificationReferencesData(ReferencesData):
data = {}
is_loaded = False
class ObjectClassificationsData(ReferencesData):
obj_type = "Object"
@classmethod
def load(cls):
cls.is_loaded = True
cls.data["references"] = cls.references()
cls.data["active_classification_library"] = cls.active_classification_library()
cls.data["classifications"] = cls.classifications()
cls.data["object_type"] = "Object"
@classmethod
def references(cls):
results = []
element = tool.Ifc.get_entity(bpy.context.active_object)
if element:
for reference in ifcopenshell.util.classification.get_references(element):
data = reference.get_info()
del data["ReferencedSource"]
results.append(data)
return results
def get_element(cls) -> Union[ifcopenshell.entity_instance, None]:
if obj := bpy.context.active_object:
return tool.Ifc.get_entity(obj)
return None
class MaterialClassificationsData(ReferencesData):
data = {}
is_loaded = False
obj_type = "Material"
@classmethod
def load(cls):
cls.is_loaded = True
cls.data["references"] = cls.references()
cls.data["active_classification_library"] = cls.active_classification_library()
cls.data["classifications"] = cls.classifications()
cls.data["object_type"] = "Material"
@classmethod
def references(cls):
results = []
def get_element(cls) -> Union[ifcopenshell.entity_instance, None]:
props = tool.Material.get_material_props()
if props.materials and props.active_material_index < len(props.materials):
material = props.materials[props.active_material_index]
if material.ifc_definition_id:
element = tool.Ifc.get().by_id(material.ifc_definition_id)
for reference in ifcopenshell.util.classification.get_references(element):
data = reference.get_info()
del data["ReferencedSource"]
results.append(data)
return results
if material := props.active_material:
return tool.Ifc.get().by_id(material.ifc_definition_id)
return None
class CostClassificationsData(ReferencesData):
data = {}
is_loaded = False
obj_type = "Cost"
@classmethod
def load(cls):
cls.is_loaded = True
cls.data["references"] = cls.references()
cls.data["active_classification_library"] = cls.active_classification_library()
cls.data["classifications"] = cls.classifications()
cls.data["object_type"] = "Cost"
@classmethod
def references(cls) -> list[dict[str, Any]]:
results: list[dict[str, Any]] = []
def get_element(cls) -> Union[ifcopenshell.entity_instance, None]:
props = tool.Cost.get_cost_props()
active_cost_item = props.active_cost_item
if not active_cost_item:
return results
element = tool.Ifc.get().by_id(active_cost_item.ifc_definition_id)
if element:
for reference in ifcopenshell.util.classification.get_references(element):
data = reference.get_info()
del data["ReferencedSource"]
results.append(data)
return results
if cost_item := props.active_cost_item:
return tool.Ifc.get().by_id(cost_item.ifc_definition_id)
return None
class ZoneClassificationsData(ReferencesData):
obj_type = "Zone"
@classmethod
def get_element(cls) -> Union[ifcopenshell.entity_instance, None]:
props = tool.System.get_zone_props()
if active_zone := props.active_zone:
return tool.Ifc.get().by_id(active_zone.ifc_definition_id)
return None
@@ -17,7 +17,6 @@
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
import bpy
import json
import ifcopenshell
import ifcopenshell.api
import ifcopenshell.api.pset
@@ -47,7 +46,7 @@ class AddClassification(bpy.types.Operator, tool.Ifc.Operator):
bl_options = {"REGISTER", "UNDO"}
def _execute(self, context):
props = context.scene.BIMClassificationProperties
props = tool.Classification.get_classification_props()
ifcopenshell.api.classification.add_classification(
tool.Ifc.get(),
classification=IfcStore.classification_file.by_id(int(props.available_classifications)),
@@ -60,7 +59,7 @@ class AddManualClassification(bpy.types.Operator, tool.Ifc.Operator):
bl_options = {"REGISTER", "UNDO"}
def _execute(self, context):
props = context.scene.BIMClassificationProperties
props = tool.Classification.get_classification_props()
attributes = bonsai.bim.helper.export_attributes(props.classification_attributes)
classification = ifcopenshell.api.classification.add_classification(tool.Ifc.get(), classification="Unnamed")
ifcopenshell.api.classification.edit_classification(
@@ -84,7 +83,7 @@ class AddManualClassificationReference(bpy.types.Operator, tool.Ifc.Operator):
objects = [context.active_object.name]
else:
objects = [self.obj]
props = context.scene.BIMClassificationReferenceProperties
props = tool.Classification.get_classification_reference_props()
attributes = bonsai.bim.helper.export_attributes(props.reference_attributes)
products = [
tool.Ifc.get().by_id(ifc_definition_id)
@@ -110,7 +109,7 @@ class AddClassificationFromBSDD(bpy.types.Operator, tool.Ifc.Operator):
bl_options = {"REGISTER", "UNDO"}
def _execute(self, context):
cprops = context.scene.BIMClassificationProperties
cprops = tool.Classification.get_classification_props()
bprops = tool.Bsdd.get_bsdd_props()
if cprops.classification_source == "BSDD":
dictionaries = [d.uri for d in bprops.dictionaries if d.is_active]
@@ -142,11 +141,11 @@ class EnableAddingManualClassification(bpy.types.Operator):
bl_options = {"REGISTER", "UNDO"}
def execute(self, context):
props = context.scene.BIMClassificationProperties
props = tool.Classification.get_classification_props()
props.is_adding = True
props.active_classification_id = 0
props.classification_attributes.clear()
bonsai.bim.helper.import_attributes2("IfcClassification", props.classification_attributes)
bonsai.bim.helper.import_attributes("IfcClassification", props.classification_attributes)
return {"FINISHED"}
@@ -156,7 +155,7 @@ class DisableAddingManualClassification(bpy.types.Operator):
bl_options = {"REGISTER", "UNDO"}
def execute(self, context):
props = context.scene.BIMClassificationProperties
props = tool.Classification.get_classification_props()
props.is_adding = False
return {"FINISHED"}
@@ -167,10 +166,10 @@ class EnableAddingManualClassificationReference(bpy.types.Operator):
bl_options = {"REGISTER", "UNDO"}
def execute(self, context):
props = context.scene.BIMClassificationReferenceProperties
props = tool.Classification.get_classification_reference_props()
props.is_adding = True
props.reference_attributes.clear()
bonsai.bim.helper.import_attributes2("IfcClassificationReference", props.reference_attributes)
bonsai.bim.helper.import_attributes("IfcClassificationReference", props.reference_attributes)
return {"FINISHED"}
@@ -180,7 +179,7 @@ class DisableAddingManualClassificationReference(bpy.types.Operator):
bl_options = {"REGISTER", "UNDO"}
def execute(self, context):
props = context.scene.BIMClassificationReferenceProperties
props = tool.Classification.get_classification_reference_props()
props.is_adding = False
return {"FINISHED"}
@@ -192,21 +191,11 @@ class EnableEditingClassification(bpy.types.Operator):
classification: bpy.props.IntProperty()
def execute(self, context):
def callback(name, prop, data):
if name == "ReferenceTokens":
geo_props = tool.Georeference.get_georeference_props()
new = geo_props.projected_crs.add()
new.name = name
new.data_type = "string"
new.is_null = data[name] is None
new.is_optional = True
new.string_value = "" if new.is_null else json.dumps(data[name])
return True
props = context.scene.BIMClassificationProperties
props = tool.Classification.get_classification_props()
props.classification_attributes.clear()
bonsai.bim.helper.import_attributes2(
tool.Ifc.get().by_id(self.classification), props.classification_attributes, callback
bonsai.bim.helper.import_attributes(
tool.Ifc.get().by_id(self.classification),
props.classification_attributes,
)
props.active_classification_id = self.classification
return {"FINISHED"}
@@ -218,7 +207,8 @@ class DisableEditingClassification(bpy.types.Operator):
bl_options = {"REGISTER", "UNDO"}
def execute(self, context):
context.scene.BIMClassificationProperties.active_classification_id = 0
props = tool.Classification.get_classification_props()
props.active_classification_id = 0
return {"FINISHED"}
@@ -246,14 +236,8 @@ class EditClassification(bpy.types.Operator, tool.Ifc.Operator):
bl_options = {"REGISTER", "UNDO"}
def _execute(self, context):
props = context.scene.BIMClassificationProperties
def callback(attributes, prop):
if prop.name == "ReferenceTokens":
attributes[prop.name] = json.loads(prop.string_value)
return True
attributes = bonsai.bim.helper.export_attributes(props.classification_attributes, callback=callback)
props = tool.Classification.get_classification_props()
attributes = bonsai.bim.helper.export_attributes(props.classification_attributes)
ifc_file = tool.Ifc.get()
ifcopenshell.api.classification.edit_classification(
ifc_file,
@@ -271,9 +255,9 @@ class EnableEditingClassificationReference(bpy.types.Operator):
obj: bpy.props.StringProperty()
def execute(self, context):
props = context.scene.BIMClassificationReferenceProperties
props = tool.Classification.get_classification_reference_props()
props.reference_attributes.clear()
bonsai.bim.helper.import_attributes2(tool.Ifc.get().by_id(self.reference), props.reference_attributes)
bonsai.bim.helper.import_attributes(tool.Ifc.get().by_id(self.reference), props.reference_attributes)
props.active_reference_id = self.reference
return {"FINISHED"}
@@ -285,7 +269,7 @@ class DisableEditingClassificationReference(bpy.types.Operator):
obj: bpy.props.StringProperty()
def execute(self, context):
context.scene.BIMClassificationReferenceProperties.active_reference_id = 0
tool.Classification.get_classification_reference_props().active_reference_id = 0
return {"FINISHED"}
@@ -337,7 +321,7 @@ class EditClassificationReference(bpy.types.Operator, tool.Ifc.Operator):
obj: bpy.props.StringProperty()
def _execute(self, context):
props = context.scene.BIMClassificationReferenceProperties
props = tool.Classification.get_classification_reference_props()
attributes = bonsai.bim.helper.export_attributes(props.reference_attributes)
ifc_file = tool.Ifc.get()
ifcopenshell.api.classification.edit_reference(
@@ -364,7 +348,7 @@ class AddClassificationReference(bpy.types.Operator, tool.Ifc.Operator):
objects = [context.active_object.name]
else:
objects = [self.obj]
props = context.scene.BIMClassificationProperties
props = tool.Classification.get_classification_props()
classification = None
classification_name = IfcStore.classification_file.by_id(int(props.available_classifications)).Name
for element in tool.Ifc.get().by_type("IfcClassification"):
@@ -405,8 +389,7 @@ class AddClassificationReferenceFromBSDD(bpy.types.Operator, tool.Ifc.Operator):
objects = [context.active_object.name]
else:
objects = [self.obj]
props = context.scene.BIMClassificationProperties
bprops = context.scene.BIMBSDDProperties
bprops = tool.Bsdd.get_bsdd_props()
use_only_ifc_properties: bool = bprops.use_only_ifc_properties
bsdd_classification = bprops.classifications[bprops.active_classification_index]
@@ -487,7 +470,7 @@ class ChangeClassificationLevel(bpy.types.Operator):
parent_id: bpy.props.IntProperty()
def execute(self, context):
props = context.scene.BIMClassificationProperties
props = tool.Classification.get_classification_props()
props.available_library_references.clear()
for reference in IfcStore.classification_file.by_id(self.parent_id).HasReferences:
new = props.available_library_references.add()
@@ -509,6 +492,6 @@ class DisableEditingClassificationReferences(bpy.types.Operator):
bl_options = {"REGISTER", "UNDO"}
def execute(self, context):
props = context.scene.BIMClassificationProperties
props = tool.Classification.get_classification_props()
props.available_library_references.clear()
return {"FINISHED"}
@@ -17,8 +17,9 @@
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
import bpy
import bonsai.tool as tool
from bonsai.bim.prop import Attribute
from bonsai.bim.module.classification.data import ClassificationsData, ClassificationReferencesData
from bonsai.bim.module.classification.data import ClassificationsData, ObjectClassificationsData
from bpy.types import PropertyGroup
from bpy.props import (
PointerProperty,
@@ -30,33 +31,43 @@ from bpy.props import (
FloatVectorProperty,
CollectionProperty,
)
from typing import TYPE_CHECKING
def get_available_classifications(self, context):
def get_available_classifications(
self: "BIMClassificationProperties", context: bpy.types.Context
) -> tool.Blender.BLENDER_ENUM_ITEMS:
if not ClassificationsData.is_loaded:
ClassificationsData.load()
return ClassificationsData.data["available_classifications"]
def get_classifications(self, context):
if not ClassificationReferencesData.is_loaded:
ClassificationReferencesData.load()
return ClassificationReferencesData.data["classifications"]
if not ObjectClassificationsData.is_loaded:
ObjectClassificationsData.load()
return ObjectClassificationsData.data["classifications"]
def get_classification_source(self, context):
def get_classification_source(
self: "BIMClassificationProperties", context: bpy.types.Context
) -> tool.Blender.BLENDER_ENUM_ITEMS:
if not ClassificationsData.is_loaded:
ClassificationsData.load()
return ClassificationsData.data["classification_source"]
class ClassificationReference(PropertyGroup):
name: StringProperty(name="Name")
identification: StringProperty(name="Identification")
ifc_definition_id: IntProperty(name="IFC Definition ID")
has_references: BoolProperty(name="Has References")
referenced_source: IntProperty(name="IFC Definition ID")
if TYPE_CHECKING:
identification: str
ifc_definition_id: int
has_references: bool
referenced_source: int
class BIMClassificationProperties(PropertyGroup):
is_adding: BoolProperty(name="Is Adding", default=False)
@@ -68,9 +79,25 @@ class BIMClassificationProperties(PropertyGroup):
active_library_referenced_source: IntProperty(name="Active Library Referenced Source")
active_library_reference_index: IntProperty(name="Active Library Reference Index")
if TYPE_CHECKING:
is_adding: bool
classification_source: str
available_classifications: str
classification_attributes: bpy.types.bpy_prop_collection_idprop[Attribute]
active_classification_id: int
available_library_references: bpy.types.bpy_prop_collection_idprop[ClassificationReference]
active_library_referenced_source: int
active_library_reference_index: int
class BIMClassificationReferenceProperties(PropertyGroup):
is_adding: BoolProperty(name="Is Adding", default=False)
classifications: EnumProperty(items=get_classifications, name="Classifications")
reference_attributes: CollectionProperty(name="Reference Attributes", type=Attribute)
active_reference_id: IntProperty(name="Active Reference Id")
if TYPE_CHECKING:
is_adding: bool
classifications: str
reference_attributes: bpy.types.bpy_prop_collection_idprop
active_reference_id: int
@@ -16,6 +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/>.
from __future__ import annotations
import bpy
import bonsai.bim.helper
import bonsai.tool as tool
@@ -23,10 +24,15 @@ import bonsai.bim.module.classification.prop as classification_prop
from bpy.types import Panel, UIList
from bonsai.bim.module.classification.data import (
ClassificationsData,
ClassificationReferencesData,
ObjectClassificationsData,
MaterialClassificationsData,
CostClassificationsData,
ZoneClassificationsData,
)
from typing import TYPE_CHECKING, Any, Union
if TYPE_CHECKING:
from bonsai.bim.module.classification.prop import BIMClassificationProperties, ClassificationReference
class BIM_PT_classifications(Panel):
@@ -46,7 +52,8 @@ class BIM_PT_classifications(Panel):
if not ClassificationsData.is_loaded:
ClassificationsData.load()
self.props = context.scene.BIMClassificationProperties
self.props = tool.Classification.get_classification_props()
assert self.layout
row = self.layout.row(align=True)
row.label(text="Source", icon="OUTLINER")
@@ -66,6 +73,7 @@ class BIM_PT_classifications(Panel):
self.draw_ui(classification)
def draw_add_manual_ui(self, context):
assert self.layout
if self.props.is_adding:
bonsai.bim.helper.draw_attributes(self.props.classification_attributes, self.layout)
row = self.layout.row(align=True)
@@ -76,10 +84,12 @@ class BIM_PT_classifications(Panel):
row.operator("bim.enable_adding_manual_classification", text="Add Classification", icon="ADD")
def draw_add_bsdd_ui(self, context):
assert self.layout
row = self.layout.row()
row.operator("bim.add_classification_from_bsdd", icon="ADD")
def draw_add_file_ui(self, context):
assert self.layout
if ClassificationsData.data["has_classification_file"]:
row = self.layout.row(align=True)
row.prop(self.props, "available_classifications", text="")
@@ -90,13 +100,15 @@ class BIM_PT_classifications(Panel):
row.label(text="No Active Classification Library")
row.operator("bim.load_classification_library", text="", icon="IMPORT")
def draw_editable_ui(self):
def draw_editable_ui(self) -> None:
assert self.layout
row = self.layout.row(align=True)
row.operator("bim.edit_classification", text="Save changes", icon="CHECKMARK")
row.operator("bim.disable_editing_classification", text="", icon="CANCEL")
bonsai.bim.helper.draw_attributes(self.props.classification_attributes, self.layout)
def draw_ui(self, classification):
def draw_ui(self, classification: dict[str, Any]) -> None:
assert self.layout
row = self.layout.row(align=True)
row.label(text=classification["Name"], icon="ASSET_MANAGER")
if not self.props.active_classification_id:
@@ -106,13 +118,32 @@ class BIM_PT_classifications(Panel):
class ReferenceUI:
layout: bpy.types.UILayout
layout: Union[bpy.types.UILayout, None]
data: type[
Union[
ObjectClassificationsData,
MaterialClassificationsData,
CostClassificationsData,
ZoneClassificationsData,
]
]
def draw_ui(self, context):
obj = context.active_object
self.sprops = context.scene.BIMClassificationProperties
self.bprops = context.scene.BIMBSDDProperties
self.props = context.scene.BIMClassificationReferenceProperties
obj: str
"""Object name."""
def get_object_name(self, context: bpy.types.Context) -> str:
return ""
def draw(self, context: bpy.types.Context) -> None:
if not self.data.is_loaded:
self.data.load()
self.obj = self.get_object_name(context)
self.draw_ui(context)
def draw_ui(self, context: bpy.types.Context) -> None:
self.sprops = tool.Classification.get_classification_props()
self.bprops = tool.Bsdd.get_bsdd_props()
self.props = tool.Classification.get_classification_reference_props()
self.file = tool.Ifc.get()
self.draw_add_ui(context)
@@ -127,7 +158,7 @@ class ReferenceUI:
else:
self.draw_reference_ui(reference)
def draw_add_ui(self, context):
def draw_add_ui(self, context: bpy.types.Context) -> None:
row = self.layout.row(align=True)
row.label(text="Source", icon="OUTLINER")
row.prop(self.sprops, "classification_source", text="")
@@ -139,20 +170,20 @@ class ReferenceUI:
else:
self.draw_add_bsdd_ui(context)
def draw_add_manual_ui(self, context):
def draw_add_manual_ui(self, context: object) -> None:
row = self.layout.row()
row.prop(self.props, "classifications", text="")
if self.props.is_adding:
bonsai.bim.helper.draw_attributes(self.props.reference_attributes, self.layout)
row = self.layout.row(align=True)
op = row.operator("bim.add_manual_classification_reference", text="Save", icon="CHECKMARK")
op.obj_type = self.data.data["object_type"]
op.obj_type = self.data.obj_type
row.operator("bim.disable_adding_manual_classification_reference", text="", icon="CANCEL")
else:
row = self.layout.row()
row.operator("bim.enable_adding_manual_classification_reference", text="Add Reference", icon="ADD")
def draw_add_bsdd_ui(self, context):
def draw_add_bsdd_ui(self, context: object) -> None:
row = self.layout.row(align=True)
row.prop(self.bprops, "keyword", text="")
row.prop(self.bprops, "should_filter_ifc_class", text="", icon="FILTER")
@@ -177,9 +208,9 @@ class ReferenceUI:
"bim.add_classification_reference_from_bsdd", text="Add Classification Reference", icon="ADD"
)
op.obj = self.obj
op.obj_type = self.obj_type
op.obj_type = self.data.obj_type
def draw_add_file_ui(self, context):
def draw_add_file_ui(self, context: object) -> None:
if not self.data.data["active_classification_library"]:
row = self.layout.row(align=True)
row.label(text="No Active Classification Library", icon="ERROR")
@@ -199,7 +230,7 @@ class ReferenceUI:
if self.sprops.active_library_reference_index < len(self.sprops.available_library_references):
op = row.operator("bim.add_classification_reference", text="", icon="ADD")
op.obj = self.obj
op.obj_type = self.obj_type
op.obj_type = self.data.obj_type
op.reference = self.sprops.available_library_references[
self.sprops.active_library_reference_index
].ifc_definition_id
@@ -213,13 +244,13 @@ class ReferenceUI:
"active_library_reference_index",
)
def draw_editable_ui(self):
def draw_editable_ui(self) -> None:
row = self.layout.row(align=True)
row.operator("bim.edit_classification_reference", text="Save changes", icon="CHECKMARK")
row.operator("bim.disable_editing_classification_reference", text="", icon="CANCEL")
bonsai.bim.helper.draw_attributes(self.props.reference_attributes, self.layout)
def draw_reference_ui(self, reference):
def draw_reference_ui(self, reference: dict[str, Any]) -> None:
row = self.layout.row(align=True)
if self.file.schema == "IFC2X3":
name = reference["ItemReference"] or "No Identification"
@@ -235,7 +266,7 @@ class ReferenceUI:
op = row.operator("bim.remove_classification_reference", text="", icon="X")
op.reference = reference["id"]
op.obj = self.obj
op.obj_type = self.obj_type
op.obj_type = self.data.obj_type
class BIM_PT_classification_references(Panel, ReferenceUI):
@@ -247,19 +278,19 @@ class BIM_PT_classification_references(Panel, ReferenceUI):
bl_context = "object"
bl_parent_id = "BIM_PT_tab_object_metadata"
data = ObjectClassificationsData
@classmethod
def poll(cls, context):
if not context.active_object:
return False
return bool(tool.Ifc.get_entity(context.active_object))
return (
(obj := tool.Blender.get_active_object())
and (element := tool.Ifc.get_entity(obj))
and element.is_a("IfcObjectDefinition")
)
def draw(self, context):
if not ClassificationReferencesData.is_loaded:
ClassificationReferencesData.load()
self.data = ClassificationReferencesData
self.obj = context.active_object.name
self.obj_type = "Object"
self.draw_ui(context)
def get_object_name(self, context: bpy.types.Context) -> str:
assert (obj := context.active_object)
return obj.name
class BIM_PT_material_classifications(Panel, ReferenceUI):
@@ -271,6 +302,8 @@ class BIM_PT_material_classifications(Panel, ReferenceUI):
bl_context = "scene"
bl_parent_id = "BIM_PT_materials"
data = MaterialClassificationsData
@classmethod
def poll(cls, context):
if not tool.Ifc.get():
@@ -280,14 +313,6 @@ class BIM_PT_material_classifications(Panel, ReferenceUI):
return True
return False
def draw(self, context):
if not MaterialClassificationsData.is_loaded:
MaterialClassificationsData.load()
self.data = MaterialClassificationsData
self.obj = ""
self.obj_type = "Material"
self.draw_ui(context)
class BIM_PT_cost_classifications(Panel, ReferenceUI):
bl_label = "Cost Item Classifications"
@@ -298,6 +323,8 @@ class BIM_PT_cost_classifications(Panel, ReferenceUI):
bl_context = "scene"
bl_parent_id = "BIM_PT_cost_schedules"
data = CostClassificationsData
@classmethod
def poll(cls, context):
if not tool.Ifc.get():
@@ -305,17 +332,35 @@ class BIM_PT_cost_classifications(Panel, ReferenceUI):
props = tool.Cost.get_cost_props()
return bool(props.cost_items)
def draw(self, context):
if not CostClassificationsData.is_loaded:
CostClassificationsData.load()
self.data = CostClassificationsData
self.obj = ""
self.obj_type = "Cost"
self.draw_ui(context)
class BIM_PT_zone_classifications(Panel, ReferenceUI):
bl_label = "Zone Classifications"
bl_idname = "BIM_PT_zone_classifications"
bl_options = {"DEFAULT_CLOSED"}
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "scene"
bl_parent_id = "BIM_PT_zones"
data = ZoneClassificationsData
@classmethod
def poll(cls, context):
props = tool.System.get_zone_props()
return bool(props.active_zone)
class BIM_UL_classifications(UIList):
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
def draw_item(
self,
context,
layout: bpy.types.UILayout,
data: BIMClassificationProperties,
item: ClassificationReference,
icon,
active_data,
active_propname,
):
if item:
if item.has_references:
op = layout.operator("bim.change_classification_level", text="", icon="DISCLOSURE_TRI_RIGHT")
@@ -81,7 +81,7 @@ class EnableEditingConstraint(bpy.types.Operator):
def execute(self, context):
props = tool.Blender.get_constraint_props()
props.constraint_attributes.clear()
bonsai.bim.helper.import_attributes2(tool.Ifc.get().by_id(self.constraint), props.constraint_attributes)
bonsai.bim.helper.import_attributes(tool.Ifc.get().by_id(self.constraint), props.constraint_attributes)
props.active_constraint_id = self.constraint
return {"FINISHED"}
@@ -52,12 +52,19 @@ class ContextData:
def get_subcontexts(cls, context: ifcopenshell.entity_instance) -> list[dict[str, Any]]:
results = []
for subcontext in context.HasSubContexts:
target_scale_denominator = None
if subcontext.TargetScale is not None:
scale_value = float(subcontext.TargetScale)
if scale_value > 0:
target_scale_denominator = 1.0 / scale_value
results.append(
{
"id": subcontext.id(),
"context_type": subcontext.ContextType,
"context_identifier": subcontext.ContextIdentifier,
"target_view": subcontext.TargetView,
"target_scale_denominator": target_scale_denominator,
}
)
return results
@@ -84,5 +84,26 @@ class BIM_PT_context(bpy.types.Panel):
row.label(text=subcontext["context_type"])
row.label(text=subcontext["context_identifier"])
row.label(text=subcontext["target_view"])
scale_col = row.column()
scale_col.ui_units_x = 6
if subcontext["target_scale_denominator"] is not None:
scale_value = subcontext["target_scale_denominator"]
if scale_value == int(scale_value):
scale_str = str(int(scale_value))
if len(scale_str) > 4:
scale_str = f"{float(scale_value):.3g}"
else:
scale_str = f"{scale_value:.4g}"
if len(scale_str) > 4:
scale_str = f"{float(scale_value):.3g}"
scale_col.label(text=f"1:{scale_str}")
else:
scale_col.label(text="")
row.operator("bim.enable_editing_context", icon="GREASEPENCIL", text="").context = subcontext["id"]
row.operator("bim.remove_context", icon="X", text="").context = subcontext["id"]
@@ -37,6 +37,7 @@ classes = (
operator.ContractCostItemRate,
operator.ContractCostItems,
operator.CopyCostItem,
operator.CopyCostSchedule,
operator.CopyCostItemValues,
operator.DisableEditingCostItem,
operator.DisableEditingCostItemQuantity,
@@ -59,9 +60,11 @@ classes = (
operator.ExpandCostItemRate,
operator.ExpandCostItems,
operator.ExportCostSchedules,
operator.ExportCostSchedulesToPDF,
operator.HighlightProductCostItem,
operator.ImportCostScheduleCsv,
operator.RefreshCostScheduleCsv,
operator.RemoveCostScheduleCsvLink,
operator.LoadCostItemElementQuantities,
operator.LoadCostItemQuantities,
operator.ShowAssignedCostRate,
@@ -84,7 +87,6 @@ classes = (
prop.CostItem,
prop.CostItemQuantity,
prop.CostItemType,
prop.CostSchedulesMapping,
prop.ScheduleColumn,
prop.BIMCostProperties,
ui.BIM_PT_cost_schedules,
+35 -14
View File
@@ -56,9 +56,29 @@ class CostSchedulesData:
"cost_values": cls.cost_values(),
"quantity_types": cls.quantity_types(),
"currency": cls.currency(),
"csv_filepaths": cls.get_csv_filepaths(),
}
cls.is_loaded = True
@classmethod
def get_csv_filepaths(cls) -> dict[int, str]:
"""Get CSV filepaths for cost schedules from document references."""
filepaths = {}
cost_docs_document = tool.Cost.get_or_create_cost_documents()
if cost_docs_document:
references = tool.Document.get_document_references(cost_docs_document)
for reference in references:
if reference.Description and "Cost Schedule ID:" in reference.Description:
schedule_id_str = reference.Description.split("Cost Schedule ID:")[1].strip()
try:
schedule_id = int(schedule_id_str)
filepaths[schedule_id] = reference.Location
except ValueError:
pass
return filepaths
@classmethod
def currency(cls) -> Union[Currency, None]:
unit = tool.Unit.get_project_currency_unit()
@@ -111,6 +131,7 @@ class CostSchedulesData:
cls._load_cost_values(cost_item, data)
cls._load_nesting_index(cost_item, data)
cls._load_assigned_cost_rate(cost_item, data)
cls._load_parent_cost_schedule(cost_item, data)
results[cost_item.id()] = data
return results
@@ -162,6 +183,10 @@ class CostSchedulesData:
def _load_assigned_cost_rate(cls, cost_item: ifcopenshell.entity_instance, data: CostItem) -> None:
data["AssignedCostRate"] = tool.Cost.get_assigned_rate_cost_item(cost_item)
@classmethod
def _load_parent_cost_schedule(cls, cost_item: ifcopenshell.entity_instance, data: CostItem) -> None:
data["ParentCostSchedule"] = tool.Cost.get_cost_schedule(cost_item)
@classmethod
def _load_cost_item_quantities(cls, cost_item: ifcopenshell.entity_instance, data: CostItem) -> None:
# parametric_quantities = []
@@ -171,6 +196,7 @@ class CostSchedulesData:
# parametric_quantities.extend(quantities)
data["TotalCostQuantity"] = ifcopenshell.util.cost.get_total_quantity(cost_item)
data["UnitSymbol"] = "-"
data["QuantityType"] = None
quantities: list[ifcopenshell.entity_instance] = cost_item.CostQuantities
if quantities:
quantity = quantities[0]
@@ -300,10 +326,8 @@ class CostSchedulesData:
@classmethod
def quantity_types(cls) -> list[tuple[str, str, str]]:
return [
(t.name(), t.name(), "")
for t in tool.Ifc.schema().declaration_by_name("IfcPhysicalSimpleQuantity").subtypes()
]
assert (entity := tool.Ifc.schema().declaration_by_name("IfcPhysicalSimpleQuantity").as_entity())
return [(t.name(), t.name(), "") for t in entity.subtypes()]
@classmethod
def get_cost_schedule_types(cls) -> list[tuple[str, str, str]]:
@@ -350,13 +374,13 @@ class CostItemQuantitiesData:
cls.is_loaded = True
@classmethod
def product_quantity_names(cls):
elements = tool.Spatial.get_selected_products()
def product_quantity_names(cls) -> tool.Blender.BLENDER_ENUM_ITEMS:
elements = list(tool.Spatial.get_selected_products())
names = ifcopenshell.util.cost.get_product_quantity_names(elements)
return [(n, n, "") for n in names]
@classmethod
def process_quantity_names(cls):
def process_quantity_names(cls) -> tool.Blender.BLENDER_ENUM_ITEMS:
props = tool.Sequence.get_work_schedule_props()
active_task_index = props.active_task_index
tprops = tool.Sequence.get_task_tree_props()
@@ -372,14 +396,11 @@ class CostItemQuantitiesData:
return [(n, n, "") for n in names if n != "id"]
@classmethod
def resource_quantity_names(cls):
active_resource_index = bpy.context.scene.BIMResourceProperties.active_resource_index
total_resources = len(bpy.context.scene.BIMResourceTreeProperties.resources)
if not total_resources or active_resource_index >= total_resources:
def resource_quantity_names(cls) -> tool.Blender.BLENDER_ENUM_ITEMS:
active_resource = tool.Resource.get_resource_props().active_resource
if not active_resource:
return []
ifc_definition_id = bpy.context.scene.BIMResourceTreeProperties.resources[
active_resource_index
].ifc_definition_id
ifc_definition_id = active_resource.ifc_definition_id
element = tool.Ifc.get().by_id(ifc_definition_id)
names = set()
qtos = ifcopenshell.util.element.get_psets(element, qtos_only=True)
+260 -5
View File
@@ -25,6 +25,8 @@ import bonsai.tool as tool
from bpy_extras.io_utils import ImportHelper, ExportHelper
import bonsai.tool as tool
import bonsai.core.cost as core
from pathlib import Path
from typing import get_args, TYPE_CHECKING, Literal
@@ -80,6 +82,20 @@ class RemoveCostSchedule(bpy.types.Operator, tool.Ifc.Operator):
core.remove_cost_schedule(tool.Ifc, tool.Cost, cost_schedule=tool.Ifc.get().by_id(self.cost_schedule))
class CopyCostSchedule(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.copy_cost_schedule"
bl_label = "Copy Cost Schedule"
bl_description = "Create a duplicate of the provided cost schedule."
bl_options = {"REGISTER", "UNDO"}
cost_schedule: bpy.props.IntProperty() # pyright: ignore[reportRedeclaration]
if TYPE_CHECKING:
cost_schedule: int
def _execute(self, context):
core.copy_cost_schedule(tool.Cost, cost_schedule=tool.Ifc.get().by_id(self.cost_schedule))
class EnableEditingCostSchedule(bpy.types.Operator):
bl_idname = "bim.enable_editing_cost_schedule_attributes"
bl_label = "Enable Editing Cost Schedule"
@@ -545,11 +561,16 @@ class SelectCostScheduleProducts(bpy.types.Operator):
class ImportCostScheduleCsv(bpy.types.Operator, ImportHelper, tool.Ifc.Operator):
bl_idname = "bim.import_cost_schedule_csv"
bl_label = "Import Cost Schedule CSV"
bl_description = "Import cost schdule from the provided .csv file."
bl_description = "Import cost schedule from the provided .csv file."
bl_options = {"REGISTER", "UNDO"}
filename_ext = ".csv"
filter_glob: bpy.props.StringProperty(default="*.csv", options={"HIDDEN"})
is_schedule_of_rates: bpy.props.BoolProperty(name="Is Schedule Of Rates", default=False)
use_relative_path: bpy.props.BoolProperty(
name="Use Relative Path",
description="Store the CSV filepath relative to the currently opened IFC file",
default=False,
)
@classmethod
def poll(cls, context):
@@ -560,22 +581,82 @@ class ImportCostScheduleCsv(bpy.types.Operator, ImportHelper, tool.Ifc.Operator)
return True
def _execute(self, context):
cost_schedule = core.import_cost_schedule_csv(tool.Cost, self.filepath, self.is_schedule_of_rates)
core.add_csv_filepath(tool.Cost, self.filepath, self.is_schedule_of_rates, cost_schedule)
return {"FINISHED"}
store_path = self.filepath
if self.use_relative_path:
store_path = tool.Ifc.get_uri(self.filepath, use_relative_path=True)
resolved_path = Path(tool.Ifc.resolve_uri(self.filepath))
if not resolved_path.exists():
self.report({"ERROR"}, f"File does not exist: '{store_path}' (resolved to '{resolved_path}')")
return {"CANCELLED"}
cost_schedule = core.import_cost_schedule_csv(tool.Cost, str(resolved_path), self.is_schedule_of_rates)
if cost_schedule:
core.add_csv_filepath(tool.Cost, store_path, self.is_schedule_of_rates, cost_schedule)
return {"FINISHED"}
return {"CANCELLED"}
def draw(self, context):
row = self.layout.row()
row.prop(self, "is_schedule_of_rates")
row = self.layout.row()
row.prop(self, "use_relative_path")
class RefreshCostScheduleCsv(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.refresh_cost_schedule_csv"
bl_label = "Refresh Cost Schedule CSV"
bl_description = "Refresh cost schedule data from the associated CSV file"
bl_options = {"REGISTER", "UNDO"}
@classmethod
def poll(cls, context):
props = tool.Cost.get_cost_props()
if not props.active_cost_schedule_id:
cls.poll_message_set("No active cost schedule")
return False
file_path = tool.Cost.get_cost_schedule_csv_filepath(props.active_cost_schedule_id)
if not file_path:
cls.poll_message_set("No CSV file associated with this cost schedule")
return False
return True
def _execute(self, context):
core.refresh_cost_schedule_csv(tool.Ifc, tool.Cost)
core.refresh_cost_schedule_csv(tool.Cost)
return {"FINISHED"}
class RemoveCostScheduleCsvLink(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.remove_cost_schedule_csv_link"
bl_label = "Remove CSV Link"
bl_description = "Remove the link to the CSV file and delete the related document reference"
bl_options = {"REGISTER", "UNDO"}
@classmethod
def poll(cls, context):
props = tool.Cost.get_cost_props()
if not props.active_cost_schedule_id:
cls.poll_message_set("No active cost schedule")
return False
file_path = tool.Cost.get_cost_schedule_csv_filepath(props.active_cost_schedule_id)
if not file_path:
cls.poll_message_set("No CSV file associated with this cost schedule")
return False
return True
def _execute(self, context):
core.remove_cost_schedule_csv_link(tool.Cost)
return {"FINISHED"}
def invoke(self, context, event):
return context.window_manager.invoke_confirm(self, event)
class AddCostColumn(bpy.types.Operator):
bl_idname = "bim.add_cost_column"
bl_label = "Add Cost Column"
@@ -620,6 +701,7 @@ class ShowAssignedCostRate(bpy.types.Operator):
bl_idname = "bim.show_assigned_cost_rate"
bl_label = "Info about the assigned cost item rate"
bl_options = {"REGISTER"}
parent_cost_schedule_name: bpy.props.StringProperty()
assigned_rate_identification: bpy.props.StringProperty()
assigned_rate_name: bpy.props.StringProperty()
assigned_rate_description: bpy.props.StringProperty()
@@ -636,6 +718,7 @@ class ShowAssignedCostRate(bpy.types.Operator):
def draw(self, context):
layout = self.layout
wrapper = textwrap.TextWrapper(width=80)
layout.label(text=f"COST SCHEDULE: {self.parent_cost_schedule_name}")
layout.label(text=f"ID: {self.assigned_rate_identification}")
layout.label(text=f"Name: {self.assigned_rate_name}")
layout.label(text="Description:")
@@ -785,6 +868,178 @@ class ExportCostSchedules(bpy.types.Operator, ExportHelper):
self.layout.label(text="Select a directory.")
class ExportCostSchedulesToPDF(bpy.types.Operator, ExportHelper):
bl_idname = "bim.export_cost_schedules_to_pdf"
bl_label = "Export Cost Schedule to PDF"
bl_options = {"REGISTER", "UNDO"}
bl_description = "Print chosen cost schedule to pdf."
filename_ext = ".pdf"
filter_glob: bpy.props.StringProperty(default="*.pdf", options={"HIDDEN"}, maxlen=255)
cost_schedules_items = []
def get_cost_schedules_enum_items(self, context):
return ExportCostSchedulesToPDF.cost_schedules_items
cost_schedules_enum: bpy.props.EnumProperty(
name="",
description="Choose IfcCostSchedule to print",
items=get_cost_schedules_enum_items,
)
nested_structure_depth: bpy.props.IntProperty(
name="Nested structure depth: ",
description="Define till which level of the structure the parent cost items are displayed.\n0: display the full structure.",
default=0,
min=0,
max=9,
)
parent_to_new_page_up_to_depth: bpy.props.IntProperty(
name="Parents to new page up to depth: ",
description="Define till which level of the structure the parent is printed to a new page.\n0: no parent is split to a new page.",
default=0,
min=0,
max=9,
)
show_only_parents: bpy.props.BoolProperty(
name="Show only parent cost items",
description="Hide cost items and show only container costs",
default=False,
)
should_print_cover: bpy.props.BoolProperty(
name="Cover page",
description="Create a cover page with project data",
default=False,
)
should_print_description: bpy.props.BoolProperty(
name="Full Cost Items Description",
description="Export the full description if present",
default=True,
)
should_print_cost_ids: bpy.props.BoolProperty(
name="Print Cost Identification",
description="Print Cost Identification under Cost Name if present",
default=True,
)
should_print_each_quantity: bpy.props.BoolProperty(
name="Show each quantity",
description="Export the full list of quantities",
default=False,
)
should_print_each_cost_value: bpy.props.BoolProperty(
name="Show each cost value",
description="Export the full list of cost values\nassociated with each cost item\nin the schedule of rates",
default=False,
)
should_print_rates: bpy.props.BoolProperty(
name="Rates and totals",
description="Print rates and totals for each voice",
default=True,
)
should_print_summary: bpy.props.BoolProperty(
name="Final Summary",
description="Print summary at the end of the document",
default=True,
)
force_schedule_type: bpy.props.EnumProperty(
name="Output type",
description='Force the output to this type.\n"Auto" defaults to selected cost schedule Predefined Type',
items=[
(
"AUTO",
"By PredefinedType",
"Uses Cost Schedule Predefined Type",
),
(
"PRICEDBILLOFQUANTITIES",
"Priced Bill of Quantities",
"Forces the output as a priced bill of quantities",
),
(
"SCHEDULEOFRATES",
"Schedule of Rates",
"Forces the output as a schedule of rates",
),
],
default="AUTO",
)
def draw(self, context):
layout = self.layout
box = layout.box()
box.label(text="Select Ifc Cost Schedule:")
box.prop(self, "cost_schedules_enum", text="")
layout.separator()
box = layout.box()
box.label(text="Nested cost structure:")
box.prop(self, "nested_structure_depth")
layout.separator()
box = layout.box()
box.label(text="PDF Document properties:")
box.prop(self, "should_print_cover")
box.prop(self, "should_print_cost_ids")
box.prop(self, "should_print_description")
box.prop(self, "should_print_each_quantity")
box.prop(self, "should_print_rates")
box.prop(self, "should_print_summary")
box.prop(self, "force_schedule_type")
@classmethod
def poll(cls, context):
try:
import typst
return True
except:
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)"
)
return False
def invoke(self, context, event):
ExportCostSchedulesToPDF.cost_schedules_items.clear()
file = tool.Ifc.get()
schedules = file.by_type("IfcCostSchedule")
for schedule in schedules:
ExportCostSchedulesToPDF.cost_schedules_items.append(
(
str(schedule.id()),
"{} ({})".format(
schedule.Name if schedule.Name is not None else "Unnamed",
schedule.PredefinedType if schedule.PredefinedType is not None else "UNTYPED",
),
"",
)
)
return ExportHelper.invoke(self, context, event)
def execute(self, context):
file = tool.Ifc.get()
self.props = tool.Cost.get_cost_props()
cost_schedule = file.by_id(int(self.cost_schedules_enum))
options = {
"nested_structure_depth": self.nested_structure_depth,
"parent_to_new_page_up_to_depth": self.parent_to_new_page_up_to_depth,
"show_only_parents": self.show_only_parents,
"should_print_cover": self.should_print_cover,
"should_print_cost_ids": self.should_print_cost_ids,
"should_print_description": self.should_print_description,
"should_print_each_quantity": self.should_print_each_quantity,
"should_print_each_cost_value": self.should_print_each_cost_value,
"should_print_rates": self.should_print_rates,
"should_print_summary": self.should_print_summary,
}
core.export_cost_schedules_to_pdf(
tool.Cost,
filepath=self.filepath,
cost_schedule=cost_schedule,
options=options,
force_schedule_type=self.force_schedule_type,
)
return {"FINISHED"}
class ClearCostItemAssignments(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.clear_cost_item_assignments"
bl_label = "Clear Cost Item Product Assignments"
-11
View File
@@ -175,15 +175,6 @@ class CostItemQuantity(PropertyGroup):
total_cost_quantity: float
class CostSchedulesMapping(PropertyGroup):
cost_schedule_id: IntProperty(name="cost_schedule_id")
csv_filepath: StringProperty(name="filepath")
if TYPE_CHECKING:
cost_schedule_id: int
csv_filepath: str
class CostItemType(PropertyGroup):
name: StringProperty(name="Name")
ifc_definition_id: IntProperty(name="IFC Definition ID")
@@ -289,7 +280,6 @@ class BIMCostProperties(PropertyGroup):
custom_currency: StringProperty(
name="Custom Currency", default="USD", description="Custom Currency in ISO 4217 format"
)
cost_schedule_files: CollectionProperty(name="Cost Schedule Files", type=CostSchedulesMapping)
if TYPE_CHECKING:
cost_schedule_predefined_types: str
@@ -344,7 +334,6 @@ class BIMCostProperties(PropertyGroup):
show_cost_item_operators: bool
currency: str
custom_currency: str
cost_schedule_files: bpy.types.bpy_prop_collection_idprop[CostSchedulesMapping]
@property
def active_cost_item(self) -> Union[CostItem, None]:
+22 -19
View File
@@ -38,6 +38,8 @@ class BIM_PT_cost_schedules(Panel):
bl_parent_id = "BIM_PT_tab_cost"
bl_options = {"HIDE_HEADER"}
layout: bpy.types.UILayout
@classmethod
def poll(cls, context):
file = tool.Ifc.get()
@@ -53,6 +55,7 @@ class BIM_PT_cost_schedules(Panel):
if CostSchedulesData.data["total_cost_schedules"]:
row.alignment = "RIGHT"
row.operator("bim.export_cost_schedules", icon="EXPORT", text="Export All Schedules")
row.operator("bim.export_cost_schedules_to_pdf", icon="OUTPUT", text="")
row = self.layout.row(align=True)
row.label(text=f"{CostSchedulesData.data['total_cost_schedules']} Cost Schedules Found", icon="TEXT")
else:
@@ -76,17 +79,14 @@ class BIM_PT_cost_schedules(Panel):
col = row0.column()
col.label(text="Linked CSV:")
row_1 = col.row(align=True)
if self.props.active_cost_schedule_id in [item.cost_schedule_id for item in self.props.cost_schedule_files]:
file = next(
(
item.csv_filepath
for item in self.props.cost_schedule_files
if item.cost_schedule_id == self.props.active_cost_schedule_id
),
None,
)
row_1.label(text=file)
csv_filepaths = CostSchedulesData.data["csv_filepaths"]
file_path = csv_filepaths.get(self.props.active_cost_schedule_id)
if file_path:
row_1.label(text=file_path)
row_1.operator("bim.refresh_cost_schedule_csv", icon="FILE_REFRESH", text="")
row_1.operator("bim.remove_cost_schedule_csv_link", icon="X", text="")
else:
row_1.label(text="No CSV file found")
row_1.operator("bim.import_cost_schedule_csv", icon="IMPORT", text="")
@@ -129,6 +129,7 @@ class BIM_PT_cost_schedules(Panel):
row.operator("bim.enable_editing_cost_schedule_attributes", text="", icon="GREASEPENCIL").cost_schedule = (
cost_schedule["id"]
)
row.operator("bim.copy_cost_schedule", text="", icon="DUPLICATE").cost_schedule = cost_schedule["id"]
row.operator("bim.remove_cost_schedule", text="", icon="X").cost_schedule = cost_schedule["id"]
if self.props.active_cost_schedule_id == cost_schedule["id"]:
if self.props.is_editing == "COST_SCHEDULE_ATTRIBUTES":
@@ -140,13 +141,13 @@ class BIM_PT_cost_schedules(Panel):
self.draw_currency_ui()
self.draw_editable_cost_item_ui()
def draw_column_ui(self):
def draw_column_ui(self) -> None:
row = self.layout.row(align=True)
row.prop(self.props, "cost_column", text="")
row.operator("bim.add_cost_column", text="", icon="ADD").name = self.props.cost_column
self.layout.template_list("BIM_UL_cost_columns", "", self.props, "columns", self.props, "active_column_index")
def draw_currency_ui(self):
def draw_currency_ui(self) -> None:
row = self.layout.row(align=True)
if CostSchedulesData.data["currency"]:
text = "Currency used: {}".format(CostSchedulesData.data["currency"]["name"])
@@ -163,7 +164,7 @@ class BIM_PT_cost_schedules(Panel):
def draw_editable_cost_schedule_ui(self):
bonsai.bim.helper.draw_attributes(self.props.cost_schedule_attributes, self.layout)
def draw_editable_cost_item_ui(self):
def draw_editable_cost_item_ui(self) -> None:
row = self.layout.row(align=True)
row.alignment = "RIGHT"
ifc_definition_id = None
@@ -219,14 +220,14 @@ class BIM_PT_cost_schedules(Panel):
elif self.props.cost_item_editing_type == "VALUES":
self.draw_editable_cost_item_values_ui()
def draw_editable_cost_item_attributes_ui(self):
def draw_editable_cost_item_attributes_ui(self) -> None:
bonsai.bim.helper.draw_attributes(self.props.cost_item_attributes, self.layout)
def draw_editable_cost_item_quantities_ui(self, cost_item: dict[str, Any]):
quantities = CostSchedulesData.data["cost_quantities"]
row = self.layout.row(align=True)
# In IFC, all quantities of IfcCostTime should have 1 type.
if quantities:
if quantities and cost_item.get("QuantityType"):
quantity_class = cost_item["QuantityType"]
row.label(text=quantity_class)
else:
@@ -395,7 +396,7 @@ class BIM_PT_cost_item_types(Panel):
op.cost_item = cost_item.ifc_definition_id
rtprops = context.scene.BIMResourceTreeProperties
rprops = context.scene.BIMResourceProperties
rprops = tool.Resource.get_resource_props()
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")
@@ -554,9 +555,8 @@ class BIM_PT_cost_item_quantities(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 = context.scene.BIMResourceProperties
if rtprops.resources and rprops.active_resource_index < len(rtprops.resources):
active_resource = tool.Resource.get_resource_props().active_resource
if active_resource:
if has_quantity_names:
op = row2.operator("bim.assign_cost_item_quantity", text="", icon="PROPERTIES")
op.related_object_type = "RESOURCE"
@@ -734,6 +734,9 @@ class BIM_UL_cost_items_trait:
if cost_item["AssignedCostRate"] is not None:
op = row.operator("bim.show_assigned_cost_rate", text="", emboss=False, icon="ZOOM_IN")
identification = cost_item["AssignedCostRate"].Identification
op.parent_cost_schedule_name = CostSchedulesData.data["cost_items"][cost_item["AssignedCostRate"].id()][
"ParentCostSchedule"
].Name
op.assigned_rate_identification = identification if identification is not None else "XXX"
op.assigned_rate_name = cost_item["AssignedCostRate"].Name or ""
op.assigned_rate_description = cost_item["AssignedCostRate"].Description or ""
@@ -121,7 +121,14 @@ class CoveringToolUI:
if AuthoringData.data["ifc_classes"]:
row = cls.layout.row(align=True)
row.label(text="", icon="FILE_3D")
prop_with_search(row, cls.props, "relating_type_id", text="")
prop_with_search(
row,
cls.props,
"relating_type_id",
text="",
enable_relating_type_suggestions=True,
search_threshold=0,
)
row.operator("bim.launch_type_manager", icon=tool.Blender.TYPE_MANAGER_ICON, text="")
else:
row.label(text=f"No {AuthoringData.data['ifc_element_type']} Found", icon="ERROR")
@@ -34,13 +34,14 @@ class Login(bpy.types.Operator):
bl_options = {"REGISTER", "UNDO"}
def execute(self, context):
token = api.login(context.scene.CoveToolProperties.username, context.scene.CoveToolProperties.password)
props = tool.Blender.get_covetool_props()
token = api.login(props.username, props.password)
if token:
context.scene.CoveToolProperties.token = token
props.token = token
projects = api.get_request("projects")
for project in projects:
new_project = context.scene.CoveToolProperties.projects.add()
new_project = props.projects.add()
new_project.name = project["name"]
new_project.run_set = project["run_set"][0]
new_project.url = project["url"]
@@ -54,11 +55,10 @@ class RunSimpleAnalysis(bpy.types.Operator):
bl_label = "Run Simple Analysis"
def execute(self, context):
simple_analysis = context.scene.CoveToolProperties.simple_analysis
props = tool.Blender.get_covetool_props()
simple_analysis = props.simple_analysis
data = {
"run": context.scene.CoveToolProperties.projects[
context.scene.CoveToolProperties.active_project_index
].run_set,
"run": props.projects[props.active_project_index].run_set,
"si_units": simple_analysis.si_units,
"building_height": simple_analysis.building_height,
"roof_area": simple_analysis.roof_area,
@@ -92,6 +92,7 @@ class RunAnalysis(bpy.types.Operator):
bl_label = "Run Analysis"
def execute(self, context):
props = tool.Blender.get_covetool_props()
self.file = tool.Ifc.get()
self.inputs = {
"floors": [],
@@ -104,9 +105,7 @@ class RunAnalysis(bpy.types.Operator):
}
self.parse_objects(context)
data = {
"run": context.scene.CoveToolProperties.projects[
context.scene.CoveToolProperties.active_project_index
].run_set,
"run": props.projects[props.active_project_index].run_set,
"source": "Bonsai",
"rotation_angle": self.get_rotation_angle(),
**self.inputs,
+37 -3
View File
@@ -16,15 +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 bpy.props
import bpy.types
import bpy
from typing import TYPE_CHECKING
class CoveToolProject(bpy.types.PropertyGroup):
name: bpy.props.StringProperty(name="Name")
run_set: bpy.props.StringProperty(name="Run Set")
url: bpy.props.StringProperty(name="URL")
if TYPE_CHECKING:
run_set: str
url: set
class CoveToolSimpleAnalysis(bpy.types.PropertyGroup):
si_units: bpy.props.BoolProperty(name="SI Units")
@@ -49,6 +52,29 @@ class CoveToolSimpleAnalysis(bpy.types.PropertyGroup):
window_area_s: bpy.props.StringProperty(name="Window Area S")
window_area_se: bpy.props.StringProperty(name="Window Area SE")
if TYPE_CHECKING:
si_units: bool
building_height: str
roof_area: str
floor_area: str
skylight_area: str
wall_area_e: str
wall_area_ne: str
wall_area_n: str
wall_area_nw: str
wall_area_w: str
wall_area_sw: str
wall_area_s: str
wall_area_se: str
window_area_e: str
window_area_ne: str
window_area_n: str
window_area_nw: str
window_area_w: str
window_area_sw: str
window_area_s: str
window_area_se: str
class CoveToolProperties(bpy.types.PropertyGroup):
username: bpy.props.StringProperty(name="Username")
@@ -57,3 +83,11 @@ class CoveToolProperties(bpy.types.PropertyGroup):
projects: bpy.props.CollectionProperty(name="Projects", type=CoveToolProject)
active_project_index: bpy.props.IntProperty(name="Active Project Index")
simple_analysis: bpy.props.PointerProperty(type=CoveToolSimpleAnalysis)
if TYPE_CHECKING:
username: str
password: str
token: str
projects: bpy.types.bpy_prop_collection_idprop[CoveToolProject]
active_project_index: int
simple_analysis: CoveToolSimpleAnalysis
+17 -3
View File
@@ -16,7 +16,13 @@
# 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
import bpy.types
import bonsai.tool as tool
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from bonsai.bim.module.covetool.prop import CoveToolProperties, CoveToolProject
class BIM_PT_covetool(bpy.types.Panel):
@@ -32,8 +38,7 @@ class BIM_PT_covetool(bpy.types.Panel):
layout = self.layout
layout.use_property_split = True
scene = context.scene
props = scene.CoveToolProperties
props = tool.Blender.get_covetool_props()
if not props.token:
row = layout.row()
@@ -81,7 +86,16 @@ class BIM_PT_covetool(bpy.types.Panel):
class BIM_UL_covetool_projects(bpy.types.UIList):
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
def draw_item(
self,
context,
layout: bpy.types.UILayout,
data: CoveToolProperties,
item: CoveToolProject,
icon,
active_data,
active_propname,
) -> None:
ob = data
if item:
layout.prop(item, "name", text="", emboss=False)
+1 -1
View File
@@ -269,7 +269,7 @@ class ExportIfcCsv(bpy.types.Operator, ExportHelper):
schedule_creator = scheduler.Scheduler()
schedule_creator.schedule(self.filepath, tool.Drawing.get_path_with_ext(self.filepath, "svg"))
if props.format == "web":
if not context.scene.WebProperties.is_connected:
if not tool.Web.get_web_props().is_connected:
bpy.ops.bim.connect_websocket_server()
df = ifc_csv.dataframe
assert df is not None
+1
View File
@@ -32,6 +32,7 @@ class BIM_PT_ifccsv(Panel):
bl_parent_id = "BIM_PT_tab_collaboration"
def draw(self, context):
assert self.layout
layout = self.layout
props = tool.Blender.get_csv_props()
@@ -20,6 +20,7 @@ import bpy
from . import ui, prop, operator
classes = (
operator.ChangeLogLevel,
operator.ConvertToBlender,
operator.CopyDebugInformation,
operator.CreateAllShapes,

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