Compare commits

..

1 Commits

Author SHA1 Message Date
Ryan Schultz 7cd556bf6d Without 'Material.Name' layers merge. 2026-02-20 19:56:57 -06:00
1060 changed files with 36180 additions and 68329 deletions
+2 -3
View File
@@ -1,8 +1,7 @@
# yaml-language-server: $schema=https://raw.githubusercontent.com/BlankSpruce/gersemi/0.24.0/gersemi/configuration.schema.json
# Gersemi doesn't support autodetection of macros/functions from other files or from the current one
# and requires to explicitly list directories/cmake files that define them.
definitions: ["./cmake", "./src"]
# Needed for gersemi to detect custom functions and macros.
definitions: ["./cmake"]
disable_formatting: false
extensions: []
indent: 4
+8 -8
View File
@@ -40,8 +40,6 @@ jobs:
# preinstalled: xz, cmake
brew install git bison autoconf automake libffi findutils
echo "$(brew --prefix findutils)/libexec/gnubin" >> $GITHUB_PATH
# Mac is using bison 2.5 by default, but we need 3.5+ for swig.
echo "$(brew --prefix bison)/bin" >> $GITHUB_PATH
- name: Install aws cli
run: |
@@ -49,11 +47,11 @@ jobs:
- name: Unpack Dependencies
run: |
cd build
python ../nix/cache_dependencies.py unpack
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.2.21
uses: hendrikmuhs/ccache-action@v1.2
with:
key: mac-${{ matrix.arch }}
@@ -83,7 +81,7 @@ jobs:
- name: Upload Build Logs
if: always()
uses: actions/upload-artifact@v7
uses: actions/upload-artifact@v6
with:
name: build-logs-osx-${{ matrix.arch }}
path: |
@@ -95,7 +93,9 @@ jobs:
- name: Pack Dependencies
run: |
cd build
python ../nix/cache_dependencies.py pack
for install_dir in $(find $(find . -maxdepth 4 -name install) -mindepth 1 -maxdepth 1 -type d); do
test -f $(dirname "$install_dir")/cache-$(basename "$install_dir").tar.gz || tar -czf $(dirname "$install_dir")/cache-$(basename "$install_dir").tar.gz -C $(dirname "$install_dir") $(basename "$install_dir");
done
- name: Commit and Push Changes to Build Repository
run: |
@@ -139,7 +139,7 @@ jobs:
cd ..
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v6
uses: aws-actions/configure-aws-credentials@v5
with:
aws-access-key-id: ${{ secrets.AWS_UPLOAD_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_UPLOAD_SECRET_ACCESS_KEY }}
+5 -5
View File
@@ -26,10 +26,10 @@ jobs:
- name: Unpack Dependencies
run: |
cd ifcopenshell_build
python ../IfcOpenShell/nix/cache_dependencies.py unpack
python ../IfcOpenShell/pyodide/cache_dependencies.py unpack
- name: ccache
uses: hendrikmuhs/ccache-action@v1.2.21
uses: hendrikmuhs/ccache-action@v1.2
with:
key: ubuntu-22.04-${{ runner.arch }}
@@ -42,7 +42,7 @@ jobs:
- name: Upload Build Logs
if: always()
uses: actions/upload-artifact@v7
uses: actions/upload-artifact@v6
with:
name: build-logs-pyodide
path: |
@@ -65,7 +65,7 @@ jobs:
- name: Pack Dependencies
run: |
cd ifcopenshell_build
python ../IfcOpenShell/nix/cache_dependencies.py pack
python ../IfcOpenShell/pyodide/cache_dependencies.py pack
- name: Commit and Push Changes to Build Repository
run: |
@@ -77,7 +77,7 @@ jobs:
git push || echo "Push failed"
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v6
uses: aws-actions/configure-aws-credentials@v5
with:
aws-access-key-id: ${{ secrets.AWS_UPLOAD_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_UPLOAD_SECRET_ACCESS_KEY }}
+14 -11
View File
@@ -6,13 +6,13 @@ on:
jobs:
build_ifcopenshell:
runs-on: ubuntu-22.04
container: rockylinux:9
container: rockylinux:8
steps:
- name: Install Dependencies
run: |
dnf update -y
dnf install -y gcc gcc-c++ git autoconf automake bison make zip cmake python3 python3-pip \
yum update -y
yum install -y gcc gcc-c++ git autoconf automake bison make zip cmake python3 \
bzip2 patch mesa-libGL-devel libffi-devel fontconfig-devel \
sqlite-devel bzip2-devel zlib-devel openssl-devel xz-devel \
readline-devel ncurses-devel libffi-devel libuuid-devel git-lfs \
@@ -38,19 +38,20 @@ jobs:
with:
repository: IfcOpenShell/build-outputs
path: ./build
ref: rockylinux9-x64
ref: rockylinux8-x64
lfs: true
token: ${{ secrets.BUILD_REPO_TOKEN }}
- name: Unpack Dependencies
run: |
cd build
python3 ../nix/cache_dependencies.py unpack
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.2.21
# TODO: Use tag after 1.2.20 releases.
uses: hendrikmuhs/ccache-action@5ebbd400eff9e74630f759d94ddd7b6c26299639
with:
key: ubuntu-22.04-${{ runner.arch }}-rockylinux9
key: ubuntu-22.04-${{ runner.arch }}-rockylinux8
- name: Run Build Script
shell: bash
@@ -60,7 +61,7 @@ jobs:
- name: Upload Build Logs
if: always()
uses: actions/upload-artifact@v7
uses: actions/upload-artifact@v6
with:
name: build-logs-rocky
path: |
@@ -71,7 +72,9 @@ jobs:
- name: Pack Dependencies
run: |
cd build
python3 ../nix/cache_dependencies.py pack
for install_dir in $(find $(find . -maxdepth 4 -name install) -mindepth 1 -maxdepth 1 -type d); do
test -f $(dirname "$install_dir")/cache-$(basename "$install_dir").tar.gz || tar -czf $(dirname "$install_dir")/cache-$(basename "$install_dir").tar.gz -C $(dirname "$install_dir") $(basename "$install_dir");
done
- name: Commit and Push Changes to Build Repository
run: |
@@ -115,7 +118,7 @@ jobs:
cd ..
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v6
uses: aws-actions/configure-aws-credentials@v5
with:
aws-access-key-id: ${{ secrets.AWS_UPLOAD_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_UPLOAD_SECRET_ACCESS_KEY }}
+14 -11
View File
@@ -6,13 +6,13 @@ on:
jobs:
build_ifcopenshell:
runs-on: ubuntu-22.04-arm
container: arm64v8/rockylinux:9
container: arm64v8/rockylinux:8
steps:
- name: Install Dependencies
run: |
dnf update -y
dnf install -y gcc gcc-c++ git autoconf automake bison make zip cmake python3 python3-pip \
yum update -y
yum install -y gcc gcc-c++ git autoconf automake bison make zip cmake python3 \
bzip2 patch mesa-libGL-devel libffi-devel fontconfig-devel \
sqlite-devel bzip2-devel zlib-devel openssl-devel xz-devel \
readline-devel ncurses-devel libffi-devel libuuid-devel git-lfs \
@@ -38,19 +38,20 @@ jobs:
with:
repository: IfcOpenShell/build-outputs
path: ./build
ref: rockylinux9-arm64
ref: rockylinux8-arm64
lfs: true
token: ${{ secrets.BUILD_REPO_TOKEN }}
- name: Unpack Dependencies
run: |
cd build
python3 ../nix/cache_dependencies.py unpack
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.2.21
# TODO: Use tag after 1.2.20 releases.
uses: hendrikmuhs/ccache-action@5ebbd400eff9e74630f759d94ddd7b6c26299639
with:
key: ubuntu-22.04-${{ runner.arch }}-rockylinux9
key: ubuntu-22.04-${{ runner.arch }}-rockylinux8
- name: Run Build Script
shell: bash
@@ -60,7 +61,7 @@ jobs:
- name: Upload Build Logs
if: always()
uses: actions/upload-artifact@v7
uses: actions/upload-artifact@v6
with:
name: build-logs-rocky-arm64
path: |
@@ -71,7 +72,9 @@ jobs:
- name: Pack Dependencies
run: |
cd build
python3 ../nix/cache_dependencies.py pack
for install_dir in $(find $(find . -maxdepth 4 -name install) -mindepth 1 -maxdepth 1 -type d); do
test -f $(dirname "$install_dir")/cache-$(basename "$install_dir").tar.gz || tar -czf $(dirname "$install_dir")/cache-$(basename "$install_dir").tar.gz -C $(dirname "$install_dir") $(basename "$install_dir");
done
- name: Commit and Push Changes to Build Repository
run: |
@@ -115,7 +118,7 @@ jobs:
cd ..
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v6
uses: aws-actions/configure-aws-credentials@v5
with:
aws-access-key-id: ${{ secrets.AWS_UPLOAD_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_UPLOAD_SECRET_ACCESS_KEY }}
+12 -29
View File
@@ -5,26 +5,11 @@ on:
jobs:
build_ifcopenshell:
runs-on: windows-2022
strategy:
fail-fast: false
matrix:
include:
- arch: x64
runs_on: windows-2022
deps_dir: _deps-vs2022-x64-installed
vcvars: '"C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat"'
build_branch: windows-x64
zip_suffix: win64
- arch: ARM64
runs_on: windows-11-arm
deps_dir: _deps-vs2022-ARM64-installed
vcvars: '"C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsarm64.bat"'
build_branch: windows-arm64
zip_suffix: win-arm64
runs-on: ${{ matrix.runs_on }}
arch: ['x64']
steps:
- name: Checkout Repository
uses: actions/checkout@v6
@@ -35,8 +20,8 @@ jobs:
uses: actions/checkout@v6
with:
repository: IfcOpenShell/build-outputs
path: ${{ matrix.deps_dir }}
ref: ${{ matrix.build_branch }}
path: _deps-vs2022-x64-installed
ref: windows-${{ matrix.arch }}
lfs: true
token: ${{ secrets.BUILD_REPO_TOKEN }}
@@ -46,13 +31,14 @@ jobs:
- name: Unpack Dependencies
run: |
cd ${{ matrix.deps_dir }}
cd _deps-vs2022-x64-installed
Get-ChildItem -Path . -Filter 'cache-*.zip' | ForEach-Object {
7z x $_.FullName
}
- name: ccache
uses: hendrikmuhs/ccache-action@v1.2.21
# TODO: Use tag after 1.2.20 releases.
uses: hendrikmuhs/ccache-action@5ebbd400eff9e74630f759d94ddd7b6c26299639
with:
key: win-${{ matrix.arch }}
# Windows ccache needs ~1GB
@@ -61,16 +47,14 @@ jobs:
- name: Run Build Script And Pack .zip Archives
shell: cmd
env:
TARGET_ARCH: ${{ matrix.arch }} # lets the Python script know which arch to target (optional override)
run: |
call ${{ matrix.vcvars }}
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat"
cd win
python build-all-win.py
- name: Pack Dependencies
run: |
cd ${{ matrix.deps_dir }}
cd _deps-vs2022-x64-installed
Get-ChildItem -Path . -Directory | ForEach-Object {
$cacheFile = "cache-$($_.Name).zip"
echo $cacheFile
@@ -81,16 +65,15 @@ jobs:
- name: Commit and Push Changes to Build Repository
run: |
cd ${{ matrix.deps_dir }}
cd _deps-vs2022-x64-installed
git config user.name "IfcOpenBot"
git config user.email "ifcopenbot@ifcopenshell.org"
git checkout -B ${{ matrix.build_branch }}
git add *.zip
git commit -m "Update build artifacts [skip ci]" || echo "No changes to commit"
git push --set-upstream origin ${{ matrix.build_branch }} || echo "Push failed"
git push || echo "Push failed"
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v6
uses: aws-actions/configure-aws-credentials@v5
with:
aws-access-key-id: ${{ secrets.AWS_UPLOAD_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_UPLOAD_SECRET_ACCESS_KEY }}
+4 -9
View File
@@ -7,9 +7,6 @@ on:
jobs:
lint-formatting:
runs-on: ubuntu-latest
env:
MIN_IOS_PY_VERSION: "3.10"
MIN_BLENDER_PY_VERSION: "3.11"
steps:
- name: Action - checkout repository
uses: actions/checkout@v6
@@ -17,12 +14,12 @@ jobs:
- name: Action - install python
uses: actions/setup-python@v6
with:
python-version: ${{ env.MIN_IOS_PY_VERSION }}
python-version: "3.10"
- name: Action - install python
uses: actions/setup-python@v6
with:
python-version: ${{ env.MIN_BLENDER_PY_VERSION }}
python-version: "3.11"
- name: Install dependencies
run: |
@@ -36,10 +33,8 @@ jobs:
id: syntax-errors
run: |
ERROR=0
# Using 2 Python versions - one minimum required for IfcOpenShell
# and other that's used by Blender currently.
python${{ env.MIN_IOS_PY_VERSION }} -W error -m compileall -q src/ifcopenshell-python || ERROR=1
python${{ env.MIN_BLENDER_PY_VERSION }} -W error -m compileall -q src/bonsai || ERROR=1
python3.10 -W error -m compileall -q src/ifcopenshell-python || ERROR=1
python3.11 -W error -m compileall -q src/bonsai || ERROR=1
exit $ERROR
continue-on-error: true
+11 -16
View File
@@ -24,15 +24,9 @@ jobs:
runs-on: ubuntu-latest
if: |
github.repository == 'IfcOpenShell/IfcOpenShell'
outputs:
timestamp: ${{ steps.timestamp.outputs.timestamp }}
steps:
- name: Get current timestamp
id: timestamp
# Include hours and minutes to release tag
# to avoid possibility of unstable repo's index.json
# pointing to the new file when index.json itself wasn't yet updated.
run: echo "timestamp=$(date +'%y%m%d%H%M')" >> $GITHUB_OUTPUT
- name: Set env
run: echo ok go
build:
needs: activate
@@ -41,7 +35,7 @@ jobs:
strategy:
fail-fast: false
matrix:
pyver: [py311, py312, py313]
pyver: [py311, py312]
config:
- {
name: "Windows Build",
@@ -59,11 +53,6 @@ jobs:
name: "MacOS ARM Build",
short_name: macosm1,
}
exclude:
# Python 3.13 is needed for Blender 5.1+ and Blender dropped Intel Mac support in 5.0.
- pyver: py313
config:
short_name: macos
steps:
- uses: actions/checkout@v6
- uses: actions/setup-python@v6 # https://github.com/actions/setup-python
@@ -73,6 +62,12 @@ jobs:
- name: Get current version
id: version
run: echo "version=$(cat VERSION)" >> $GITHUB_OUTPUT
- name: Get current date
id: date
# Include hours and minutes to release tag
# to avoid possibility of unstable repo's index.json
# pointing to the new file when index.json itself wasn't yet updated.
run: echo "date=$(date +'%y%m%d%H%M')" >> $GITHUB_OUTPUT
- name: Compile
run: |
cd src/bonsai && make dist PLATFORM=${{ matrix.config.short_name }} PYVERSION=${{ matrix.pyver }}
@@ -88,8 +83,8 @@ jobs:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: ${{ steps.find_zip.outputs.filepath }}
asset_name: ${{ steps.find_zip.outputs.filename }}
release_name: "bonsai-${{steps.version.outputs.version}}-alpha${{ needs.activate.outputs.timestamp }} (unstable)"
tag: "bonsai-${{steps.version.outputs.version}}-alpha${{ needs.activate.outputs.timestamp }}"
release_name: "bonsai-${{steps.version.outputs.version}}-alpha${{steps.date.outputs.date}} (unstable)"
tag: "bonsai-${{steps.version.outputs.version}}-alpha${{steps.date.outputs.date}}"
overwrite: true
body: "See README in https://github.com/IfcOpenShell/bonsai_unstable_repo/ on how to setup autoupdates for daily Bonsai builds."
+7 -7
View File
@@ -35,7 +35,7 @@ jobs:
-
name: ccache
uses: hendrikmuhs/ccache-action@v1.2.21
uses: hendrikmuhs/ccache-action@v1.2
-
name: Build ifcopenshell
@@ -73,7 +73,7 @@ jobs:
make package
working-directory: build
- name: Upload
uses: actions/upload-artifact@v7
uses: actions/upload-artifact@v6
with:
# Artifact name
name: ifcos-artifacts
@@ -91,26 +91,26 @@ jobs:
lfs: true
- name: Download
uses: actions/download-artifact@v8.0.1
uses: actions/download-artifact@v7.0.0
with:
# Artifact name
name: ifcos-artifacts
path: artifacts/
-
name: Set up QEMU
uses: docker/setup-qemu-action@v4
uses: docker/setup-qemu-action@v3
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
uses: docker/setup-buildx-action@v3
-
name: Login to Dockerhub
uses: docker/login-action@v4
uses: docker/login-action@v3
with:
username: aecgeeks
password: ${{ secrets.DOCKER_HUB_TOKEN }}
-
name: Build container image
uses: docker/build-push-action@v7
uses: docker/build-push-action@v6
with:
context: artifacts
repository: aecgeeks/ifcopenshell
@@ -24,7 +24,7 @@ jobs:
strategy:
fail-fast: false
matrix:
pyver: [py310, py311, py312, py313, py314]
pyver: [py39, py310, py311, py312, py313, py314]
config:
- {
name: "Windows 64bit",
+1 -1
View File
@@ -19,7 +19,7 @@ jobs:
strategy:
fail-fast: false
matrix:
pyver: [py310, py311, py312, py313, py314]
pyver: [py39, py310, py311, py312, py313, py314]
config:
- {
name: "Windows 64bit",
+9 -26
View File
@@ -53,6 +53,7 @@ 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 git+https://github.com/zdhoward/aud
pip install pytest-xdist==3.8.0
- name: Install C++ dependencies
@@ -79,7 +80,10 @@ jobs:
libhdf5-dev libcgal-dev libeigen3-dev
- name: ccache
uses: hendrikmuhs/ccache-action@v1.2.21
# TODO: temporarily pointing to 1.2.19 to get notified by dependabot when 1.2.20 is released
# to update hardcoded references to commits in some other workflows.
# Then we can switch back to 1.2 in all actions.
uses: hendrikmuhs/ccache-action@v1.2.19
with:
key: ubuntu-22.04-${{ runner.arch }}
@@ -181,7 +185,6 @@ jobs:
"-DSCHEMA_VERSIONS=2x3;4;4x3_add2" \
-DGLTF_SUPPORT=On \
-DWITH_ROCKSDB=On \
-DBUILD_EXAMPLES=ON \
../cmake
sudo make -j $(nproc)
sudo make install
@@ -206,36 +209,17 @@ jobs:
- name: Build standalone examples to test cmake package
run: |
set -x
cd src/examples
mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache
cmake --build .
./arbitrary_open_profile_def && test -f arbitrary_open_profile_def.ifc
./composite_profile_def && test -f composite_profile_def.ifc
./csg_primitive && test -f csg_primitive.ifc
./ellipse_pies && test -f ellipse_pies.ifc
./faces && test -f faces.ifc
./ifc_curve_rebar && test -f ifc_curve_rebar.ifc
./profiles
test -f IfcUShapeProfileDef.ifc
test -f IfcTShapeProfileDef.ifc
test -f IfcZShapeProfileDef.ifc
test -f IfcEllipseProfileDef.ifc
test -f IfcIShapeProfileDef.ifc
test -f IfcLShapeProfileDef.ifc
test -f IfcCShapeProfileDef.ifc
test -f IfcCircleProfileDef.ifc
test -f IfcRectangleProfileDef.ifc
test -f IfcTrapeziumProfileDef.ifc
./IfcParseExamples "../IfcParseExamples_test.ifc"
./IfcOpenHouse && test -f IfcOpenHouse.ifc
./IfcAdvancedHouse && test -f IfcAdvancedHouse.ifc
./IfcAlignment && test -f IfcAlignment.ifc
./IfcSimplifiedAlignment && test -f IfcSimplifiedAlignment.ifc
./triangulated_faceset && test -f triangulated_faceset.ifc
./IfcOpenHouse
./IfcAdvancedHouse
./IfcAlignment
./IfcSimplifiedAlignment
- name: Test ifcopenshell-python
run: |
@@ -254,7 +238,6 @@ jobs:
cd ../ifcpatch && make test || ERROR=1
pip install -e ../ifctester --no-deps
cd ../ifctester && make test || ERROR=1
make build-ids-docs || ERROR=1
# Run mathutils related tests at the end to ensure no other code is relying on mathutils.
cd ../ifcopenshell-python
pip install mathutils
+1 -16
View File
@@ -5,8 +5,6 @@
/_installed-vs*-x*/
/build/
/src/examples/build/
# ifctester docs output
/src/ifctester/test/build/
# output directories
/cmake/out/
@@ -14,7 +12,6 @@
/src/ifcmax/out/
/src/ifcwrap/out/
/src/qtviewer/out/
/src/ifctester/webapp/public/pyodide/
/win/BuildDepsCache*.txt
@@ -83,14 +80,8 @@ src/ifcopenshell-python/test/build
# bonsai i18n
src/bonsai/bonsai/translations.py
# bonsai external dependencies (cloned for just ty checks)
src/bonsai/external_dependencies/
# bonsai test temp/cache files
# bonsai test temp files
src/bonsai/test/files/temp
src/bonsai/test/files/*.cache.blend
src/bonsai/test/files/*.cache.json
src/bonsai/test/files/*.cache.sqlite
# bonsai data
src/bonsai/bonsai/bim/data/build/
@@ -122,9 +113,3 @@ dev_environment.bat
src/ifcopenshell-python/ifcopenshell/express/*.exp
src/ifcopenshell-python/ifcopenshell/express/*.exp.cache.dat
# temp files from AI coding tools
*.claude
*.py.tmp*
*.json.tmp*
-153
View File
@@ -1,153 +0,0 @@
<!-- This file was generated with the assistance of an AI coding tool. -->
# AGENTS.md
Guidelines for AI coding agents contributing to IfcOpenShell. This file is
intended to be read by all AI agents regardless of platform (Claude Code,
Copilot, Cursor, etc.) in addition to any tool-specific configuration files.
Human contributors using AI tools should also read this document carefully,
as they are responsible for ensuring their contributions comply with these
guidelines.
## Project Overview
IfcOpenShell is an open source library for working with Industry Foundation
Classes (IFC). It provides C++ and Python APIs, geometry processing, and an
ecosystem of tools including IfcConvert and the Bonsai Blender add-on.
## Licensing
All contributions must be compatible with the project's licensing:
- **Library code** (everything except Bonsai): **LGPL-3.0-or-later**
- **Bonsai** (`src/bonsai/`): **GPL-3.0-or-later**
There is no Contributor License Agreement (CLA). By submitting a pull request,
you agree that your contribution is licensed under the applicable license above.
## Indicating AI-Generated Code
Contributors must clearly indicate when code has been generated or
substantially written by an AI tool.
### Commits
Commits that modify existing code must include a note in the **body** of the
commit message (not the subject line) indicating that the change was
AI-generated. For example:
```
Fix off-by-one error in element iteration
The loop termination condition was incorrect when processing
IfcRelAggregates relationships.
Generated with the assistance of an AI coding tool.
```
### New Files
New files that are AI-generated must include a comment near the top of the
file indicating this. Use the appropriate comment syntax for the language:
```python
# This file was generated with the assistance of an AI coding tool.
```
```cpp
// This file was generated with the assistance of an AI coding tool.
```
### Pull Requests
Pull requests containing AI-generated code must indicate in the PR description
which parts of the contribution are AI-generated. If the entire PR is
AI-generated, state that clearly. If only specific commits or files are
AI-generated, identify them.
## Pull Request Guidelines
### Scope and Size
- Each pull request should address a **single issue or feature**.
- Do not mix unrelated changes (e.g., bug fixes with refactoring or style
changes) in the same PR.
- Large pull requests should be broken down into **multiple small, standalone
commits** that are each easy to review independently. Rewrite commit history
for this purpose if necessary.
- PRs that are minimal, focused solutions to a specific problem are much more
likely to be accepted.
### What to Avoid
- **Over-engineering**: Do not add features, abstractions, or configurability
beyond what is needed to solve the immediate problem.
- **Scope creep**: Do not make changes to files or code that are not directly
related to the task at hand.
- **Unnecessary additions**: Do not add docstrings, comments, type annotations,
or error handling to code you did not otherwise need to change.
- **Cosmetic changes**: Do not reformat, rename, or reorganize code that is
unrelated to your change.
## Commit Messages
- The **subject line** must be **50 characters or less**.
- Use the **imperative mood** (e.g., "Fix crash in geometry kernel", not
"Fixed crash" or "Fixes crash").
- A commit message can be a single line if the purpose is obvious from the
subject alone.
- Otherwise, add a blank line after the subject followed by a short explanation
of a few lines in the body.
## Code Style
### Python
- **Line length**: 120 characters
- **Formatter**: black
- **Linter**: ruff
- Configuration is in `pyproject.toml`
### C++
- **Standard**: C++17 minimum
- **Formatter**: clang-format (configuration in `.clang-format`)
- **Linter**: clang-tidy (configuration in `.clang-tidy`)
Run linters and formatters **before submitting** your pull request. Do not rely
on CI to catch formatting issues.
## Testing
- Pull requests with test coverage are **much more likely to be merged**.
- If tests are appropriate and feasible for your change, they should be
included.
- Tests are not required for every change (e.g., documentation-only changes),
but the expectation is that testable code changes come with tests.
- Python tests use **pytest** and are located in `test/` or `tests/` directories
within each package under `src/`.
- Run the existing test suite for the package you modified before submitting.
## Architecture Quick Reference
### Directory Structure
- `src/ifcparse/` — C++ IFC file parsing
- `src/ifcgeom/` — C++ geometry processing (OpenCASCADE and CGAL kernels)
- `src/serializers/` — Output format serializers (glTF, Collada, SVG, etc.)
- `src/ifcwrap/` — SWIG Python bindings
- `src/ifcconvert/` — CLI conversion tool
- `src/ifcopenshell-python/` — Python API (`ifcopenshell` package)
- `src/bonsai/` — Blender add-on (GPL-3.0-or-later)
- `src/ifctester/` — IDS model auditing
- `src/ifcpatch/` — IFC file manipulation scripts
- `src/ifcdiff/` — IFC model comparison
- `src/ifcclash/` — Clash detection
- `src/ifccsv/` — Schedule import/export
### IFC Schema Versions
The library supports IFC2x3 TC1, IFC4 Add2 TC1, IFC4x1, IFC4x2, and
IFC4x3 Add2. Schema-specific code is compiled conditionally. Be aware of
which schema versions your change affects.
+10 -19
View File
@@ -13,7 +13,6 @@ import hashlib
import os
import pathlib
import re
import subprocess
from typing import NoReturn
from urllib import request
@@ -21,7 +20,7 @@ from github import Github
def get_repo_tag_names() -> list[str]:
git_return = subprocess.check_output("git tag -l", text=True)
git_return = os.popen("git tag -l").read()
tag_names = [tag_name for tag_name in git_return.split("\n") if tag_name]
print(f"{len(tag_names)} tag_names found in repo")
return tag_names
@@ -79,10 +78,6 @@ def get_release_zip(tag: str) -> tuple[str, str]:
raise Exception(f"Couldn't find the release matching '{python_version}' and '{TARGET_OS}' in tag '{tag}'.")
def run(command: str) -> None:
subprocess.check_output(command)
start = datetime.datetime.now()
URL_CHOCO_PACKAGE = "https://community.chocolatey.org/packages/blender"
@@ -102,7 +97,7 @@ should_release = False
target_release_tag = ""
TARGET_OS = "windows-x64"
git_status = subprocess.check_output("git status", text=True)
git_status = os.popen("git status").read()
print(git_status)
for tag_name in get_repo_tag_names():
@@ -152,7 +147,7 @@ blenderbim_build_version = target_release_tag.replace("blenderbim-", "")
# url_blenderbim_py3x_win_zip
release_zip_file_name, url_blenderbim_py3x_win_zip = get_release_zip(target_release_tag)
subprocess.check_call(f"wget {url_blenderbim_py3x_win_zip} --no-verbose")
os.popen(f"wget {url_blenderbim_py3x_win_zip} --no-verbose").read()
# sha256sum_blenderbim_py310_win_zip
sha256sum_blenderbim_py3x_win_zip = get_file_sha256_hash(release_zip_file_name)
@@ -206,13 +201,13 @@ print("[INFO] inserting dynamic chocolatey package parameters successful")
print("\n_____ build choco.exe with mono")
choco_version = "1.1.0"
run(f"wget https://github.com/chocolatey/choco/archive/refs/tags/{choco_version}.tar.gz --quiet")
run(f"tar -xzf {choco_version}.tar.gz")
os.popen(f"wget https://github.com/chocolatey/choco/archive/refs/tags/{choco_version}.tar.gz --quiet").read()
os.popen(f"tar -xzf {choco_version}.tar.gz").read()
print("choco tar unpack successful")
os.chdir("choco-1.1.0")
run("./build.sh")
os.popen("./build.sh").read()
run("cp -r build_output/chocolatey /opt/chocolatey")
os.popen("cp -r build_output/chocolatey /opt/chocolatey").read()
os.chdir(BLENDERBIM_DIR)
if pathlib.Path("/opt/chocolatey/choco.exe").exists():
@@ -220,15 +215,11 @@ if pathlib.Path("/opt/chocolatey/choco.exe").exists():
print("\n_____ build choco pack")
run("mono /opt/chocolatey/choco.exe pack --allow-unofficial")
run(
'mono /opt/chocolatey/choco.exe setapikey --key="{choco_token}" --source="https://push.chocolatey.org/" --allow-unofficial'
)
os.popen("mono /opt/chocolatey/choco.exe pack --allow-unofficial").read()
os.popen('mono /opt/chocolatey/choco.exe setapikey --key="{choco_token}" --source="https://push.chocolatey.org/" --allow-unofficial').read()
print("\n_____ build choco push")
run(
'mono /opt/chocolatey/choco.exe push --source="https://push.chocolatey.org/" --key="$CHOCO_TOKEN" --allow-unofficial --verbose'
)
os.popen('mono /opt/chocolatey/choco.exe push --source="https://push.chocolatey.org/" --key="$CHOCO_TOKEN" --allow-unofficial --verbose').read()
print(f"choco push of version: {target_release_tag} successful!")
print(f"it took: {datetime.datetime.now() - start}")
+10 -18
View File
@@ -80,7 +80,7 @@ option(BUILD_IFCGEOM "Build IfcGeom." ON)
option(BUILD_IFCPYTHON "Build IfcPython." ON)
option(BUILD_CONVERT "Build IfcConvert executable." ON)
option(BUILD_DOCUMENTATION "Build IfcOpenShell Documentation." OFF)
option(BUILD_EXAMPLES "Build example applications." OFF)
option(BUILD_EXAMPLES "Build example applications." 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
@@ -258,10 +258,10 @@ if(WITH_ROCKSDB)
set(ROCKSDB_LIBRARIES "IFCOPENSHELL_RocksDB")
target_compile_definitions(IFCOPENSHELL_RocksDB INTERFACE IFOPSH_WITH_ROCKSDB)
set(SWIG_DEFINES ${SWIG_DEFINES} -DIFOPSH_WITH_ROCKSDB)
# Shared binaries for `rocksdb` only support limited API (only `c.h`), but we use `db.h` API.
# So rocksdb supported only as a static library.
# See https://github.com/facebook/rocksdb/issues/981.
target_link_libraries(IFCOPENSHELL_RocksDB INTERFACE RocksDB::rocksdb)
target_link_libraries(
IFCOPENSHELL_RocksDB
INTERFACE $<IF:$<TARGET_EXISTS:RocksDB::rocksdb-shared>,RocksDB::rocksdb-shared,RocksDB::rocksdb>
)
if(WITH_ZSTD)
# @todo do we actually need the zstd include dir or rather just pass
@@ -368,20 +368,12 @@ if(ENABLE_BUILD_OPTIMIZATIONS)
# Linker
# /OPT:REF enables also /OPT:ICF and disables INCREMENTAL
set(LINKER_FLAGS_RELEASE "/LTCG /OPT:REF")
# /OPT:NOICF is recommended when /DEBUG is used (http://msdn.microsoft.com/en-us/library/xe4t6fc1.aspx)
set(LINKER_FLAGS_RELWITHDEBINFO "/DEBUG /OPT:NOICF")
set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /LTCG /OPT:REF")
set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} ${LINKER_FLAGS_RELEASE}")
set(CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO
"${CMAKE_SHARED_LINKER_FLAGS_RELEASE} ${LINKER_FLAGS_RELWITHDEBINFO}"
)
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} ${LINKER_FLAGS_RELEASE}")
set(CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_EXE_LINKER_FLAGS_RELEASE} ${LINKER_FLAGS_RELWITHDEBINFO}")
set(CMAKE_MODULE_LINKER_FLAGS_RELEASE "${CMAKE_MODULE_LINKER_FLAGS_RELEASE} ${LINKER_FLAGS_RELEASE}")
set(CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO
"${CMAKE_MODULE_LINKER_FLAGS_RELEASE} ${LINKER_FLAGS_RELWITHDEBINFO}"
)
# /OPT:NOICF is recommended when /DEBUG is used (http://msdn.microsoft.com/en-us/library/xe4t6fc1.aspx)
set(CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /DEBUG /OPT:NOICF")
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /LTCG /OPT:REF")
set(CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /DEBUG /OPT:NOICF")
else()
# GCC-like: Release should use O3 but RelWithDebInfo 02 so enforce 03. Anything other useful that could be added here?
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3")
-11
View File
@@ -43,17 +43,6 @@ if(NOT OCC_INCLUDE_DIR AND NOT OCC_LIBRARY_DIR)
set_target_properties(TKernel PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${OpenCASCADE_INCLUDE_DIR}")
endif()
if(
OpenCASCADE_VERSION VERSION_LESS "7.9.0"
AND CMAKE_VERSION GREATER_EQUAL "3.24"
AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU"
)
# Before 7.9.0 targets in OCCT cmake configs are not linked to each other
# leading to missing symbols on Unix. Link them as a single group as a workaround.
# Only needed for gcc, because other compilers (e.g. Apple Clang, MSVC) do rescan automatically.
set(OpenCASCADE_LIBRARIES "$<LINK_GROUP:RESCAN,${OpenCASCADE_LIBRARIES}>")
endif()
if(OpenCASCADE_VERSION VERSION_LESS "7.9.0" AND WIN32)
# Bug in OCCT cmake configs < 7.9.0 - missing linked library.
list(APPEND OpenCASCADE_LIBRARIES WSOCK32.lib)
+5 -9
View File
@@ -13,14 +13,7 @@ include(CMakeFindDependencyMacro)
set(Boost_USE_STATIC_LIBS ON)
set(Boost_USE_STATIC_RUNTIME OFF)
set(Boost_USE_MULTITHREADED ON)
set(Boost_COMPONENTS
system
program_options
regex
thread
date_time
iostreams
)
set(Boost_COMPONENTS system program_options regex thread date_time iostreams)
find_dependency(Boost CONFIG COMPONENTS ${Boost_COMPONENTS})
find_dependency(Eigen3 CONFIG)
@@ -46,6 +39,7 @@ if(IFCOPENSHELL_IFCXML)
find_dependency(LibXml2 CONFIG)
endif()
if(IFCOPENSHELL_WITH_CGAL)
find_dependency(CGAL CONFIG)
endif()
@@ -54,7 +48,9 @@ if(IFCOPENSHELL_WITH_OPENCASCADE)
find_dependency(OpenCASCADE CONFIG)
if(OpenCASCADE_VERSION VERSION_LESS "7.7.0")
# cmake configs < 7.7.0 were not adding include directories to targets automatically.
set_target_properties(TKernel PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${OpenCASCADE_INCLUDE_DIR}")
set_target_properties(TKernel PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${OpenCASCADE_INCLUDE_DIR}"
)
endif()
endif()
+13 -6
View File
@@ -25,12 +25,19 @@ file(READ "@CMAKE_BINARY_DIR@/install_manifest.txt" files)
string(REGEX REPLACE "\n" ";" files "${files}")
foreach(file ${files})
set(filepath "$ENV{DESTDIR}${file}")
message(STATUS "Uninstalling ${filepath}")
message(STATUS "Uninstalling $ENV{DESTDIR}${file}")
if(IS_SYMLINK "${filepath}" OR EXISTS "${filepath}")
file(REMOVE "${filepath}")
else(NOT EXISTS "${filepath}")
message(STATUS "File ${filepath} does not exist.")
if(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
exec_program(
"@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\""
OUTPUT_VARIABLE rm_out
RETURN_VALUE rm_retval
)
if(NOT "${rm_retval}" STREQUAL 0)
message(FATAL_ERROR "Problem when removing $ENV{DESTDIR}${file}")
endif()
else(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
message(STATUS "File $ENV{DESTDIR}${file} does not exist.")
endif()
endforeach()
+24 -19
View File
@@ -1,10 +1,14 @@
#Look for an executable called sphinx-build
find_program(SPHINX_EXECUTABLE NAMES sphinx-build DOC "Path to sphinx-build executable")
find_program(SPHINX_EXECUTABLE
NAMES sphinx-build
DOC "Path to sphinx-build executable")
include(FindPackageHandleStandardArgs)
#Handle standard arguments to find_package like REQUIRED and QUIET
find_package_handle_standard_args(Sphinx "Failed to find sphinx-build executable" SPHINX_EXECUTABLE)
find_package_handle_standard_args(Sphinx
"Failed to find sphinx-build executable"
SPHINX_EXECUTABLE)
find_package(Doxygen REQUIRED)
#find_package(Sphinx REQUIRED)
@@ -12,24 +16,25 @@ find_package(Doxygen REQUIRED)
set(SPHINX_SOURCE ${CMAKE_CURRENT_SOURCE_DIR})
set(SPHINX_BUILD ${CMAKE_CURRENT_BINARY_DIR}/docs/sphinx)
message(STATUS "SPHINX BUILD ${CMAKE_CURRENT_BINARY_DIR}")
MESSAGE(STATUS "SPHINX BUILD ${CMAKE_CURRENT_BINARY_DIR}")
file(MAKE_DIRECTORY ./output/doxygen)
if(DOXYGEN_FOUND)
add_custom_target(
Sphinx
ALL
COMMAND ${SPHINX_EXECUTABLE} -v -T -b html ${SPHINX_SOURCE} ${CMAKE_CURRENT_SOURCE_DIR}/output
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/output
COMMENT "Generating documentation with Sphinx"
)
if (DOXYGEN_FOUND)
# add_custom_target(ifcopenshell_python_docs ALL
# COMMAND make html
# WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/../src/ifcblenderexport/docs
# OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/../src/ifcblenderexport/docs
# COMMENT "Generating documentation with Sphinx")
else(DOXYGEN_FOUND)
message("Doxygen need to be installed to generate the doxygen documentation")
endif(DOXYGEN_FOUND)
add_custom_target(Sphinx ALL
COMMAND
${SPHINX_EXECUTABLE} -v -T -b html
${SPHINX_SOURCE} ${CMAKE_CURRENT_SOURCE_DIR}/output
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/output
COMMENT "Generating documentation with Sphinx")
# add_custom_target(ifcopenshell_python_docs ALL
# COMMAND make html
# WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/../src/ifcblenderexport/docs
# OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/../src/ifcblenderexport/docs
# COMMENT "Generating documentation with Sphinx")
else (DOXYGEN_FOUND)
message("Doxygen need to be installed to generate the doxygen documentation")
endif (DOXYGEN_FOUND)
+77 -62
View File
@@ -75,30 +75,27 @@ Used environment variables:
# #
# for python37 to install correctly additionally: #
# * libffi(-dev[el]) #
# for Python build we also needs ssl and zlib #
# for Python build we also needs ssl #
# (since we do `pip install numpy` at the end) #
# * libssl-dev #
# #
# on debian 7.8 these can be obtained with: #
# $ apt-get install git gcc g++ autoconf bison bzip2 cmake #
# mesa-common-dev libffi-dev libfontconfig1-dev #
# libssl-dev xz zlib1g-dev #
# libssl-dev xz #
# #
# on ubuntu 14.04: #
# $ apt-get install git gcc g++ autoconf bison make cmake #
# mesa-common-dev libffi-dev libfontconfig1-dev #
# libssl-dev xz-utils zlib1g-dev #
# libssl-dev xz-utils #
# #
# on OS X El Capitan with homebrew: #
# $ brew install git bison autoconf automake libffi cmake #
# $ # `bison` shipped with Mac is too old for swig build, #
# $ # so we use `brew`. #
# $ export PATH=$(brew --prefix bison)/bin:$PATH #
# #
# on RHEL-related distros: #
# $ dnf install git gcc gcc-c++ autoconf bison make cmake #
# $ yum install git gcc gcc-c++ autoconf bison make cmake #
# mesa-libGL-devel libffi-devel fontconfig-devel bzip2 #
# automake patch byacc xz zlib-devel openssl-devel #
# automake patch byacc xz #
"""
@@ -150,8 +147,9 @@ OCCT_VERSION = "7.8.1"
BOOST_VERSION = "1.86.0"
EIGEN_VERSION = "3.4.0"
PCRE_VERSION = "8.41"
PCRE2_VERSION = "10.32"
LIBXML2_VERSION = "2.13.8"
SWIG_VERSION = "4.2.1"
SWIG_VERSION = "4.1.0"
OPENCOLLADA_VERSION = "v1.6.68"
HDF5_VERSION = "1.13.1"
@@ -248,8 +246,15 @@ if WASM:
# https://github.com/pyodide/pyodide-build/pull/249
WASM_CMAKE_IS_USING_INIT_VARS = get_pyodide_build_version() >= (99, 0, 0)
# 0.31 is required for SIDE_MODULE_CXXFLAGS to be provided.
assert get_pyodide_build_version() >= (0, 31)
# pyodide provide empty `CXXFLAGS`, leading to issues using C++ files compiled with `-fexceptions`
# which is used by OCCT.
# https://github.com/pyodide/pyodide-build/issues/251
side_module_cxx_flags = os.environ.get("SIDE_MODULE_CXXFLAGS", "")
if side_module_cxx_flags.strip():
print("SIDE_MODULE_CXXFLAGS are already passed from pyodide build ('{side_module_cxx_flags}').")
print("Maybe it's time to stop overriding them in the script?")
os.environ["SIDE_MODULE_CXXFLAGS"] = os.environ["SIDE_MODULE_CFLAGS"]
# Set defaults for missing empty environment variables
@@ -289,7 +294,6 @@ DEPS_DIR = os.getenv("DEPS_DIR", DEFAULT_DEPS_DIR)
if not os.path.exists(DEPS_DIR):
os.makedirs(DEPS_DIR)
INSTALL_DIR = Path(DEPS_DIR) / "install"
BUILD_CFG = os.getenv("BUILD_CFG", "RelWithDebInfo")
@@ -315,18 +319,24 @@ cecho(f"* Build Directory = {BUILD_DIR}", MAGENTA)
cecho(f"* Dependency Directory = {DEPS_DIR}", MAGENTA)
cecho(f" - The directory where {PROJECT_NAME} dependencies are installed.")
cecho(f"* Build Config Type = {BUILD_CFG}", MAGENTA)
cecho(""" - The used build configuration type for the dependencies.
Defaults to RelWithDebInfo if not specified.""")
cecho(
""" - The used build configuration type for the dependencies.
Defaults to RelWithDebInfo if not specified."""
)
if BUILD_CFG == "MinSizeRel":
cecho(" WARNING: MinSizeRel build can suffer from a significant performance loss.", RED)
cecho(f"* IFCOS_NUM_BUILD_PROCS = {IFCOS_NUM_BUILD_PROCS}", MAGENTA)
cecho(""" - How many compiler processes may be run in parallel.
""")
cecho(
""" - How many compiler processes may be run in parallel.
"""
)
cecho(f" * IFCOS_SCHEMAS = '{os.environ.get('IFCOS_SCHEMAS')}'", MAGENTA)
cecho(""" - IFC Schemas to compile. If not provided, fallback to default provided in cmake.
""")
cecho(
""" - IFC Schemas to compile. If not provided, fallback to default provided in cmake.
"""
)
dependency_tree: "dict[str, tuple[str, ...]]" = {
"IfcParse": ("boost", "libxml2", "hdf5", "rocksdb"),
@@ -335,12 +345,13 @@ dependency_tree: "dict[str, tuple[str, ...]]" = {
"OpenCOLLADA": ("libxml2", "pcre"),
"IfcGeomServer": ("IfcGeom",),
"IfcOpenShell-Python": ("python", "swig", "IfcGeom"),
"swig": (),
"swig": ("pcre2",),
"boost": (),
"libxml2": (),
"python": (),
"occ": (),
"pcre": (),
"pcre2": (),
"json": (),
"hdf5": (),
"cgal": (),
@@ -407,6 +418,7 @@ if WASM:
"opencollada",
"swig",
"pcre",
"pcre2",
"IfcGeom",
"IfcConvert",
"IfcGeomServer",
@@ -421,16 +433,13 @@ print("Building:", *sorted(targets, key=lambda t: len(list(gather_dependencies(t
# Check that required tools are in PATH
yacc = "yacc" # Used during swig building process, installed with `bison` on Debian / `byacc` on Red Hat.
bison = "bison"
missing_commands: "list[str]" = []
required_commands = [git, bunzip2, tar, cc, cplusplus, autoconf, automake, make, "patch", "cmake", yacc, xz, bison]
required_commands = [git, bunzip2, tar, cc, cplusplus, autoconf, automake, make, "patch", "cmake", yacc, xz]
if "wasm" in flags:
# Skip swig build for WASM.
required_commands.append("swig")
required_commands.append("pyodide")
required_commands.remove(yacc)
required_commands.remove(bison)
for cmd in required_commands:
if shutil.which(cmd) is None:
@@ -489,7 +498,7 @@ def run(cmds: "Sequence[str]", cwd: "Union[str, None]" = None, can_fail: bool =
collector.append(line)
pipe.close()
logger.debug(f"running command `{' '.join(cmds)}` in directory '{cwd}'")
logger.debug(f"running command {' '.join(cmds)} in directory {cwd}")
stdout: list[str] = []
stderr: list[str] = []
@@ -535,14 +544,14 @@ BOOST_LOCATION = f"https://github.com/boostorg/boost/releases/download/boost-{BO
# Helper functions
def run_autoconf(dependency_name: str, configure_args: "list[str]", cwd: str) -> None:
def run_autoconf(arg1: str, configure_args: "list[str]", cwd: str) -> None:
configure_path = os.path.realpath(os.path.join(cwd, "..", "configure"))
if not os.path.exists(configure_path):
run(
[bash, "./autogen.sh"], cwd=os.path.realpath(os.path.join(cwd, ".."))
) # only run autogen.sh in the directory it is located and use cwd to achieve that in order to not mess up things
# Using `sh` over `bash` fixes issues with building swig
prefix = os.path.realpath(f"{DEPS_DIR}/install/{dependency_name}")
prefix = os.path.realpath(f"{DEPS_DIR}/install/{arg1}")
wasm = []
if "wasm" in flags:
@@ -921,15 +930,20 @@ if "pcre" in targets:
restore_env("CC", OLD_CC)
restore_env("CXX", OLD_CXX)
if "swig" in targets:
dependency_name = f"swig-{SWIG_VERSION}"
if "pcre2" in targets:
build_dependency(
name=dependency_name,
mode="cmake",
build_tool_args=[
"-DWITH_PCRE=OFF",
f"-DCMAKE_INSTALL_PREFIX={DEPS_DIR}/install/{dependency_name}",
],
name=f"pcre2-{PCRE2_VERSION}",
mode="autoconf",
build_tool_args=[DISABLE_FLAG],
download_url=f"https://downloads.sourceforge.net/project/pcre/pcre2/{PCRE2_VERSION}/",
download_name=f"pcre2-{PCRE2_VERSION}.tar.bz2",
)
if "swig" in targets:
build_dependency(
name=f"swig-{SWIG_VERSION}",
mode="autoconf",
build_tool_args=["--disable-ccache", f"--with-pcre2-prefix={DEPS_DIR}/install/pcre2-{PCRE2_VERSION}"],
download_url="https://github.com/swig/swig.git",
download_name="swig",
download_tool=download_tool_git,
@@ -937,18 +951,21 @@ if "swig" in targets:
)
if USE_OCCT and "occ" in targets:
occt_args: "list[str]" = []
patches: "list[str]" = []
patches = []
if OCCT_VERSION < "7.4":
patches.append("./patches/occt/enable-exception-handling.patch")
# Skip ExpToCasExe as we don't need it and it requires additional dependencies.
# Before 7.7.2 ExpToCasExe is part of DataExchange, DETools doesn't exist yet.
# Since we do need DataExchange (used for IgesSerializer), we use a patch to skip only ExpToCasExe.
if "7.7.2" > OCCT_VERSION >= "7.7":
if OCCT_VERSION == "7.7.1":
patches.append("./patches/occt/no_ExpToCasExe.patch")
elif OCCT_VERSION >= "7.7.2":
occt_args.append("-DBUILD_MODULE_DETools=OFF")
if OCCT_VERSION == "7.7.2":
patches.append("./patches/occt/no_ExpToCasExe_7_7_2.patch")
if OCCT_VERSION == "7.8.1":
patches.append("./patches/occt/no_ExpToCasExe_7_8_1.patch")
if OCCT_VERSION == "7.9.1":
patches.append("./patches/occt/no_ExpToCasExe_7_9_1.patch")
if "wasm" in flags:
patches.append("./patches/occt/no_em_js.patch")
@@ -969,7 +986,6 @@ if USE_OCCT and "occ" in targets:
f"-DUSE_GLES2=OFF",
f"-DCMAKE_POLICY_VERSION_MINIMUM=3.5",
*MAC_CROSS_COMPILE_INTEL_ARGS,
*occt_args,
],
download_url="https://github.com/Open-Cascade-SAS/OCCT",
download_name="occt",
@@ -1085,19 +1101,23 @@ if "python" in targets and not USE_CURRENT_PYTHON_VERSION and "wasm" not in flag
PYTHON_CONFIGURE_ARGS.extend(["--with-universal-archs=intel-64", "--enable-universalsdk"])
for PYTHON_VERSION in PYTHON_VERSIONS:
# Don't fail silently on missing Python dependencies (e.g. openssl or zlib),
# because later ifcopenshell-python build will fail too but in a more confusing way.
build_dependency(
f"python-{PYTHON_VERSION}",
"autoconf",
PYTHON_CONFIGURE_ARGS,
f"http://www.python.org/ftp/python/{PYTHON_VERSION}/",
f"Python-{PYTHON_VERSION}.tgz",
)
python_bin = INSTALL_DIR / f"python-{PYTHON_VERSION}" / "bin" / "python3"
# `_ssl` module is present -> we will be able to install `numpy` later
# to verify IfcOpenShell installation
run([str(python_bin), "-c", "import _ssl"])
try:
build_dependency(
f"python-{PYTHON_VERSION}",
"autoconf",
PYTHON_CONFIGURE_ARGS,
f"http://www.python.org/ftp/python/{PYTHON_VERSION}/",
f"Python-{PYTHON_VERSION}.tgz",
)
except RuntimeError as e:
# Sometimes setting up modules such as pip/lzma can cause
# the python installer script to return a non zero exit
# code where actually the headers and dynamic libraries
# are installed correctly. This is all we need so we catch
# the exception and only reraise if a partially successful
# install is not detected.
if not os.path.exists(os.path.join(DEPS_DIR, "install", f"python-{PYTHON_VERSION}")):
raise e
if MAC_CROSS_COMPILE_INTEL:
assert original_path
@@ -1157,8 +1177,6 @@ if "cgal" in targets:
# Disable assembly, otherwise `emcc -c conftest.s` will crash due to assembly mismatch.
gmp_args.extend(("--disable-assembly", "--enable-cxx"))
mpfr_args.extend(("--host", "none"))
elif "x86" in arch:
gmp_args.append("--enable-fat") # See issues #7458 #7556
OLD_CC = None
if MAC_CROSS_COMPILE_INTEL:
@@ -1515,16 +1533,13 @@ if "IfcOpenShell-Python" in targets:
)
# Copy setup.py where pyodide build system expects it.
shutil.copy(REPO_PATH / "pyodide" / "setup.py", REPO_PATH)
# Empty pyproject so it's contents won't affect the resulting wheelthe the
# otherwise the wheel will use version and dependencies from toml, not setup.py.
(REPO_PATH / "pyproject.toml").write_text("")
elif USE_CURRENT_PYTHON_VERSION:
python_info = sysconfig.get_paths()
compile_python_wrapper(platform.python_version(), python_info["include"], sys.executable)
else:
for python_version in PYTHON_VERSIONS:
python_path = INSTALL_DIR / f"python-{python_version}"
python_path = Path(DEPS_DIR) / "install" / f"python-{python_version}"
module_dir = compile_python_wrapper(python_version, python_path=python_path)
assert module_dir
# Not sure why, but added after reading this in the logs
+13 -9
View File
@@ -1,9 +1,13 @@
--- a/adm/MODULES
+++ b/adm/MODULES
@@ -3,5 +3,5 @@ ModelingData TKG2d TKG3d TKGeomBase TKBRep
ModelingAlgorithms TKGeomAlgo TKTopAlgo TKPrim TKBO TKBool TKHLR TKFillet TKOffset TKFeat TKMesh TKXMesh TKShHealing
Visualization TKService TKV3d TKOpenGl TKOpenGles TKMeshVS TKIVtk TKD3DHost
ApplicationFramework TKCDF TKLCAF TKCAF TKBinL TKXmlL TKBin TKXml TKStdL TKStd TKTObj TKBinTObj TKXmlTObj TKVCAF
-DataExchange TKXDE TKXSBase TKSTEPBase TKSTEPAttr TKSTEP209 TKSTEP TKIGES TKXCAF TKXDEIGES TKXDESTEP TKSTL TKVRML TKXmlXCAF TKBinXCAF TKRWMesh TKXDECascade TKExpress ExpToCasExe
+DataExchange TKXDE TKXSBase TKSTEPBase TKSTEPAttr TKSTEP209 TKSTEP TKIGES TKXCAF TKXDEIGES TKXDESTEP TKSTL TKVRML TKXmlXCAF TKBinXCAF TKRWMesh TKXDECascade TKExpress
Draw TKDraw TKTopTest TKOpenGlTest TKOpenGlesTest TKD3DHostTest TKViewerTest TKXSDRAW TKDCAF TKXDEDRAW TKTObjDRAW TKQADraw TKIVtkDraw DRAWEXE
diff --git a/CMakeLists.txt b/CMakeLists.txt
index fd17283f77..6cecf9dad3 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -826,6 +826,8 @@ if (EMSCRIPTEN)
list (REMOVE_ITEM BUILD_TOOLKITS ExpToCasExe)
endif()
+list (REMOVE_ITEM BUILD_TOOLKITS ExpToCasExe)
+
# bison
if (BUILD_YACCLEX)
OCCT_INCLUDE_CMAKE_FILE ("adm/cmake/bison")
@@ -0,0 +1,13 @@
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 1bacca1a48..11f931ad39 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -820,6 +820,8 @@ else()
OCCT_CHECK_AND_UNSET ("3RDPARTY_DOT_EXECUTABLE")
endif()
+list (REMOVE_ITEM BUILD_TOOLKITS ExpToCasExe)
+
# bison
if (BUILD_YACCLEX)
OCCT_INCLUDE_CMAKE_FILE ("adm/cmake/bison")
@@ -0,0 +1,13 @@
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 86905287dc..9d0bce984c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -828,6 +828,8 @@ else()
OCCT_CHECK_AND_UNSET ("3RDPARTY_DOT_EXECUTABLE")
endif()
+list (REMOVE_ITEM BUILD_TOOLKITS ExpToCasExe)
+
# bison
if (BUILD_YACCLEX)
OCCT_INCLUDE_CMAKE_FILE ("adm/cmake/bison")
@@ -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")
+2 -7
View File
@@ -1,12 +1,9 @@
#!/usr/bin/bash
set -ex
# Script is assuming that it will be possible to execute it multiple times
# therefore we're clearing venv each time and ignoring existing 'emsdk' folder.
# Install uv.
curl -LsSf https://astral.sh/uv/install.sh | sh
uv venv --python 3.13 --clear
uv venv --python 3.13
source .venv/bin/activate
# Install pyodide cross build environment.
@@ -16,9 +13,7 @@ uv pip install pyodide-build
uv run pyodide xbuildenv install
# Emscripten doesn't come with xbuildenv.
if [ ! -d emsdk ]; then
git clone https://github.com/emscripten-core/emsdk
fi
git clone https://github.com/emscripten-core/emsdk
pushd emsdk
PYODIDE_EMSCRIPTEN_VERSION=$(pyodide config get emscripten_version)
./emsdk install ${PYODIDE_EMSCRIPTEN_VERSION}
@@ -5,13 +5,9 @@ This script is finding common install directory and either
packs each folder into a tar.gz archive, if it wasn't packed before,
or unpacks existing archives.
Expected to be executed from 'build' directory (e.g. that might contain 'Linux/x86_64/install').
Usage: python cache_dependencies.py [pack|unpack]
"""
import platform
import subprocess
import sys
import tarfile
from pathlib import Path
@@ -21,35 +17,23 @@ CACHE_PREFIX = "cache-"
def get_install_dir() -> Path:
if platform.system() == "Darwin":
pattern = "Darwin/*/*/install"
else:
pattern = "*/*/install"
for data in Path.cwd().glob(pattern):
for data in Path.cwd().glob("*/*/install"):
return data
raise Exception("No install dir found")
def run(cmd: str) -> None:
print(f"Running command: `{cmd}`")
subprocess.check_call(cmd, shell=True)
def pack_dependencies(install_dir: Path) -> None:
# Process each install_dir
for dependency_path in install_dir.iterdir():
if not dependency_path.is_dir():
continue
dependency_name = dependency_path.name
# Skip ifcopenshell - it's a build output, not a dependency to reuse across builds.
if dependency_name == "ifcopenshell":
continue
tar_path = install_dir / f"{CACHE_PREFIX}{dependency_name}.tar.gz"
if tar_path.exists():
print(f"Skipping existing cache: '{tar_path}'")
else:
# Python's `tarfile` is 10x slower than `tar` cli, so we use `tar`.
run(f'tar -czf "{tar_path}" -C "{install_dir}" "{dependency_name}"')
with tarfile.open(tar_path, "w:gz") as tar:
tar.add(dependency_path, arcname=dependency_path.name)
print(f"Created cache: '{tar_path}'")
+5 -186
View File
@@ -2,10 +2,10 @@
name = "IfcOpenShell"
version = "0.0.0"
dependencies = [
"black==26.3.1",
"ruff==0.15.7",
"black==25.12",
"ruff==0.14.10",
"poethepoet",
"gersemi==0.26.1",
"gersemi==0.24",
]
[tool.black]
@@ -15,8 +15,7 @@ include = '''
|nix/.*.pyi?$
'''
extend-exclude = '''
src/ifcopenshell-python/ifcopenshell/express/rules/*
|src/ifcopenshell-python/ifcopenshell/express/express_parser.py
src/ifcopenshell-python/ifcopenshell/express/*
|src/ifcopenshell-python/ifcopenshell/mvd/*
|src/ifcopenshell-python/ifcopenshell/simple_spf/*
|src/ifc2ca/templates/*
@@ -28,12 +27,6 @@ extend-exclude = '''
reportInvalidTypeForm = false
disableBytesTypePromotions = true
reportUnnecessaryTypeIgnoreComment = true
# Pylance doesn't respect gitignore, so we have to exclude files manually here
# to avoid VS Code slowing down.
# https://github.com/microsoft/pylance-release/issues/5169
exclude = [
"_deps",
]
# Define here general ruff settings,
# then they will be inherited by projects' .toml files.
@@ -78,139 +71,6 @@ ignore = [
"UP032", # Replace .format with f-string
]
[tool.ty.rules]
all = "ignore"
# Structural rules (no deep type inference needed, easier to adapt).
abstract-method-in-final-class = "error"
ambiguous-protocol-member = "error"
byte-string-type-annotation = "error"
conflicting-declarations = "error"
conflicting-metaclass = "error"
cyclic-class-definition = "error"
cyclic-type-alias-definition = "error"
dataclass-field-order = "error"
duplicate-base = "error"
duplicate-kw-only = "error"
empty-body = "error"
escape-character-in-forward-annotation = "error"
final-on-non-method = "error"
final-without-value = "error"
fstring-type-annotation = "error"
ignore-comment-unknown-rule = "error"
implicit-concatenated-string-type-annotation = "error"
inconsistent-mro = "error"
ineffective-final = "error"
instance-layout-conflict = "error"
invalid-dataclass = "error"
invalid-dataclass-override = "error"
invalid-enum-member-annotation = "error"
invalid-explicit-override = "error"
invalid-frozen-dataclass-subclass = "error"
invalid-generic-class = "error"
invalid-generic-enum = "error"
invalid-ignore-comment = "error"
invalid-legacy-positional-parameter = "error"
invalid-legacy-type-variable = "error"
invalid-named-tuple = "error"
invalid-newtype = "error"
invalid-overload = "error"
invalid-paramspec = "error"
invalid-protocol = "error"
invalid-syntax-in-forward-annotation = "error"
invalid-total-ordering = "error"
invalid-type-alias-type = "error"
invalid-type-checking-constant = "error"
invalid-type-guard-definition = "error"
invalid-type-variable-bound = "error"
invalid-type-variable-constraints = "error"
invalid-typed-dict-header = "error"
invalid-typed-dict-statement = "error"
override-of-final-method = "error"
override-of-final-variable = "error"
possibly-missing-import = "error"
possibly-missing-submodule = "error"
# Has false positives due to ty walrus operator bug.
# possibly-unresolved-reference = "error"
raw-string-type-annotation = "error"
redundant-final-classvar = "error"
shadowed-type-variable = "error"
subclass-of-final-class = "error"
super-call-in-named-tuple-method = "error"
unavailable-implicit-super-arguments = "error"
unbound-type-variable = "error"
undefined-reveal = "error"
unresolved-global = "error"
unresolved-import = "error"
unresolved-reference = "error"
unused-ignore-comment = "error"
unused-type-ignore-comment = "error"
useless-overload-body = "error"
# Non-structural rules:
deprecated = "error"
zero-stepsize-in-slice = "error"
possibly-missing-implicit-call = "error"
unused-awaitable = "error"
# Function argument rules:
# Conflicts with `ifcopenshell.api.geometry.add_representation` type of callables we have, confusing them with a module.
# call-non-callable = "error"
conflicting-argument-forms = "error"
# Too many false positives.
# invalid-argument-type = "error"
missing-argument = "error"
parameter-already-assigned = "error"
positional-only-parameter-as-kwarg = "error"
too-many-positional-arguments = "error"
unknown-argument = "error"
# Has a lot of warnings due to current ty walrus operator issues.
# index-out-of-bounds = "error"
# unresolved-attribute = "error"
[tool.ty.environment]
extra-paths = [
"src/bonsai/external_dependencies",
"src/bcf",
"src/bsdd",
"src/bonsai",
"src/ifc4d",
"src/ifc5d",
"src/ifccityjson",
"src/ifcclash",
"src/ifccsv",
"src/ifcdiff",
"src/ifcfm",
"src/ifcopenshell-python",
"src/ifcpatch",
"src/ifctester",
]
[tool.ty.src]
exclude = [
# External dependencies cloned for type checking only.
"src/bonsai/external_dependencies",
# Submodules.
"src/ifcopenshell-python/ifcopenshell/express",
"src/ifcopenshell-python/ifcopenshell/mvd",
"src/ifcopenshell-python/ifcopenshell/simple_spf",
"src/svgfill/3rdparty",
# Has special dependencies.
"src/ifcopenshell-python/ifcopenshell/geom/app.py",
"src/ifcopenshell-python/ifcopenshell/geom/code_editor_pane.py",
"src/ifcopenshell-python/ifcopenshell/util/doc.py",
"src/ifcopenshell-python/ifcopenshell/util/generate_pset_templates.py",
"src/ifcopenshell-python/ifcopenshell/util/ifc4x3dev_scrape_data_for_docs.py",
# Too esoteric.
"src/ifcopenshell-python/ifcopenshell/ifcopenshell_wrapper.py",
"src/ifc2ca/templates",
# Too dev.
"src/bcf/setup.py",
"src/bsdd/yml_to_classes.py",
# Deprecated.
"src/ifc2ca/_deprecated",
]
[tool.poe.tasks]
ruff-main = "ruff check --extend-exclude nix/build-all.py"
@@ -220,47 +80,6 @@ ruff.sequence = ["ruff-main", "ruff-old"]
black = "black ."
ty.sequence = ["ty-bonsai", "ty-ios"]
ty.help = "Run ty type checker. Requires ty-venv to be set up first."
ty-bonsai = "ty check src/bonsai --python=src/bonsai/.venv"
ty-venv.sequence = ["ty-venv-bonsai", "ty-venv-ios"]
ty-venv-bonsai.sequence = [
{cmd = "uv venv src/bonsai/.venv --python=3.11 --allow-existing"},
{cmd = "uv pip install -r src/bonsai/type-check-requirements.txt --python=src/bonsai/.venv"},
]
ty-venv-ios.sequence = [
{cmd = "uv venv src/ifcopenshell-python/.venv --python=3.10 --allow-existing"},
{cmd = "uv pip install -r src/ifcopenshell-python/type-check-requirements.txt --python=src/ifcopenshell-python/.venv"},
]
format.sequence = ["black", "ruff-main", "ruff-old"]
cmake-format = "gersemi . --in-place"
[tool.poe.tasks.ty-ios]
# --ignore unresolved-reference: walrus operator false positives in ty.
cmd = """
ty check
src/bcf
src/bsdd
src/ifc2ca
src/ifc4d
src/ifc5d
src/ifccityjson
src/ifcclash
src/ifccsv
src/ifcdiff
src/ifcfm
src/ifcopenshell-python
src/ifcpatch
src/ifctester
--python=src/ifcopenshell-python/.venv
--ignore unresolved-reference
"""
[tool.poe.tasks.bonsai-deps]
help = "Clone or update Bonsai external dependencies."
cmd = "python src/bonsai/scripts/bonsai_deps.py"
cmake-format = "gersemi cmake src --in-place"
+1 -2
View File
@@ -2,8 +2,6 @@ import tempfile
from pathlib import Path
from typing import Optional, Union
from typing_extensions import assert_never
import bcf.agnostic.model as mdl
import bcf.v2.bcfxml
import bcf.v2.model
@@ -11,6 +9,7 @@ import bcf.v2.topic
import bcf.v3.bcfxml
import bcf.v3.model
import bcf.v3.topic
from typing_extensions import assert_never
TopicHandler = Union[bcf.v2.topic.TopicHandler, bcf.v3.topic.TopicHandler]
+1 -1
View File
@@ -14,7 +14,7 @@
# Currently extensions support for v2 is only read-only.
from dataclasses import dataclass, field
from dataclasses import dataclass, field, fields
from typing import Optional
+2 -1
View File
@@ -3,10 +3,11 @@
from __future__ import annotations
import datetime
import tempfile
import uuid
import zipfile
from pathlib import Path
from typing import Any, NoReturn, Optional
from typing import Any, NoReturn, Optional, Union
import numpy as np
from ifcopenshell import entity_instance
+1 -1
View File
@@ -1,7 +1,7 @@
import uuid
import zipfile
from collections.abc import Iterable
from typing import Literal, Optional, Union
from typing import Any, Literal, Optional, Union
import ifcopenshell.util.placement
import ifcopenshell.util.unit
+4 -3
View File
@@ -24,6 +24,7 @@ import time
import urllib.parse
import uuid
import webbrowser
from re import A
from typing import Any, Optional
import requests
@@ -34,8 +35,8 @@ client_id, client_secret = "", ""
class OAuthReceiver(http.server.BaseHTTPRequestHandler):
def do_GET(self) -> None:
query = urllib.parse.parse_qs(urllib.parse.urlparse(self.path).query)
self.server.auth_code = query.get("code", [""])[0]
self.server.auth_state = query.get("state", [""])[0]
self.server.auth_code = query.get("code", [""])[0] # type:ignore
self.server.auth_state = query.get("state", [""])[0] # type:ignore
self.send_response(200)
self.send_header("Content-type", "text/plain")
self.end_headers()
@@ -255,7 +256,7 @@ class BcfClient:
project_id: str = "",
topics: str = "",
query_string: Optional[str] = None,
) -> None:
) -> list[Any]:
# return self.get(
# f"/projects/{project_id}/topics",
# {
+1 -1
View File
@@ -1,7 +1,7 @@
"""BCF XML V3 Documents handler."""
import zipfile
from typing import Optional
from typing import Any, Optional
import bcf.v3.model as mdl
from bcf.inmemory_zipfile import ZipFileInterface
+1 -1
View File
@@ -1,7 +1,7 @@
import uuid
import zipfile
from collections.abc import Iterable
from typing import Literal, Optional, Union
from typing import Any, Literal, Optional, Union
import ifcopenshell.util.placement
import ifcopenshell.util.unit
-6
View File
@@ -140,9 +140,3 @@ max-attributes = 10
[tool.pylint.format]
expected-line-ending-format = "LF"
max-line-length = 120
[tool.ruff]
extend = "../../pyproject.toml"
lint.select = [
"F401", # unused imports
]
-1
View File
@@ -1,5 +1,4 @@
import pytest
from bcf.xml_parser import XmlParserSerializer
+1 -2
View File
@@ -4,9 +4,8 @@ import uuid
from pathlib import Path
from tempfile import TemporaryDirectory
import pytest
import bcf.v2.model as mdl
import pytest
from bcf.v2.bcfxml import BcfXml
from bcf.v2.topic import TopicHandler
from bcf.v2.visinfo import (
+1 -2
View File
@@ -3,11 +3,10 @@ import os
import zipfile
from pathlib import Path
from xsdata.models.datatype import XmlDateTime
import bcf.v2.model as mdl
from bcf.v2.bcfxml import BcfXml
from bcf.v2.topic import TopicHandler
from xsdata.models.datatype import XmlDateTime
def test_maximum_information() -> None:
-1
View File
@@ -1,6 +1,5 @@
import numpy as np
import pytest
from bcf.v2.bcfxml import BcfXml
+1 -2
View File
@@ -4,9 +4,8 @@ import uuid
from pathlib import Path
from tempfile import TemporaryDirectory
import pytest
import bcf.v3.model as mdl
import pytest
from bcf.v3.bcfxml import BcfXml
from bcf.v3.topic import TopicHandler
from bcf.v3.visinfo import (
+13 -16
View File
@@ -1,11 +1,12 @@
import json
import os
import zipfile
from pathlib import Path
from xsdata.models.datatype import XmlDateTime
import bcf.v3.model as mdl
from bcf.v3.bcfxml import BcfXml
from bcf.v3.topic import TopicHandler
from xsdata.models.datatype import XmlDateTime
def test_doc_ref_internal() -> None:
@@ -173,17 +174,16 @@ def assert_viewpoints(viewpoints):
assert viewpoint.snapshot is not None
# TODO: dead code - ported from v2 but buildingSMART/BCF-XML has no v3 MaximumInformation.bcf equivalent
def assert_second_viewpoint(viewpoint, expected_selection, expected_exception, expected_coloring) -> None:
expected_vp = mdl.VisualizationInfo(
components=mdl.Components(
view_setup_hints=mdl.ViewSetupHints(
spaces_visible=False,
space_boundaries_visible=False,
openings_visible=False,
),
selection=expected_selection,
visibility=mdl.ComponentVisibility(
view_setup_hints=mdl.ViewSetupHints(
spaces_visible=False,
space_boundaries_visible=False,
openings_visible=False,
),
exceptions=expected_exception,
default_visibility=False,
),
@@ -194,7 +194,6 @@ def assert_second_viewpoint(viewpoint, expected_selection, expected_exception, e
camera_direction=mdl.Direction(x=0.6745243072509766, y=-0.6599355936050415, z=-0.33091068267822266),
camera_up_vector=mdl.Direction(x=0.2271970510482788, y=-0.24091780185699463, z=0.9435783624649048),
field_of_view=60,
aspect_ratio=1.0,
),
guid="21dd4807-e9af-439e-a980-04d913a6b1ce",
)
@@ -202,17 +201,16 @@ def assert_second_viewpoint(viewpoint, expected_selection, expected_exception, e
assert viewpoint.snapshot is not None
# TODO: dead code - ported from v2 but buildingSMART/BCF-XML has no v3 MaximumInformation.bcf equivalent
def assert_third_viewpoint(viewpoint, expected_selection, expected_exception, expected_coloring) -> None:
expected_vp = mdl.VisualizationInfo(
components=mdl.Components(
view_setup_hints=mdl.ViewSetupHints(
spaces_visible=False,
space_boundaries_visible=False,
openings_visible=True,
),
selection=expected_selection,
visibility=mdl.ComponentVisibility(
view_setup_hints=mdl.ViewSetupHints(
spaces_visible=False,
space_boundaries_visible=False,
openings_visible=True,
),
exceptions=expected_exception,
default_visibility=True,
),
@@ -223,7 +221,6 @@ def assert_third_viewpoint(viewpoint, expected_selection, expected_exception, ex
camera_direction=mdl.Direction(x=0.7232745289802551, y=0.5967116951942444, z=-0.3475759029388428),
camera_up_vector=mdl.Direction(x=0.27662187814712524, y=0.21082592010498047, z=0.937567412853241),
field_of_view=60,
aspect_ratio=1.0,
),
guid="81daa431-bf01-4a49-80a2-1ab07c177717",
)
-1
View File
@@ -1,6 +1,5 @@
import numpy as np
import pytest
from bcf.v3.bcfxml import BcfXml
-22
View File
@@ -1,22 +0,0 @@
# Build Bonsai .zip.
# Usage:
# # While in `bonsai` folder.
# docker build -t bonsai-dist .
# # Output zip file will be in `dist` folder.
# # See possible values for variables in `Makefile`'s `dist` target description.
# docker run --rm -v "$PWD/../../:/work" -w /work -e PLATFORM=win -e PYVERSION=py313 bonsai-dist
FROM ubuntu:24.04
RUN apt-get update
RUN apt-get install -y make git wget unzip zip
# Python
RUN apt-get install -y software-properties-common
RUN add-apt-repository ppa:deadsnakes/ppa
RUN apt-get update
RUN apt-get install -y python3.11 python3.11-venv
RUN apt-get install -y npm
WORKDIR /work
CMD cd src/bonsai && make dist PLATFORM=$PLATFORM PYVERSION=$PYVERSION
+45 -45
View File
@@ -48,33 +48,18 @@ VERSION_PATCH:=$(shell cat '../../VERSION' | cut -d '.' -f 3)
VERSION_DATE:=$(shell date '+%y%m%d')
LAST_COMMIT_HASH:=$(shell git rev-parse HEAD)
LAST_COMMIT_DATE:=$(shell git show -s --format=%cI)
PYVERSION:=py310
PYPI_IMP:=cp
ifdef PYVERSION
SUPPORTED_PYVERSIONS := py311 py312 py313
ifeq ($(filter $(PYVERSION),$(SUPPORTED_PYVERSIONS)),)
$(error Unsupported PYVERSION=$(PYVERSION). Must be one of $(SUPPORTED_PYVERSIONS))
endif
PYMINOR:=$(subst py3,,$(PYVERSION))
PYLIBDIR:=python3.$(PYMINOR)
PYNUMBER:=3$(PYMINOR)
PYPI_VERSION:=3.$(PYMINOR)
endif # def PYVERSION
ifdef PLATFORM
SUPPORTED_PLATFORMS := linux macos macosm1 win
ifeq ($(filter $(PLATFORM),$(SUPPORTED_PLATFORMS)),)
$(error Unsupported PLATFORM=$(PLATFORM). Must be one of $(SUPPORTED_PLATFORMS))
endif
ifeq ($(PLATFORM),macos)
ifeq ($(PYVERSION),py313)
$(error Blender 5.1 with Python 3.13 doesn't support intel macOS.)
ifeq ($(PYVERSION), py311)
PYLIBDIR:=python3.11
PYNUMBER:=311
PYPI_VERSION:=3.11
endif
ifeq ($(PYVERSION), py312)
PYLIBDIR:=python3.12
PYNUMBER:=312
PYPI_VERSION:=3.12
endif
ifeq ($(PLATFORM), linux)
@@ -101,10 +86,8 @@ PYPI_PLATFORM:=--platform win_amd64
BLENDER_PLATFORM:=windows-x64
endif
endif # def PLATFORM
# Current build commit hash.
OLD:=1c5b825
OLD:=e8eb5e4
.PHONY: bump
bump:
ifndef NEW
@@ -116,10 +99,7 @@ endif
.PHONY: dist
dist:
ifndef PLATFORM
$(error PLATFORM is not set. Example values: $(SUPPORTED_PLATFORMS).)
endif
ifndef PYVERSION
$(error PYVERSION is not set. Example values: $(SUPPORTED_PYVERSIONS). )
$(error PLATFORM is not set)
endif
rm -rf build
mkdir -p build
@@ -145,6 +125,9 @@ endif
cd ../ifc5d && make dist && mv dist/*.whl ../bonsai/build/wheels/
cd ../ifccityjson && make dist && mv dist/*.whl ../bonsai/build/wheels/
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/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
@@ -206,7 +189,7 @@ endif
cd build && . env/$(VENV_ACTIVATE) && $(PIP) download tzfpy $(PYPI_PLATFORM) --python-version $(PYPI_VERSION) --implementation $(PYPI_IMP) --only-binary=:all: --dest=./wheels
# pyradiance is using different platform versions than defaults in our makefile.
ifeq ($(PLATFORM), linux)
cd build && . env/$(VENV_ACTIVATE) && $(PIP) download pyradiance --platform manylinux_2_28_x86_64 --python-version $(PYPI_VERSION) --implementation $(PYPI_IMP) --only-binary=:all: --dest=./wheels
cd build && . env/$(VENV_ACTIVATE) && $(PIP) download pyradiance --platform manylinux_2_35_x86_64 --python-version $(PYPI_VERSION) --implementation $(PYPI_IMP) --only-binary=:all: --dest=./wheels
else ifeq ($(PLATFORM), macos)
cd build && . env/$(VENV_ACTIVATE) && $(PIP) download pyradiance --platform macosx_10_13_x86_64 --python-version $(PYPI_VERSION) --implementation $(PYPI_IMP) --only-binary=:all: --dest=./wheels
else
@@ -223,8 +206,19 @@ endif
cd build/bonsai/bim/data/gantt/ && wget https://raw.githubusercontent.com/jsGanttImproved/jsgantt-improved/master/dist/jsgantt.css
# Provides IFCJSON functionality
# TODO: Use official repo, once https://github.com/IFCJSON-Team/IFC2JSON_python/pull/8 is merged.
cd build && . env/$(VENV_ACTIVATE) && $(PYTHON) -m pip wheel "git+https://github.com/Andrej730/IFC2JSON_python.git@pyproject_toml" --no-deps -w wheels/
cd build && wget -O ifc2json.zip https://github.com/IFCJSON-Team/IFC2JSON_python/archive/refs/heads/master.zip
cd build && unzip ifc2json.zip && rm ifc2json.zip
# IFCJSON doesn't have pyproject.toml, so we use python command.
cd build && . env/$(VENV_ACTIVATE) && cd IFC2JSON_python-*/file_converters && \
$(PYTHON) -c "from setuptools import setup; \
setup( \
name='ifcjson', \
version='0.0.1', \
author='Jan Brouwer', \
author_email='jan@brewsky.nl', \
packages=['ifcjson'], \
)" bdist_wheel
cp -r build/IFC2JSON_python-*/file_converters/dist/*.whl build/wheels/
# Brickschema requires pkg_resources which is provided by Blender.
# Provides Brickschema functionality
@@ -232,7 +226,16 @@ endif
cd build/bonsai/bim/data/brick/ && wget https://github.com/BrickSchema/Brick/releases/download/nightly/Brick.ttl
# Required for hipped roof generation
cd build && . env/$(VENV_ACTIVATE) && $(PYTHON) -m pip wheel "git+https://github.com/prochitecture/bpypolyskel" --no-deps -w wheels/
cd build && wget https://github.com/prochitecture/bpypolyskel/archive/refs/heads/master.zip
cd build && unzip master.zip && rm master.zip
cd build && . env/$(VENV_ACTIVATE) && cd bpypolyskel-master && \
$(PYTHON) -c "from setuptools import setup; \
setup( \
name='bpypolyskel', \
version='0.0.0', \
packages=['bpypolyskel'], \
)" bdist_wheel
cp -r build/bpypolyskel-master/dist/*.whl build/wheels/
# folder for executable files
mkdir -p build/bonsai/libs/bin
@@ -264,11 +267,6 @@ else
$(SED) 's/version = "0.0.0"/version = "$(VERSION)-alpha$(VERSION_DATE)"/' build/pyproject.toml
endif
# Blender 5.1+ requires Python 3.13.
ifeq ($(PYVERSION), py313)
$(SED) 's/blender_version_min = "4\.2\.0"/blender_version_min = "5.1.0"/' build/bonsai/blender_manifest.toml
endif
$(SED) "s/os-arch/$(BLENDER_PLATFORM)/" build/bonsai/blender_manifest.toml
# Provides bonsai Add-on functionality
@@ -290,6 +288,12 @@ endif
fi
mv build/wheels/*.whl build/bonsai/wheels/
# Temporary workaround for Blender not handling non-3.11 wheels #5743.
# Use '-n' as on macos x86-64 doesn't have a binary wheel and it autoincludes 'cp311'.
prev_whl_name=$$(find build/bonsai/wheels/tzfpy-*.whl); \
whl_name=$$(echo $$prev_whl_name | sed "s/-cp39-/-cp$(PYNUMBER)-/"); \
mv --update=none "$$prev_whl_name" "$$whl_name";
ifneq ($(PLATFORM), linux)
# Safeguard: in case one of `pip download` will break,
# it will produce a linux wheel for non-linux build (our github action machine is using linux).
@@ -332,11 +336,7 @@ test:
.PHONY: test-core
test-core:
ifndef MODULE
pytest -p no:pytest-blender test/core
else
pytest -p no:pytest-blender test/core/test_${MODULE}.py
endif
.PHONY: test-bim
test-bim:
@@ -351,7 +351,7 @@ test-tool:
ifndef MODULE
pytest test/tool
else
pytest test/tool/test_$(MODULE).py --maxfail=1
pytest test/tool/test_$(MODULE).py
endif
# Reregistering test is not added to the standard test suite because during unregister
+40 -40
View File
@@ -32,14 +32,17 @@ if IN_BLENDER:
# and then as a bonsai-package.
IN_PACKAGE = __package__ == "bonsai"
import platform
import re
import platform
import traceback
import webbrowser
import uuid
import shutil
from collections import deque
from collections.abc import Generator
from pathlib import Path
from typing import TYPE_CHECKING, Any, Union
from typing import Union, Any
from collections.abc import Generator
last_commit_hash = "8888888"
last_commit_date = "9999999"
@@ -71,21 +74,6 @@ REINSTALLED_BBIM_VERSION: Union[str, None] = None
REGISTERED_BBIM_PACKAGE: str
def is_registering() -> bool:
"""
During addon registration ``bpy.context`` and ``bpy.data`` are restricted
and you can't access their properties.
"""
import bpy
if TYPE_CHECKING or bpy.app.version >= (5, 0, 0):
import _bpy_restrict_state as bpy_restrict_state
else:
import bpy_restrict_state
return isinstance(bpy.context, bpy_restrict_state._RestrictContext)
def initialize_bbim_semver():
"""Initialize `bbim_semver` dictionary.
@@ -107,13 +95,9 @@ def initialize_bbim_semver():
bbim_semver["version"] = version_str
def get_debug_info(*, bonsai_failed_to_load: bool = False) -> dict[str, Any]:
import bpy
def get_debug_info():
bbim_version = bbim_semver["version"]
# All data here should be gettable even in case of `bpy.context` and `bpy.data` being inaccessible
# and Bonsai completely failed to load.
debug_info = {
"os": platform.system(),
"os_version": platform.version(),
@@ -129,14 +113,6 @@ def get_debug_info(*, bonsai_failed_to_load: bool = False) -> dict[str, Any]:
"last_error": last_error,
}
# Can't access blend data or context during registration.
# If Bonsai failed to load we cannot safely access any of its properties or its tools
# as they may not be registered yet and acessing them will break Bonsai Fatal Error UI.
if is_registering() or bonsai_failed_to_load:
return debug_info
import bonsai.tool as tool
# Add .blend file save information
if bpy.data.is_saved:
debug_info["blend_file_path"] = bpy.data.filepath
@@ -157,7 +133,7 @@ def get_debug_info(*, bonsai_failed_to_load: bool = False) -> dict[str, Any]:
return debug_info
def format_debug_info(info: dict[str, Any]) -> str:
def format_debug_info(info: dict):
last_actions = ""
for action in info["last_actions"]:
last_actions += f"\n# {action['type']}: {action['name']}"
@@ -175,10 +151,33 @@ def get_binaries(path: Path) -> Generator[Path, None, None]:
yield from path.glob("**/*.so")
# TODO: remove before 0.8.6 release.
# On Windows issues with removing extensions were resolved in Blender 4.3,
# but we removed our workaround that was producing some junk only in 0.8.5 release.
# So we're temporarily keeping the part that's cleaning up outputs from previous releases.
def safe_link_dlls() -> None:
# Blender 4.2+ has a problem on Windows for disabling/enabling/reinstalling extensions
# with loaded binary dependencies (on Windows you can't remove a binary if it's loaded by some program).
# To avoid this issue we temporary hard link dlls to our temp directory on unregister()
# (unregister is executed before Blender will try to uninstall dependencies and the issue will arise).
# Then, Blender won't have a problem unlinking unloaded dlls as they are still linked somewhere.
# On register() we clean up our temp directory with binaries.
#
# TODO: If user uninstalls Bonsai to never use it again, temporary directory won't be cleared.
#
# See: https://projects.blender.org/blender/blender/issues/125049
import bpy
ext_path = Path(bpy.utils.user_resource("EXTENSIONS"))
local_path = ext_path / ".local"
# We use random hash subfolder as user may try to enable/disable addon multiple times.
random_hash = uuid.uuid4().hex[:8]
temp_local = ext_path / ".local_temp" / random_hash
temp_local.mkdir(parents=True)
for filepath in get_binaries(local_path):
dest_path = temp_local / filepath.relative_to(local_path)
dest_path.parent.mkdir(exist_ok=True, parents=True)
os.link(filepath, dest_path)
def clean_up_dlls_safe_links() -> None:
import bpy
@@ -208,8 +207,6 @@ def clean_up_dlls_safe_links() -> None:
if IN_BLENDER:
import bpy
initialize_bbim_semver()
def get_binary_info() -> dict[str, Any]:
@@ -301,6 +298,9 @@ if IN_BLENDER:
purge_cache()
def unregister():
if platform.system() == "Windows":
safe_link_dlls()
import bonsai.bim
bonsai.bim.unregister()
@@ -335,7 +335,7 @@ if IN_BLENDER:
bl_context = "scene"
def draw(self, context):
info = get_debug_info(bonsai_failed_to_load=True)
info = get_debug_info()
layout = self.layout
layout.alert = True
@@ -411,7 +411,7 @@ if IN_BLENDER:
bl_description = "Copies debugging information to your clipboard for use in bugreports"
def execute(self, context):
info = get_debug_info(bonsai_failed_to_load=True)
info = get_debug_info()
info.update(get_binary_info())
info = format_debug_info(info)
context.window_manager.clipboard = info
+5 -7
View File
@@ -16,16 +16,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 importlib
import os
from collections.abc import Callable
from typing import Union
import bpy
import bpy.utils.previews
from bpy_extras.io_utils import ExportHelper, ImportHelper
from . import handler, operator, prop, ui
import importlib
from bpy_extras.io_utils import ImportHelper, ExportHelper
from . import handler, ui, prop, operator
from typing import Union
from collections.abc import Callable
try:
from bonsai.translations import translations_dict
@@ -1,5 +1,6 @@
import os
import sys
import os
bonsai_lib_path = os.environ.get("BONSAI_LIB_PATH")
bonsai_version = os.environ.get("BONSAI_VERSION")
@@ -8,13 +9,12 @@ if bonsai_lib_path:
sys.path.insert(0, bonsai_lib_path)
import argparse
import base64
import json
import xml.etree.ElementTree as ET
import pystache
import socketio
from aiohttp import web
import socketio
import pystache
import json
import base64
import xml.etree.ElementTree as ET
sio_port = 8080 # default port
+18 -11
View File
@@ -17,23 +17,27 @@
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
from __future__ import annotations
import datetime
import json
import os
import tempfile
import zipfile
from logging import Logger
from typing import Union
import bpy
import json
import datetime
import zipfile
import tempfile
import ifcopenshell
import ifcopenshell.api
import ifcopenshell.util.element
import ifcopenshell.util.placement
import ifcopenshell.util.unit
import bonsai.core.geometry
import bonsai.tool as tool
import bonsai.core.geometry
import bonsai.core.aggregate
import bonsai.core.spatial
import bonsai.core.style
from bonsai.bim.ifc import IfcStore
from mathutils import Vector
from typing import Union
from logging import Logger
from math import radians
class IfcExporter:
@@ -45,6 +49,7 @@ class IfcExporter:
self.set_header()
IfcStore.update_cache()
self.sync_all_objects()
tool.Project.save_linked_models_to_ifc()
extension = self.ifc_export_settings.output_file.split(".")[-1].lower()
if extension == "ifczip":
with tempfile.TemporaryDirectory() as unzipped_path:
@@ -72,7 +77,9 @@ class IfcExporter:
def set_header(self):
self.file.header.file_name.name = os.path.basename(self.ifc_export_settings.output_file)
self.file.header.file_name.time_stamp = datetime.datetime.now().astimezone().replace(microsecond=0).isoformat()
self.file.header.file_name.time_stamp = (
datetime.datetime.utcnow().replace(tzinfo=datetime.UTC).astimezone().replace(microsecond=0).isoformat()
)
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()
+16 -24
View File
@@ -17,47 +17,39 @@
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
import os
import weakref
from collections.abc import Callable
from math import cos
from typing import Union
import bpy
import ifcopenshell.api.owner.settings
import ifcopenshell.util.element
import ifcopenshell.util.representation
import ifcopenshell.util.unit
from bpy.app.handlers import persistent
from mathutils import Vector
import ifcopenshell.api.owner.settings
import bonsai.bim
import bonsai.tool as tool
import weakref
from bpy.app.handlers import persistent
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.data import AuthoringData
from bonsai.bim.module.model.decorator import (
BoundingBoxDecorator,
SlabDirectionDecorator,
WallAxisDecorator,
)
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
from typing import Union
from collections.abc import Callable
cwd = os.path.dirname(os.path.realpath(__file__))
global_subscription_owner = object()
# Separate owner for per-object msgbus subscriptions (name, active_material_index).
# Using a dedicated owner allows clearing all per-object subscriptions at once
# during undo/redo without affecting other global subscriptions.
object_subscription_owner = object()
def name_callback(obj: Union[bpy.types.Object, bpy.types.Material], data: str) -> None:
try:
obj.name
except:
# The object is invalid but somehow still has a callback.
# This can occur during undo/redo when the Python wrapper is stale.
return
# The object is invalid but somehow still has a callback. Clear all
# msgbus subscriptions to prevent useless further triggers.
bpy.msgbus.clear_by_owner(obj)
return # In case the object RNA is gone during an undo / redo operation
# Blender names are up to 63 UTF-8 bytes
if len(bytes(obj.name, "utf-8")) >= 63:
return
@@ -192,7 +184,7 @@ def subscribe_to(obj: bpy.types.ID, data_path: str, callback: Callable[[bpy.type
return
bpy.msgbus.subscribe_rna(
key=subscribe_to,
owner=object_subscription_owner,
owner=obj,
args=(
obj,
data_path,
@@ -210,8 +202,8 @@ def refresh_ui_data():
Note that calling non-ifc-operators by itself doesn't refresh the UI data
and it need to be refreshed manually if needed.
"""
import bonsai.bim.ui
from bonsai.bim import modules
import bonsai.bim.ui
bonsai.bim.ui.refresh()
+34 -33
View File
@@ -17,30 +17,24 @@
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
from __future__ import annotations
import importlib
import json
from collections.abc import Callable, Iterable, Sequence
from types import EllipsisType
from typing import TYPE_CHECKING, Any, Optional, Union
import bpy
import json
import ifcopenshell
import ifcopenshell.ifcopenshell_wrapper as W
import ifcopenshell.util.attribute
import ifcopenshell.util.element
import ifcopenshell.util.unit
from ifcopenshell.util.doc import (
get_attribute_doc,
get_predefined_type_doc,
get_property_doc,
)
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, Sequence
if TYPE_CHECKING:
import bonsai.bim.prop
from bonsai.bim.module.search.prop import BIMFilterGroup
from bonsai.bim.prop import Attribute
from bonsai.bim.module.search.prop import BIMFilterGroup
# ImportCallback return values:
# - None - property should be imported by default workflow
@@ -517,15 +511,14 @@ def draw_filter(
row.operator("bim.edit_element_filter", icon="CHECKMARK", text="").filter_mode = "EXCLUDE"
row.operator("bim.enable_editing_element_filter", icon="CANCEL", text="").filter_mode = "NONE"
row = layout.row(align=True)
preferences = tool.Blender.get_addon_preferences()
if not preferences.chain_filter_with_set_operations:
if not tool.Blender.get_addon_preferences().chain_filter_with_set_operations:
row.operator("bim.add_filter_group", text="Add Search Group", icon="ADD").module = module
else:
row.prop(sprops, "facet", text="")
op = row.operator("bim.add_filter", text="Add Filter", icon="ADD")
op.type = sprops.facet
op.index = 0
op.module = module
if not filter_groups or not any(fg.filters for fg in filter_groups):
op = row.operator("bim.add_filter", text="Add Filter", icon="ADD")
op.type = "entity"
op.index = 0
op.module = module
op = row.operator("bim.edit_filter_query", text="", icon="FILTER")
if "module" in op.bl_rna.properties:
op.module = module
@@ -533,23 +526,26 @@ def draw_filter(
for i, filter_group in enumerate(filter_groups):
box = layout.box()
preferences = tool.Blender.get_addon_preferences()
if not preferences.chain_filter_with_set_operations:
row = box.row(align=True)
row.prop(sprops, "facet", text="")
op = row.operator("bim.add_filter", text="Add Filter", icon="ADD")
op.type = sprops.facet
op.index = i
op.module = module
op = row.operator("bim.remove_filter_group", text="", icon="X")
op.index = i
op.module = module
row = box.row(align=True)
row.prop(sprops, "facet", text="")
op = row.operator("bim.add_filter", text="Add Filter", icon="ADD")
op.type = sprops.facet
op.index = i
op.module = module
op = row.operator("bim.remove_filter_group", text="", icon="X")
op.index = i
op.module = module
for j, ifc_filter in enumerate(filter_group.filters):
if ifc_filter.type == "entity":
row = box.row(align=True)
preferences = tool.Blender.get_addon_preferences()
show_mode_toggle = preferences.chain_filter_with_set_operations and j > 0
if preferences.chain_filter_with_set_operations:
show_mode_toggle = j > 0
else:
show_mode_toggle = (
preferences.default_filter_with_set_operations_for_globalid_and_class and j > 0
) # PR 7315 mode
if show_mode_toggle:
mode_icons = {"ADD": "ADD", "SUBTRACT": "REMOVE", "FILTER": "FILTER"}
op = row.operator(
@@ -765,7 +761,12 @@ def draw_filter(
elif ifc_filter.type == "instance":
row = box.row(align=True)
preferences = tool.Blender.get_addon_preferences()
show_mode_toggle = preferences.chain_filter_with_set_operations and j > 0
if preferences.chain_filter_with_set_operations:
show_mode_toggle = j > 0
else:
show_mode_toggle = (
preferences.default_filter_with_set_operations_for_globalid_and_class and j > 0
) # PR 7315 mode
if show_mode_toggle:
mode_icons = {"ADD": "ADD", "SUBTRACT": "REMOVE", "FILTER": "FILTER"}
op = row.operator(
+18 -15
View File
@@ -17,28 +17,26 @@
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
from __future__ import annotations
import hashlib
import os
import bpy
import uuid
import shutil
import hashlib
import zipfile
import tempfile
import traceback
import uuid
import zipfile
from collections.abc import Callable
from pathlib import Path
from typing import Literal, NotRequired, Optional, TypedDict, Union
import bpy
import ifcopenshell
import ifcopenshell.geom
import ifcopenshell.ifcopenshell_wrapper
from ifcopenshell.file import UndoSystemError
import bonsai
import bonsai.bim.handler
import bonsai.tool as tool
from ifcopenshell.file import UndoSystemError
from pathlib import Path
from bonsai.tool.brick import BrickStore
from typing import Union, Optional, TypedDict, NotRequired, Literal
from collections.abc import Callable
IFC_CONNECTED_TYPE = Union[bpy.types.Material, bpy.types.Object]
@@ -316,8 +314,11 @@ class IfcStore:
del IfcStore.id_map[data["id"]]
if "guid" in data:
del IfcStore.guid_map[data["guid"]]
# Note: msgbus subscriptions are cleared globally during
# rebuild_element_maps which runs after every undo/redo.
obj = IfcStore.get_object_by_name(data["obj"])
if obj is None:
# obj was just created during this step and didn't existed before.
return
bpy.msgbus.clear_by_owner(obj)
@staticmethod
def commit_link_element(data: OperationData) -> None:
@@ -364,8 +365,10 @@ class IfcStore:
del IfcStore.id_map[data["id"]]
if "guid" in data:
del IfcStore.guid_map[data["guid"]]
# Note: msgbus subscriptions are cleared globally during
# rebuild_element_maps which runs after every undo/redo.
obj = IfcStore.get_object_by_name(data["obj"])
# obj might be removed after unlink.
if not obj:
bpy.msgbus.clear_by_owner(obj)
@staticmethod
def unlink_element(
+72 -28
View File
@@ -17,34 +17,32 @@
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
from __future__ import annotations
import json
import logging
import multiprocessing
import time
import traceback
from collections.abc import Iterable
from typing import Any, Literal, Optional, Union
import bpy
import time
import json
import ifcpatch
import logging
import traceback
import mathutils
import numpy as np
import numpy.typing as npt
import multiprocessing
import ifcopenshell
import ifcopenshell.api.pset
import ifcopenshell.geom
import ifcopenshell.ifcopenshell_wrapper as W
import ifcopenshell.util.unit
import ifcopenshell.util.element
import ifcopenshell.util.geolocation
import ifcopenshell.util.placement
import ifcopenshell.util.representation
import ifcopenshell.util.shape
import ifcopenshell.util.unit
import ifcpatch
import mathutils
import numpy as np
import numpy.typing as npt
from ifcopenshell.util.shape import MatrixType
import bonsai.tool as tool
from bonsai.bim.ifc import IFC_CONNECTED_TYPE, IfcStore
from bonsai.bim.ifc import IfcStore, IFC_CONNECTED_TYPE
from bonsai.tool.loader import OBJECT_DATA_TYPE
from typing import Union, Optional, Any, Literal
from collections.abc import Iterable
from ifcopenshell.util.shape import MatrixType
class MaterialCreator:
@@ -64,8 +62,8 @@ class MaterialCreator:
mesh: Union[OBJECT_DATA_TYPE, None],
shape_has_openings: bool,
) -> None:
if (((rep := getattr(element, "Representation", ...)) is not ... and not rep) or
((rep := getattr(element, "RepresentationMaps", ...)) is not ... and not rep)
if ((rep := getattr(element, "Representation", ...) is not ...) and not rep) or (
(rep := getattr(element, "RepresentationMaps", ...) is not ...) and not rep
):
return
@@ -84,7 +82,7 @@ class MaterialCreator:
if element.is_a("IfcTypeProduct"):
self.parse_element_type_material_styles(element)
self.parsed_meshes.add(self.mesh.name)
if self.ifc_import_settings.load_indexed_maps:
if not self.ifc_import_settings.load_indexed_maps:
self.load_texture_maps(shape_has_openings)
self.assign_material_slots_to_faces()
tool.Geometry.record_object_materials(obj)
@@ -116,6 +114,7 @@ class MaterialCreator:
for texture in texture_style.Textures or []:
if coords := getattr(texture, "IsMappedBy", None):
coords = coords[0]
# IfcTextureCoordinateGenerator handled in the style shader graph
if coords.is_a("IfcIndexedTextureMap"):
return coords
# TODO: support IfcTextureMap
@@ -133,10 +132,6 @@ class MaterialCreator:
if shape_has_openings and coords.is_a("IfcIndexedTextureMap"):
continue
tool.Loader.load_indexed_map(coords, self.mesh)
elif tool.Style.get_texture_style(material):
# No explicit coordinate mapping (e.g. IFC2X3 has no IsMappedBy,
# and IFC4 COORD uses generated UVs). Bake XY→UV as fallback.
tool.Loader.load_generated_uv_map(self.mesh)
def assign_material_slots_to_faces(self) -> None:
if not self.mesh["ios_materials"]:
@@ -295,6 +290,7 @@ class IfcImporter:
self.profile_code("Load linked models")
self.add_project_to_scene()
self.profile_code("Add project to scene")
self.hide_ifc_spaces()
if self.ifc_import_settings.should_clean_mesh and len(self.file.by_type("IfcElement")) < 1000:
self.clean_mesh()
self.profile_code("Mesh cleaning")
@@ -747,7 +743,6 @@ class IfcImporter:
self.update_progress((percent_average / 100 * progress_range) + start_progress)
shape = iterator.get()
if shape:
assert isinstance(shape, W.TriangulationElement)
product = self.file.by_id(shape.id)
self.create_product(product, shape)
results.add(product)
@@ -895,6 +890,48 @@ class IfcImporter:
obj, tool.Loader.apply_blender_offset_to_matrix_world(obj, self.get_element_matrix(element))
)
if element.is_a("IfcAnnotation") and getattr(element, "ObjectType", None) == "IMAGE":
image = None
if obj.data and obj.data.materials and obj.data.materials[0]:
material = obj.data.materials[0]
if material.use_nodes and material.node_tree:
for node in material.node_tree.nodes:
if node.type == "TEX_IMAGE" and node.image:
image = node.image
break
if image:
import bmesh
bm = bmesh.new()
bm.from_mesh(obj.data)
if not bm.loops.layers.uv:
uv_layer = bm.loops.layers.uv.new()
else:
uv_layer = bm.loops.layers.uv.active
if bm.verts:
min_x = min(v.co.x for v in bm.verts)
max_x = max(v.co.x for v in bm.verts)
min_y = min(v.co.y for v in bm.verts)
max_y = max(v.co.y for v in bm.verts)
width = max_x - min_x
height = max_y - min_y
for face in bm.faces:
for loop in face.loops:
vert = loop.vert
u = (vert.co.x - min_x) / width if width > 0 else 0.5
v = (vert.co.y - min_y) / height if height > 0 else 0.5
u = max(0.0, min(1.0, u))
v = max(0.0, min(1.0, v))
loop[uv_layer].uv = (u, v)
bm.to_mesh(obj.data)
bm.free()
obj.data.update()
return obj
def load_existing_meshes(self) -> None:
@@ -1021,8 +1058,7 @@ class IfcImporter:
obj.hide_select = True
obj.hide_viewport = True
self.project["blender"].objects.link(obj)
collection_props = tool.Blender.get_collection_props(self.project["blender"])
collection_props.obj = obj
self.project["blender"].BIMCollectionProperties.obj = obj
props = tool.Blender.get_object_bim_props(obj)
props.collection = self.collections[project.GlobalId] = self.project["blender"]
@@ -1251,6 +1287,14 @@ class IfcImporter:
properties={"Aggregate_Index": aggregate_index, "Name": name},
)
def hide_ifc_spaces(self):
"""Hide IfcSpace objects after they've been added to the scene."""
for ifc_definition_id, obj in self.added_data.items():
if isinstance(obj, bpy.types.Object):
element = self.file.by_id(ifc_definition_id)
if element.is_a("IfcSpace"):
obj.hide_set(True)
class IfcImportSettings:
"""
@@ -1268,7 +1312,7 @@ class IfcImportSettings:
self.should_load_geometry = True
self.should_clean_mesh = False
self.should_cache = True
self.deflection_tolerance = 0.05 # Default is 0.001, but I find this to be more practical
self.deflection_tolerance = 0.001
self.angular_tolerance = 0.5
self.void_limit = 30
self.style_limit = 300
@@ -17,8 +17,7 @@
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
import bpy
from . import operator, prop, ui
from . import ui, prop, operator
classes = (
operator.BIM_OT_add_aggregate,
@@ -16,12 +16,10 @@
# You should have received a copy of the GNU General Public License
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
from typing import Union
import bpy
import ifcopenshell.util.element
import bonsai.tool as tool
import ifcopenshell.util.element
from typing import Union
def refresh():
@@ -19,13 +19,14 @@
import blf
import bpy
import gpu
import ifcopenshell
import ifcopenshell.util.element
import bonsai.tool as tool
from bpy.types import SpaceView3D
from bpy_extras import view3d_utils
from gpu_extras.batch import batch_for_shader
from mathutils import Vector
import bonsai.tool as tool
from bonsai.bim.module.geometry.decorator import ItemDecorator
def transparent_color(color, alpha=0.1):
@@ -101,7 +102,7 @@ class AggregateDecorator:
cls.is_installed = False
def dotted_line_shader(self):
vert_out = gpu.types.GPUStageInterfaceInfo("my_interface") # ty:ignore[too-many-positional-arguments]
vert_out = gpu.types.GPUStageInterfaceInfo("my_interface")
vert_out.smooth("FLOAT", "v_ArcLength")
shader_info = gpu.types.GPUShaderCreateInfo()
@@ -16,17 +16,17 @@
# You should have received a copy of the GNU General Public License
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
from typing import TYPE_CHECKING
import bpy
import ifcopenshell
import ifcopenshell.api
import ifcopenshell.api.group
import ifcopenshell.api.pset
import ifcopenshell.api.root
import ifcopenshell.util.element
import bonsai.tool as tool
import bonsai.core.aggregate as core
import bonsai.core.spatial
import bonsai.tool as tool
from typing import TYPE_CHECKING
class BIM_OT_aggregate_assign_object(bpy.types.Operator, tool.Ifc.Operator):
@@ -222,7 +222,7 @@ class BIM_OT_add_aggregate(bpy.types.Operator, tool.Ifc.Operator):
tool.Collector,
tool.Spatial,
container=current_container,
objs=[aggregate],
element_obj=aggregate,
)
core.assign_object(tool.Ifc, tool.Aggregate, tool.Collector, relating_obj=aggregate, related_obj=obj)
+14 -12
View File
@@ -16,22 +16,24 @@
# You should have received a copy of the GNU General Public License
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
from typing import TYPE_CHECKING, Union
import bpy
import ifcopenshell.util.element
from bpy.props import (
BoolProperty,
CollectionProperty,
PointerProperty,
)
from bpy.types import PropertyGroup
import bonsai.tool as tool
from bonsai.bim.module.aggregate.decorator import (
AggregateDecorator,
AggregateModeDecorator,
from bonsai.bim.prop import StrProperty, Attribute
from bonsai.bim.module.spatial.data import SpatialData
from bpy.types import PropertyGroup
from bpy.props import (
PointerProperty,
StringProperty,
EnumProperty,
BoolProperty,
IntProperty,
FloatProperty,
FloatVectorProperty,
CollectionProperty,
)
from bonsai.bim.module.aggregate.decorator import AggregateDecorator, AggregateModeDecorator
from typing import TYPE_CHECKING, Union
def can_aggregate(relating_obj: bpy.types.Object, related_obj: bpy.types.Object) -> bool:
+3 -3
View File
@@ -17,10 +17,10 @@
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
from bpy.types import Panel
import bonsai.tool as tool
from bonsai.bim.ifc import IfcStore
from bonsai.bim.module.aggregate.data import AggregateData
from bonsai.bim.module.group.data import GroupsData, ObjectGroupsData
from bonsai.bim.ifc import IfcStore
import bonsai.tool as tool
class BIM_PT_aggregate(Panel):
@@ -18,16 +18,26 @@
# pyright: reportUnnecessaryTypeIgnoreComment=error
import time
import os
import ifcopenshell.api.alignment
import bpy
import ifcopenshell.api.alignment
import json
import time
import calendar
import isodate
import bonsai.core.sequence as core
import bonsai.tool as tool
import bonsai.bim.module.sequence.helper as helper
import ifcopenshell.api.spatial
import ifcopenshell.geom
import ifcopenshell.util.sequence
import ifcopenshell.util.selector
from datetime import datetime
from dateutil import parser, relativedelta
from bpy_extras.io_utils import ImportHelper
import bonsai.tool as tool
class ImportAlignmentCSV(bpy.types.Operator, tool.Ifc.Operator, ImportHelper):
bl_idname = "bim.import_alignment_csv"
@@ -17,8 +17,7 @@
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
import bpy
from . import operator, prop, ui
from . import ui, prop, operator
classes = (
operator.EnableEditingAttributes,
@@ -18,7 +18,6 @@
import bpy
import ifcopenshell
import bonsai.tool as tool
@@ -16,24 +16,21 @@
# You should have received a copy of the GNU General Public License
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
import json
from typing import TYPE_CHECKING, Any, Literal, Union
import bpy
import json
import ifcopenshell
import ifcopenshell.api.attribute
import ifcopenshell.guid
import ifcopenshell.util.element
import bonsai.bim.helper
import bonsai.tool as tool
import bonsai.core.attribute as core
import bonsai.core.spatial
import bonsai.tool as tool
from typing import TYPE_CHECKING, Any, Union, Literal
if TYPE_CHECKING:
import bpy.stub_internal.rna_enums as rna_enums
from bonsai.bim.prop import Attribute
import bpy.stub_internal.rna_enums as rna_enums
def get_objs_for_operation(
+13 -11
View File
@@ -16,19 +16,21 @@
# You should have received a copy of the GNU General Public License
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
from typing import TYPE_CHECKING, Union
import bpy
from bpy.props import (
BoolProperty,
CollectionProperty,
EnumProperty,
IntProperty,
)
from bpy.types import PropertyGroup
import bonsai.tool as tool
from bonsai.bim.prop import Attribute
from bonsai.bim.prop import StrProperty, Attribute
from bpy.types import PropertyGroup
from bpy.props import (
PointerProperty,
StringProperty,
EnumProperty,
BoolProperty,
IntProperty,
FloatProperty,
FloatVectorProperty,
CollectionProperty,
)
from typing import TYPE_CHECKING, Union
class BIMAttributeProperties(PropertyGroup):
+3 -6
View File
@@ -17,15 +17,12 @@
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
from __future__ import annotations
from typing import TYPE_CHECKING
import bonsai.bim.helper
import bpy.types
from bpy.types import Panel
import bonsai.bim.helper
import bonsai.tool as tool
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
@@ -17,8 +17,7 @@
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
import bpy
from . import operator, prop, ui
from . import ui, prop, operator
classes = (
prop.AuginProperties,
@@ -16,16 +16,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 datetime
import os
import bpy
import string
import random
import shutil
import string
import tempfile
import bpy
import requests
import tempfile
import datetime
import bonsai.tool as tool
+2 -11
View File
@@ -16,9 +16,8 @@
# You should have received a copy of the GNU General Public License
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
from typing import TYPE_CHECKING
import bpy
import bpy.props
import bpy.types
class AuginProperties(bpy.types.PropertyGroup):
@@ -28,11 +27,3 @@ class AuginProperties(bpy.types.PropertyGroup):
project_name: bpy.props.StringProperty(name="Project Name")
project_filename: bpy.props.StringProperty(name="IFC Filename")
is_success: bpy.props.BoolProperty(name="Is Successful Upload", default=False)
if TYPE_CHECKING:
username: str
password: str
token: str
project_name: str
project_filename: str
is_success: bool
-1
View File
@@ -17,7 +17,6 @@
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
import bpy.types
import bonsai.tool as tool
+1 -2
View File
@@ -17,8 +17,7 @@
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
import bpy
from . import operator, prop, ui
from . import ui, prop, operator
classes = (
operator.ActivateBcfViewpoint,
+4 -4
View File
@@ -17,12 +17,12 @@
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
import os
from typing import Union
import bcf.bcfxml
import bpy
import bcf
import bcf.bcfxml
import bcf.v2.bcfxml
import bonsai.tool as tool
from typing import Union
class BcfStore:
+23 -20
View File
@@ -16,34 +16,37 @@
# You should have received a copy of the GNU General Public License
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
import tempfile
import uuid
import webbrowser
from math import atan, degrees, radians, tan
from pathlib import Path
import bcf.agnostic.topic
import bcf.agnostic.visinfo
import bcf.v2.bcfxml
import bcf.v2.model
import bcf.v2.topic
import bcf.v2.visinfo
import os
import bcf.v3
import bcf.v3.bcfxml
import bcf.v3.document
import bcf.v3.model
import bcf.v3.topic
import bcf.v3.visinfo
import bpy
import bcf
import bcf.bcfxml
import bcf.v2.bcfxml
import bcf.v2.model
import bcf.v2.topic
import bcf.v2.visinfo
import bcf.agnostic.topic
import bcf.agnostic.visinfo
import uuid
import numpy as np
import tempfile
import webbrowser
import ifcopenshell
import ifcopenshell.util.geolocation
import ifcopenshell.util.unit
import numpy as np
from bpy_extras.io_utils import ExportHelper, ImportHelper
from mathutils import Matrix, Vector
from xsdata.models.datatype import XmlDateTime
import bonsai.bim.module.bcf.bcfstore as bcfstore
import bonsai.tool as tool
import bonsai.bim.module.bcf.prop as bcf_prop
import bonsai.bim.module.bcf.bcfstore as bcfstore
from bpy_extras.io_utils import ImportHelper, ExportHelper
from pathlib import Path
from math import radians, degrees, atan, tan, cos, sin
from mathutils import Vector, Matrix, Euler, geometry
from xsdata.models.datatype import XmlDateTime
class NewBcfProject(bpy.types.Operator):
@@ -1253,8 +1256,8 @@ class ActivateBcfViewpoint(bpy.types.Operator):
else:
obj.data.show_background_images = False
assert (space := tool.Blender.get_view3d_space())
space.region_3d.view_perspective = "CAMERA"
area = next(area for area in context.screen.areas if area.type == "VIEW_3D")
area.spaces[0].region_3d.view_perspective = "CAMERA"
if self.file:
self.set_viewpoint_components(viewpoint, context)
+13 -13
View File
@@ -16,24 +16,24 @@
# You should have received a copy of the GNU General Public License
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
from typing import TYPE_CHECKING, Union
import bpy
from bcf.agnostic.extensions import get_extensions_attributes
import bonsai.tool as tool
from . import bcfstore
from bonsai.bim.prop import StrProperty
from bpy.types import PropertyGroup
from bpy.props import (
BoolProperty,
CollectionProperty,
EnumProperty,
IntProperty,
PointerProperty,
StringProperty,
EnumProperty,
BoolProperty,
IntProperty,
FloatProperty,
FloatVectorProperty,
CollectionProperty,
)
from bpy.types import PropertyGroup
from bcf.agnostic.extensions import get_extensions_attributes
from typing import TYPE_CHECKING, Union
import bonsai.tool as tool
from bonsai.bim.prop import StrProperty
from . import bcfstore
bcfviewpoints_enum = None
@@ -230,7 +230,7 @@ class BcfTopic(PropertyGroup):
def get_related_topics(self: "BCFProperties", context: bpy.types.Context) -> list[tuple[str, str, str]]:
global RELATED_TOPICS_ENUM_ITEMS # ty: ignore[unresolved-global]
global RELATED_TOPICS_ENUM_ITEMS
props = self
active_topic = props.active_topic
active_related_topics = active_topic.related_topics.keys()
+6 -9
View File
@@ -17,18 +17,15 @@
# 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
import bpy
from bpy.types import Panel
import bonsai.tool as tool
from . import bcfstore
if TYPE_CHECKING:
from bonsai.bim.module.bcf.prop import BCFProperties, BcfTopic
from bonsai.bim.module.bcf.prop import BcfTopic, BCFProperties
class BIM_PT_bcf(Panel):
@@ -17,8 +17,7 @@
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
import bpy
from . import operator, prop, ui
from . import ui, operator, prop
classes = (
operator.AddBoundary,
@@ -17,7 +17,6 @@
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
import bpy
import bonsai.tool as tool
@@ -16,12 +16,12 @@
# You should have received a copy of the GNU General Public License
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
import bmesh
import gpu
from bpy.types import SpaceView3D
from gpu_extras.batch import batch_for_shader
import bmesh
import bonsai.tool as tool
from bpy.types import SpaceView3D
from mathutils import Vector
from gpu_extras.batch import batch_for_shader
class BoundaryDecorator:
@@ -16,34 +16,34 @@
# You should have received a copy of the GNU General Public License
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
import logging
import multiprocessing
from math import acos, degrees, inf, pi, radians
from typing import Optional, Union
import bmesh
import bpy
import bmesh
import logging
import shapely
import shapely.ops
import mathutils
import numpy as np
import multiprocessing
import ifcopenshell.api
import ifcopenshell.api.boundary
import ifcopenshell.api.root
import ifcopenshell.geom
import ifcopenshell.ifcopenshell_wrapper as W
import ifcopenshell.util.unit
import ifcopenshell.util.shape
import ifcopenshell.util.element
import ifcopenshell.util.placement
import ifcopenshell.util.shape
import ifcopenshell.util.unit
import mathutils
import shapely
import shapely.ops
from ifcopenshell.util.shape_builder import ShapeBuilder
from mathutils import Matrix, Vector
import bonsai.bim.import_ifc as import_ifc
import bonsai.core.geometry
import ifcopenshell.util.representation
import bonsai.tool as tool
import bonsai.bim.import_ifc as import_ifc
from math import pi, inf, degrees, acos, radians
from mathutils import Vector, Matrix
from bonsai.bim.ifc import IfcStore
from bonsai.bim.module.boundary.decorator import BoundaryDecorator
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
def disable_editing_boundary_geometry(context):
@@ -702,7 +702,6 @@ class AddBoundary(bpy.types.Operator, tool.Ifc.Operator):
while True:
tree.add_element(iterator.get_native())
shape = iterator.get()
assert isinstance(shape, W.TriangulationElement)
shapes[shape.id] = {
"verts": ifcopenshell.util.shape.get_vertices(shape.geometry),
"faces": ifcopenshell.util.shape.get_faces(shape.geometry),
+12 -8
View File
@@ -16,17 +16,21 @@
# You should have received a copy of the GNU General Public License
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
from typing import TYPE_CHECKING, Union
import bpy
from bpy.props import (
BoolProperty,
PointerProperty,
)
from bpy.types import PropertyGroup
import bonsai.tool as tool
from bonsai.bim.prop import ObjProperty
from bpy.props import (
PointerProperty,
StringProperty,
EnumProperty,
BoolProperty,
IntProperty,
FloatProperty,
FloatVectorProperty,
CollectionProperty,
)
import bonsai.tool as tool
from typing import TYPE_CHECKING, Union
def space_filter(self: "BIMObjectBoundaryProperties", object: bpy.types.Object) -> bool:
+2 -2
View File
@@ -16,8 +16,8 @@
# You should have received a copy of the GNU General Public License
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
from bpy.types import Panel
import bpy
from bpy.types import Panel, UIList
import bonsai.tool as tool
from bonsai.bim.module.boundary.data import SpaceBoundariesData
@@ -17,8 +17,7 @@
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
import bpy
from . import operator, prop, ui
from . import ui, prop, operator
classes = (
operator.AddBrick,
+7 -4
View File
@@ -17,12 +17,11 @@
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
import bpy
import bonsai.tool as tool
from bonsai.tool.brick import BrickStore
try:
from rdflib import BNode, URIRef
from rdflib import URIRef, BNode
except:
# See #1860
print("Warning: brickschema not available.")
@@ -63,7 +62,8 @@ class BrickschemaData:
if namespace == "https://brickschema.org/schema/Brick":
return []
results = []
query = BrickStore.graph.query("""
query = BrickStore.graph.query(
"""
PREFIX brick: <https://brickschema.org/schema/Brick#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
@@ -80,7 +80,10 @@ class BrickschemaData:
}
}
GROUP BY ?object
""".replace("{uri}", uri))
""".replace(
"{uri}", uri
)
)
for row in query:
predicate_uri = row.get("predicate")
predicate_name = predicate_uri.toPython().split("#")[-1]
@@ -17,13 +17,12 @@
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
import os
import bpy
from bpy_extras.io_utils import ExportHelper, ImportHelper
import bonsai.bim.handler
import bonsai.core.brick as core
import ifcopenshell.api
import bonsai.tool as tool
import bonsai.core.brick as core
import bonsai.bim.handler
from bpy_extras.io_utils import ImportHelper, ExportHelper
from bonsai.bim.ifc import IfcStore
from bonsai.tool.brick import BrickStore
+17 -16
View File
@@ -16,23 +16,24 @@
# You should have received a copy of the GNU General Public License
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
from typing import TYPE_CHECKING
import bpy
from bpy.props import (
BoolProperty,
CollectionProperty,
EnumProperty,
IntProperty,
StringProperty,
)
from bonsai.bim.module.brick.data import BrickschemaData, BrickschemaReferencesData
from bonsai.bim.prop import StrProperty, Attribute
from bpy.types import PropertyGroup
from bpy.props import (
PointerProperty,
StringProperty,
EnumProperty,
BoolProperty,
IntProperty,
FloatProperty,
FloatVectorProperty,
CollectionProperty,
)
import bonsai.core.brick as core
import bonsai.tool.brick as tool
from bonsai.bim.module.brick.data import BrickschemaData, BrickschemaReferencesData
from bonsai.bim.prop import StrProperty
from bonsai.tool.brick import BrickStore
from typing import TYPE_CHECKING
def update_active_brick_index(self, context):
@@ -46,26 +47,26 @@ def get_libraries(self, context):
def get_namespaces(self, context):
global NAMESPACES_ENUM_ITEMS # ty: ignore[unresolved-global]
global NAMESPACES_ENUM_ITEMS
NAMESPACES_ENUM_ITEMS = [(uri, f"{alias}: {uri}", "") for alias, uri in BrickStore.namespaces]
return NAMESPACES_ENUM_ITEMS
def get_brick_entity_classes(self, context):
global ENTITY_CLASSES_ENUM_ITEMS # ty: ignore[unresolved-global]
global ENTITY_CLASSES_ENUM_ITEMS
entity = self.brick_entity_create_type
ENTITY_CLASSES_ENUM_ITEMS = [(uri, uri.split("#")[-1], "") for uri in BrickStore.entity_classes[entity]]
return ENTITY_CLASSES_ENUM_ITEMS
def get_brick_roots(self, context):
global BRICK_ROOTS_ENUM_ITEMS # ty: ignore[unresolved-global]
global BRICK_ROOTS_ENUM_ITEMS
BRICK_ROOTS_ENUM_ITEMS = [(root, root, "") for root in BrickStore.root_classes]
return BRICK_ROOTS_ENUM_ITEMS
def get_brick_relations(self, context):
global BRICK_RELATIONS_ENUM_ITEMS # ty: ignore[unresolved-global]
global BRICK_RELATIONS_ENUM_ITEMS
BRICK_RELATIONS_ENUM_ITEMS = [(uri, uri.split("#")[-1], "") for uri in BrickStore.relationships]
for relation in BrickschemaData.data["active_relations"]:
if relation["predicate_name"] == "label":
+2 -14
View File
@@ -16,18 +16,8 @@
# You should have received a copy of the GNU General Public License
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
from __future__ import annotations
from typing import TYPE_CHECKING
import bpy
from bpy.types import Panel, UIList
import bonsai.tool as tool
if TYPE_CHECKING:
from bonsai.bim.module.brick.prop import Brick
from bpy.types import Panel, UIList
from bonsai.bim.helper import prop_with_search
from bonsai.bim.module.brick.data import BrickschemaData, BrickschemaReferencesData
from bonsai.tool.brick import BrickStore
@@ -283,9 +273,7 @@ class BIM_PT_brickschema_viewport(Panel):
class BIM_UL_bricks(UIList):
split_screen = False
def draw_item(
self, context, layout: bpy.types.UILayout, data, item: Brick, icon, active_data, active_propname
) -> None:
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
if item:
split = layout.split(factor=0.85, align=True)
row = split.row()
@@ -17,8 +17,7 @@
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
import bpy
from . import operator, prop, ui
from . import ui, prop, operator
classes = (
operator.AddBSDDProperties,
+5 -1
View File
@@ -16,8 +16,12 @@
# You should have received a copy of the GNU General Public License
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
import bpy
import ifcopenshell
import ifcopenshell.util.date
import ifcopenshell.util.classification
import bonsai.tool as tool
from bonsai.bim.ifc import IfcStore
def refresh():
@@ -16,14 +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/>.
import textwrap
from typing import Any
import bpy
import bsdd
import bonsai.tool as tool
import ifcopenshell.api.pset
import ifcopenshell.util.element
import bonsai.tool as tool
from bonsai.core import bsdd as core
from typing import Any
class LoadBSDDDictionaries(bpy.types.Operator):
+13 -12
View File
@@ -16,22 +16,23 @@
# You should have received a copy of the GNU General Public License
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
from typing import TYPE_CHECKING, Literal, Union
import bpy
from bpy.props import (
BoolProperty,
CollectionProperty,
EnumProperty,
IntProperty,
StringProperty,
)
from bpy.types import PropertyGroup
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
from bonsai.bim.prop import Attribute, StrProperty
from bpy.props import (
PointerProperty,
StringProperty,
EnumProperty,
BoolProperty,
IntProperty,
FloatProperty,
FloatVectorProperty,
CollectionProperty,
)
from typing import Union, TYPE_CHECKING, Literal
def get_active_dictionary(self: "BIMBSDDProperties", context: object) -> tool.Blender.BLENDER_ENUM_ITEMS:
+3 -11
View File
@@ -17,22 +17,14 @@
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
from __future__ import annotations
from typing import TYPE_CHECKING
import bpy
from bpy.types import Panel, UIList
import bonsai.tool as tool
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,
BSDDClassification,
BSDDDictionary,
BSDDProperty,
)
from bonsai.bim.module.bsdd.prop import BIMBSDDProperties, BSDDDictionary, BSDDClassification, BSDDProperty
class BIM_PT_bsdd(Panel):
@@ -17,7 +17,6 @@
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
import bpy
from . import operator, prop, workspace
classes = (
+8 -9
View File
@@ -16,16 +16,17 @@
# You should have received a copy of the GNU General Public License
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
import math
from math import pi, sqrt
import bmesh
import bpy
import bpy_extras
import math
import bmesh
import mathutils
from mathutils import Matrix, Vector
import bpy_extras
import bonsai.tool as tool
from mathutils import Vector, Matrix
from math import pi, radians, sin, cos, sqrt
import ifcopenshell.util.unit
from typing import Union
messages = {
"SHARED_VERTEX": "Shared Vertex, no intersection possible",
@@ -37,7 +38,6 @@ messages = {
class CadTrimExtend(bpy.types.Operator):
bl_idname = "bim.cad_trim_extend"
bl_label = "CAD Trim / Extend"
bl_description = "Extends/reduces element to 3D cursor"
@classmethod
def poll(cls, context):
@@ -83,7 +83,6 @@ class CadTrimExtend(bpy.types.Operator):
class CadMitre(bpy.types.Operator):
bl_idname = "bim.cad_mitre"
bl_label = "CAD Mitre"
bl_description = "Joins two non-parallel paths at their intersection"
@classmethod
def poll(cls, context):
+3 -3
View File
@@ -16,12 +16,12 @@
# You should have received a copy of the GNU General Public License
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
import bpy
from bonsai.bim.module.model.data import AuthoringData
from bpy.types import PropertyGroup
from math import pi
from typing import TYPE_CHECKING
import bpy
from bpy.types import PropertyGroup
class BIMCadProperties(PropertyGroup):
resolution: bpy.props.IntProperty(name="Arc Resolution", min=1, default=1)
+23 -61
View File
@@ -17,13 +17,13 @@
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
import os
from functools import partial
import bpy
from bpy.types import WorkSpaceTool
import bonsai.tool as tool
from bonsai.bim.module.model.data import RailingData, RoofData
import bonsai.bim.module.type.prop as type_prop
import ifcopenshell.util.unit
from bpy.types import WorkSpaceTool
from bonsai.bim.module.model.data import AuthoringData, RailingData, RoofData
from functools import partial
def load_custom_icons():
@@ -106,37 +106,23 @@ class CadTool(WorkSpaceTool):
)
row = layout.row(align=True)
add_layout_hotkey_operator(
row, "Extend", "S_E", bpy.ops.bim.cad_trim_extend.__doc__.split("\n", 1)[1].strip(), ui_context
)
add_layout_hotkey_operator(row, "Extend", "S_E", "Extends/reduces element to 3D cursor", ui_context)
row = row if ui_context == "TOOL_HEADER" else layout.row(align=True)
add_layout_hotkey_operator(
row, "Join", "S_T", bpy.ops.bim.cad_mitre.__doc__.split("\n", 1)[1].strip(), ui_context
row, "Join", "S_T", "Joins two non-parallel paths at their intersection", ui_context
)
row = row if ui_context == "TOOL_HEADER" else layout.row(align=True)
add_layout_hotkey_operator(
row, "Fillet", "S_F", bpy.ops.bim.add_ifcarcindex_fillet.__doc__.split("\n", 1)[1].strip(), ui_context
)
add_layout_hotkey_operator(row, "Fillet", "S_F", bpy.ops.bim.add_ifcarcindex_fillet.__doc__, ui_context)
row = row if ui_context == "TOOL_HEADER" else layout.row(align=True)
add_layout_hotkey_operator(
row, "Offset", "S_O", bpy.ops.bim.cad_offset.__doc__.split("\n", 1)[1].strip(), ui_context
)
add_layout_hotkey_operator(row, "Offset", "S_O", bpy.ops.bim.cad_offset.__doc__, ui_context)
row = row if ui_context == "TOOL_HEADER" else layout.row(align=True)
add_layout_hotkey_operator(
row, "Rectangle", "S_R", bpy.ops.bim.add_rectangle.__doc__.split("\n", 1)[1].strip(), ui_context
)
add_layout_hotkey_operator(row, "Rectangle", "S_R", bpy.ops.bim.add_rectangle.__doc__, ui_context)
row = row if ui_context == "TOOL_HEADER" else layout.row(align=True)
add_layout_hotkey_operator(
row, "Circle", "S_C", bpy.ops.bim.add_ifccircle.__doc__.split("\n", 1)[1].strip(), ui_context
)
add_layout_hotkey_operator(row, "Circle", "S_C", bpy.ops.bim.add_ifccircle.__doc__, ui_context)
row = row if ui_context == "TOOL_HEADER" else layout.row(align=True)
add_layout_hotkey_operator(
row, "3-Point Arc", "S_V", bpy.ops.bim.set_arc_index.__doc__.split("\n", 1)[1].strip(), ui_context
)
add_layout_hotkey_operator(row, "3-Point Arc", "S_V", bpy.ops.bim.set_arc_index.__doc__, ui_context)
row = row if ui_context == "TOOL_HEADER" else layout.row(align=True)
add_layout_hotkey_operator(
row, "Reset Vertex", "S_X", bpy.ops.bim.reset_vertex.__doc__.split("\n", 1)[1].strip(), ui_context
)
add_layout_hotkey_operator(row, "Reset Vertex", "S_X", bpy.ops.bim.reset_vertex.__doc__, ui_context)
elif (
isinstance(data, tool.Geometry.TYPES_WITH_MESH_PROPERTIES)
@@ -146,21 +132,15 @@ class CadTool(WorkSpaceTool):
layout, "Edit Axis", "bim.edit_extrusion_axis", "bim.disable_editing_extrusion_axis", ui_context
)
row = layout.row(align=True)
add_layout_hotkey_operator(
row, "Extend", "S_E", bpy.ops.bim.cad_trim_extend.__doc__.split("\n", 1)[1].strip(), ui_context
)
add_layout_hotkey_operator(row, "Extend", "S_E", "Extends/reduces element to 3D cursor", ui_context)
row = row if ui_context == "TOOL_HEADER" else layout.row(align=True)
add_layout_hotkey_operator(
row, "Join", "S_T", bpy.ops.bim.cad_mitre.__doc__.split("\n", 1)[1].strip(), ui_context
row, "Join", "S_T", "Joins two non-parallel paths at their intersection", ui_context
)
row = row if ui_context == "TOOL_HEADER" else layout.row(align=True)
add_layout_hotkey_operator(
row, "Fillet", "S_F", bpy.ops.bim.cad_fillet.__doc__.split("\n", 1)[1].strip(), ui_context
)
add_layout_hotkey_operator(row, "Fillet", "S_F", bpy.ops.bim.cad_fillet.__doc__, ui_context)
row = row if ui_context == "TOOL_HEADER" else layout.row(align=True)
add_layout_hotkey_operator(
row, "Offset", "S_O", bpy.ops.bim.cad_offset.__doc__.split("\n", 1)[1].strip(), ui_context
)
add_layout_hotkey_operator(row, "Offset", "S_O", bpy.ops.bim.cad_offset.__doc__, ui_context)
else:
if (
@@ -188,37 +168,19 @@ class CadTool(WorkSpaceTool):
add_layout_hotkey_operator(row, "Set Gable Roof Angle", "S_R", "Set Gable Roof Angle", ui_context)
row = layout.row(align=True)
add_layout_hotkey_operator(
row, "Extend", "S_E", bpy.ops.bim.cad_trim_extend.__doc__.split("\n", 1)[1].strip(), ui_context
)
add_layout_hotkey_operator(row, "Extend", "S_E", "Extends/reduces element to 3D cursor", ui_context)
row = row if ui_context == "TOOL_HEADER" else layout.row(align=True)
add_layout_hotkey_operator(
row, "Join", "S_T", bpy.ops.bim.cad_mitre.__doc__.split("\n", 1)[1].strip(), ui_context
row, "Join", "S_T", "Joins two non-parallel paths at their intersection", ui_context
)
row = row if ui_context == "TOOL_HEADER" else layout.row(align=True)
add_layout_hotkey_operator(
row, "Fillet", "S_F", bpy.ops.bim.add_ifcarcindex_fillet.__doc__.split("\n", 1)[1].strip(), ui_context
)
add_layout_hotkey_operator(row, "Fillet", "S_F", bpy.ops.bim.add_ifcarcindex_fillet.__doc__, ui_context)
row = row if ui_context == "TOOL_HEADER" else layout.row(align=True)
add_layout_hotkey_operator(
row, "Offset", "S_O", bpy.ops.bim.cad_offset.__doc__.split("\n", 1)[1].strip(), ui_context
)
add_layout_hotkey_operator(row, "Offset", "S_O", bpy.ops.bim.cad_offset.__doc__, ui_context)
row = row if ui_context == "TOOL_HEADER" else layout.row(align=True)
add_layout_hotkey_operator(
row,
"2-Point Arc",
"S_C",
bpy.ops.bim.cad_arc_from_2_points.__doc__.split("\n", 1)[1].strip(),
ui_context,
)
add_layout_hotkey_operator(row, "2-Point Arc", "S_C", bpy.ops.bim.cad_arc_from_2_points.__doc__, ui_context)
row = row if ui_context == "TOOL_HEADER" else layout.row(align=True)
add_layout_hotkey_operator(
row,
"3-Point Arc",
"S_V",
bpy.ops.bim.cad_arc_from_3_points.__doc__.split("\n", 1)[1].strip(),
ui_context,
)
add_layout_hotkey_operator(row, "3-Point Arc", "S_V", bpy.ops.bim.cad_arc_from_3_points.__doc__, ui_context)
class CadHotkey(bpy.types.Operator):
@@ -17,8 +17,7 @@
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
import bpy
from . import operator, prop, ui
from . import ui, prop, operator
classes = (
operator.AddClashSet,
+2 -1
View File
@@ -16,8 +16,9 @@
# You should have received a copy of the GNU General Public License
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
import bpy
import json
import ifcopenshell.util.element
import bonsai.tool as tool
@@ -18,12 +18,12 @@
import blf
import gpu
from bpy.types import SpaceView3D
from bpy_extras.view3d_utils import location_3d_to_region_2d
from gpu_extras.batch import batch_for_shader
from mathutils import Vector
import bmesh
import bonsai.tool as tool
from bpy.types import SpaceView3D
from mathutils import Vector
from gpu_extras.batch import batch_for_shader
from bpy_extras.view3d_utils import location_3d_to_region_2d
class ClashDecorator:
+14 -11
View File
@@ -16,21 +16,22 @@
# You should have received a copy of the GNU General Public License
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
import json
import logging
import tempfile
from math import radians
from pathlib import Path
from typing import TYPE_CHECKING
import os
import bpy
import json
import tempfile
import bmesh
import logging
import numpy as np
import ifcopenshell
from bpy_extras.io_utils import ExportHelper, ImportHelper
from mathutils import Matrix, Vector
import bonsai.tool as tool
from pathlib import Path
from bpy_extras.io_utils import ExportHelper, ImportHelper
from math import radians
from mathutils import Matrix, Vector
from bonsai.bim.ifc import IfcStore
from bonsai.bim.module.clash.decorator import ClashDecorator
from typing import TYPE_CHECKING
class ExportClashSets(bpy.types.Operator, ExportHelper):
@@ -457,7 +458,9 @@ class HideClash(bpy.types.Operator):
def execute(self, context):
ClashDecorator.uninstall()
tool.Blender.update_all_viewports(context)
for area in context.screen.areas:
if area.type == "VIEW_3D":
area.tag_redraw()
return {"FINISHED"}
+10 -11
View File
@@ -16,24 +16,23 @@
# You should have received a copy of the GNU General Public License
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
from typing import TYPE_CHECKING, Literal, Union
import bpy
import bonsai.tool as tool
from bonsai.bim.prop import StrProperty, Attribute, BIMFilterGroup
from bpy.types import PropertyGroup
from bpy.props import (
BoolProperty,
CollectionProperty,
PointerProperty,
StringProperty,
EnumProperty,
BoolProperty,
IntProperty,
FloatProperty,
FloatVectorProperty,
IntProperty,
StringProperty,
CollectionProperty,
)
from bpy.types import PropertyGroup
from ifcopenshell.geom.main import CLASH_TYPE_ITEMS, ClashType
from ifcopenshell.geom.main import ClashType, CLASH_TYPE_ITEMS
from mathutils import Vector
import bonsai.tool as tool
from bonsai.bim.prop import BIMFilterGroup, StrProperty
from typing import TYPE_CHECKING, Literal, Union
class ClashSource(PropertyGroup):
+6 -14
View File
@@ -17,23 +17,15 @@
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
from __future__ import annotations
import bpy
import bonsai.tool as tool
import bonsai.bim.helper
from bpy.types import Panel
from bonsai.bim.module.clash.data import ClashData
from typing import TYPE_CHECKING, assert_never
import bpy
from bpy.types import Panel
import bonsai.bim.helper
import bonsai.tool as tool
from bonsai.bim.module.clash.data import ClashData
if TYPE_CHECKING:
from bonsai.bim.module.clash.prop import (
BIMClashProperties,
Clash,
ClashSet,
SmartClashGroup,
)
from bonsai.bim.module.clash.prop import BIMClashProperties, ClashSet, SmartClashGroup, Clash
class BIM_PT_ifcclash(Panel):

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