Merge branch 'v0.8.0' of https://github.com/IfcOpenShell/IfcOpenShell into light/newUI

This commit is contained in:
Chirag Singh
2026-03-08 23:01:34 +05:30
363 changed files with 4391 additions and 3683 deletions
+3 -2
View File
@@ -1,7 +1,8 @@
# yaml-language-server: $schema=https://raw.githubusercontent.com/BlankSpruce/gersemi/0.24.0/gersemi/configuration.schema.json # yaml-language-server: $schema=https://raw.githubusercontent.com/BlankSpruce/gersemi/0.24.0/gersemi/configuration.schema.json
# Needed for gersemi to detect custom functions and macros. # Gersemi doesn't support autodetection of macros/functions from other files or from the current one
definitions: ["./cmake"] # and requires to explicitly list directories/cmake files that define them.
definitions: ["./cmake", "./src"]
disable_formatting: false disable_formatting: false
extensions: [] extensions: []
indent: 4 indent: 4
+7 -7
View File
@@ -40,6 +40,8 @@ jobs:
# preinstalled: xz, cmake # preinstalled: xz, cmake
brew install git bison autoconf automake libffi findutils brew install git bison autoconf automake libffi findutils
echo "$(brew --prefix findutils)/libexec/gnubin" >> $GITHUB_PATH 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 - name: Install aws cli
run: | run: |
@@ -47,11 +49,11 @@ jobs:
- name: Unpack Dependencies - name: Unpack Dependencies
run: | run: |
install_root=$(find ./build -maxdepth 4 -type d -name install 2>/dev/null | head -n 1 || true) cd build
[ -n "$install_root" ] && find "$install_root" -type f -name 'cache-*.tar.gz' -maxdepth 1 -exec tar -xzf {} -C "$install_root" \; || true python ../nix/cache_dependencies.py unpack
- name: ccache - name: ccache
uses: hendrikmuhs/ccache-action@v1.2 uses: hendrikmuhs/ccache-action@v1.2.20
with: with:
key: mac-${{ matrix.arch }} key: mac-${{ matrix.arch }}
@@ -81,7 +83,7 @@ jobs:
- name: Upload Build Logs - name: Upload Build Logs
if: always() if: always()
uses: actions/upload-artifact@v6 uses: actions/upload-artifact@v7
with: with:
name: build-logs-osx-${{ matrix.arch }} name: build-logs-osx-${{ matrix.arch }}
path: | path: |
@@ -93,9 +95,7 @@ jobs:
- name: Pack Dependencies - name: Pack Dependencies
run: | run: |
cd build cd build
for install_dir in $(find $(find . -maxdepth 4 -name install) -mindepth 1 -maxdepth 1 -type d); do python ../nix/cache_dependencies.py pack
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 - name: Commit and Push Changes to Build Repository
run: | run: |
+4 -4
View File
@@ -26,10 +26,10 @@ jobs:
- name: Unpack Dependencies - name: Unpack Dependencies
run: | run: |
cd ifcopenshell_build cd ifcopenshell_build
python ../IfcOpenShell/pyodide/cache_dependencies.py unpack python ../IfcOpenShell/nix/cache_dependencies.py unpack
- name: ccache - name: ccache
uses: hendrikmuhs/ccache-action@v1.2 uses: hendrikmuhs/ccache-action@v1.2.20
with: with:
key: ubuntu-22.04-${{ runner.arch }} key: ubuntu-22.04-${{ runner.arch }}
@@ -42,7 +42,7 @@ jobs:
- name: Upload Build Logs - name: Upload Build Logs
if: always() if: always()
uses: actions/upload-artifact@v6 uses: actions/upload-artifact@v7
with: with:
name: build-logs-pyodide name: build-logs-pyodide
path: | path: |
@@ -65,7 +65,7 @@ jobs:
- name: Pack Dependencies - name: Pack Dependencies
run: | run: |
cd ifcopenshell_build cd ifcopenshell_build
python ../IfcOpenShell/pyodide/cache_dependencies.py pack python ../IfcOpenShell/nix/cache_dependencies.py pack
- name: Commit and Push Changes to Build Repository - name: Commit and Push Changes to Build Repository
run: | run: |
+10 -13
View File
@@ -6,13 +6,13 @@ on:
jobs: jobs:
build_ifcopenshell: build_ifcopenshell:
runs-on: ubuntu-22.04 runs-on: ubuntu-22.04
container: rockylinux:8 container: rockylinux:9
steps: steps:
- name: Install Dependencies - name: Install Dependencies
run: | run: |
yum update -y dnf update -y
yum install -y gcc gcc-c++ git autoconf automake bison make zip cmake python3 \ dnf install -y gcc gcc-c++ git autoconf automake bison make zip cmake python3 python3-pip \
bzip2 patch mesa-libGL-devel libffi-devel fontconfig-devel \ bzip2 patch mesa-libGL-devel libffi-devel fontconfig-devel \
sqlite-devel bzip2-devel zlib-devel openssl-devel xz-devel \ sqlite-devel bzip2-devel zlib-devel openssl-devel xz-devel \
readline-devel ncurses-devel libffi-devel libuuid-devel git-lfs \ readline-devel ncurses-devel libffi-devel libuuid-devel git-lfs \
@@ -38,20 +38,19 @@ jobs:
with: with:
repository: IfcOpenShell/build-outputs repository: IfcOpenShell/build-outputs
path: ./build path: ./build
ref: rockylinux8-x64 ref: rockylinux9-x64
lfs: true lfs: true
token: ${{ secrets.BUILD_REPO_TOKEN }} token: ${{ secrets.BUILD_REPO_TOKEN }}
- name: Unpack Dependencies - name: Unpack Dependencies
run: | run: |
install_root=$(find ./build -maxdepth 4 -type d -name install 2>/dev/null | head -n 1 || true) cd build
[ -n "$install_root" ] && find "$install_root" -type f -name 'cache-*.tar.gz' -maxdepth 1 -exec tar -xzf {} -C "$install_root" \; || true python3 ../nix/cache_dependencies.py unpack
- name: ccache - name: ccache
# TODO: Use tag after 1.2.20 releases. uses: hendrikmuhs/ccache-action@v1.2.20
uses: hendrikmuhs/ccache-action@5ebbd400eff9e74630f759d94ddd7b6c26299639
with: with:
key: ubuntu-22.04-${{ runner.arch }}-rockylinux8 key: ubuntu-22.04-${{ runner.arch }}-rockylinux9
- name: Run Build Script - name: Run Build Script
shell: bash shell: bash
@@ -61,7 +60,7 @@ jobs:
- name: Upload Build Logs - name: Upload Build Logs
if: always() if: always()
uses: actions/upload-artifact@v6 uses: actions/upload-artifact@v7
with: with:
name: build-logs-rocky name: build-logs-rocky
path: | path: |
@@ -72,9 +71,7 @@ jobs:
- name: Pack Dependencies - name: Pack Dependencies
run: | run: |
cd build cd build
for install_dir in $(find $(find . -maxdepth 4 -name install) -mindepth 1 -maxdepth 1 -type d); do python3 ../nix/cache_dependencies.py pack
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 - name: Commit and Push Changes to Build Repository
run: | run: |
+10 -13
View File
@@ -6,13 +6,13 @@ on:
jobs: jobs:
build_ifcopenshell: build_ifcopenshell:
runs-on: ubuntu-22.04-arm runs-on: ubuntu-22.04-arm
container: arm64v8/rockylinux:8 container: arm64v8/rockylinux:9
steps: steps:
- name: Install Dependencies - name: Install Dependencies
run: | run: |
yum update -y dnf update -y
yum install -y gcc gcc-c++ git autoconf automake bison make zip cmake python3 \ dnf install -y gcc gcc-c++ git autoconf automake bison make zip cmake python3 python3-pip \
bzip2 patch mesa-libGL-devel libffi-devel fontconfig-devel \ bzip2 patch mesa-libGL-devel libffi-devel fontconfig-devel \
sqlite-devel bzip2-devel zlib-devel openssl-devel xz-devel \ sqlite-devel bzip2-devel zlib-devel openssl-devel xz-devel \
readline-devel ncurses-devel libffi-devel libuuid-devel git-lfs \ readline-devel ncurses-devel libffi-devel libuuid-devel git-lfs \
@@ -38,20 +38,19 @@ jobs:
with: with:
repository: IfcOpenShell/build-outputs repository: IfcOpenShell/build-outputs
path: ./build path: ./build
ref: rockylinux8-arm64 ref: rockylinux9-arm64
lfs: true lfs: true
token: ${{ secrets.BUILD_REPO_TOKEN }} token: ${{ secrets.BUILD_REPO_TOKEN }}
- name: Unpack Dependencies - name: Unpack Dependencies
run: | run: |
install_root=$(find ./build -maxdepth 4 -type d -name install 2>/dev/null | head -n 1 || true) cd build
[ -n "$install_root" ] && find "$install_root" -type f -name 'cache-*.tar.gz' -maxdepth 1 -exec tar -xzf {} -C "$install_root" \; || true python3 ../nix/cache_dependencies.py unpack
- name: ccache - name: ccache
# TODO: Use tag after 1.2.20 releases. uses: hendrikmuhs/ccache-action@v1.2.20
uses: hendrikmuhs/ccache-action@5ebbd400eff9e74630f759d94ddd7b6c26299639
with: with:
key: ubuntu-22.04-${{ runner.arch }}-rockylinux8 key: ubuntu-22.04-${{ runner.arch }}-rockylinux9
- name: Run Build Script - name: Run Build Script
shell: bash shell: bash
@@ -61,7 +60,7 @@ jobs:
- name: Upload Build Logs - name: Upload Build Logs
if: always() if: always()
uses: actions/upload-artifact@v6 uses: actions/upload-artifact@v7
with: with:
name: build-logs-rocky-arm64 name: build-logs-rocky-arm64
path: | path: |
@@ -72,9 +71,7 @@ jobs:
- name: Pack Dependencies - name: Pack Dependencies
run: | run: |
cd build cd build
for install_dir in $(find $(find . -maxdepth 4 -name install) -mindepth 1 -maxdepth 1 -type d); do python3 ../nix/cache_dependencies.py pack
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 - name: Commit and Push Changes to Build Repository
run: | run: |
+1 -2
View File
@@ -37,8 +37,7 @@ jobs:
} }
- name: ccache - name: ccache
# TODO: Use tag after 1.2.20 releases. uses: hendrikmuhs/ccache-action@v1.2.20
uses: hendrikmuhs/ccache-action@5ebbd400eff9e74630f759d94ddd7b6c26299639
with: with:
key: win-${{ matrix.arch }} key: win-${{ matrix.arch }}
# Windows ccache needs ~1GB # Windows ccache needs ~1GB
+10 -10
View File
@@ -24,9 +24,15 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: | if: |
github.repository == 'IfcOpenShell/IfcOpenShell' github.repository == 'IfcOpenShell/IfcOpenShell'
outputs:
timestamp: ${{ steps.timestamp.outputs.timestamp }}
steps: steps:
- name: Set env - name: Get current timestamp
run: echo ok go id: timestamp
# Include hours and minutes to release tag
# to avoid possibility of unstable repo's index.json
# pointing to the new file when index.json itself wasn't yet updated.
run: echo "timestamp=$(date +'%y%m%d%H%M')" >> $GITHUB_OUTPUT
build: build:
needs: activate needs: activate
@@ -67,12 +73,6 @@ jobs:
- name: Get current version - name: Get current version
id: version id: version
run: echo "version=$(cat VERSION)" >> $GITHUB_OUTPUT 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 - name: Compile
run: | run: |
cd src/bonsai && make dist PLATFORM=${{ matrix.config.short_name }} PYVERSION=${{ matrix.pyver }} cd src/bonsai && make dist PLATFORM=${{ matrix.config.short_name }} PYVERSION=${{ matrix.pyver }}
@@ -88,8 +88,8 @@ jobs:
repo_token: ${{ secrets.GITHUB_TOKEN }} repo_token: ${{ secrets.GITHUB_TOKEN }}
file: ${{ steps.find_zip.outputs.filepath }} file: ${{ steps.find_zip.outputs.filepath }}
asset_name: ${{ steps.find_zip.outputs.filename }} asset_name: ${{ steps.find_zip.outputs.filename }}
release_name: "bonsai-${{steps.version.outputs.version}}-alpha${{steps.date.outputs.date}} (unstable)" release_name: "bonsai-${{steps.version.outputs.version}}-alpha${{ needs.activate.outputs.timestamp }} (unstable)"
tag: "bonsai-${{steps.version.outputs.version}}-alpha${{steps.date.outputs.date}}" tag: "bonsai-${{steps.version.outputs.version}}-alpha${{ needs.activate.outputs.timestamp }}"
overwrite: true overwrite: true
body: "See README in https://github.com/IfcOpenShell/bonsai_unstable_repo/ on how to setup autoupdates for daily Bonsai builds." body: "See README in https://github.com/IfcOpenShell/bonsai_unstable_repo/ on how to setup autoupdates for daily Bonsai builds."
+3 -3
View File
@@ -35,7 +35,7 @@ jobs:
- -
name: ccache name: ccache
uses: hendrikmuhs/ccache-action@v1.2 uses: hendrikmuhs/ccache-action@v1.2.20
- -
name: Build ifcopenshell name: Build ifcopenshell
@@ -73,7 +73,7 @@ jobs:
make package make package
working-directory: build working-directory: build
- name: Upload - name: Upload
uses: actions/upload-artifact@v6 uses: actions/upload-artifact@v7
with: with:
# Artifact name # Artifact name
name: ifcos-artifacts name: ifcos-artifacts
@@ -91,7 +91,7 @@ jobs:
lfs: true lfs: true
- name: Download - name: Download
uses: actions/download-artifact@v7.0.0 uses: actions/download-artifact@v8.0.0
with: with:
# Artifact name # Artifact name
name: ifcos-artifacts name: ifcos-artifacts
+1 -4
View File
@@ -79,10 +79,7 @@ jobs:
libhdf5-dev libcgal-dev libeigen3-dev libhdf5-dev libcgal-dev libeigen3-dev
- name: ccache - name: ccache
# TODO: temporarily pointing to 1.2.19 to get notified by dependabot when 1.2.20 is released uses: hendrikmuhs/ccache-action@v1.2.20
# 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: with:
key: ubuntu-22.04-${{ runner.arch }} key: ubuntu-22.04-${{ runner.arch }}
+2
View File
@@ -82,6 +82,8 @@ src/bonsai/bonsai/translations.py
# bonsai test temp files # bonsai test temp files
src/bonsai/test/files/temp src/bonsai/test/files/temp
src/bonsai/test/files/basic.ifc.cache.blend
src/bonsai/test/files/basic.ifc.cache.sqlite
# bonsai data # bonsai data
src/bonsai/bonsai/bim/data/build/ src/bonsai/bonsai/bim/data/build/
+153
View File
@@ -0,0 +1,153 @@
<!-- 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.
+17 -9
View File
@@ -258,10 +258,10 @@ if(WITH_ROCKSDB)
set(ROCKSDB_LIBRARIES "IFCOPENSHELL_RocksDB") set(ROCKSDB_LIBRARIES "IFCOPENSHELL_RocksDB")
target_compile_definitions(IFCOPENSHELL_RocksDB INTERFACE IFOPSH_WITH_ROCKSDB) target_compile_definitions(IFCOPENSHELL_RocksDB INTERFACE IFOPSH_WITH_ROCKSDB)
set(SWIG_DEFINES ${SWIG_DEFINES} -DIFOPSH_WITH_ROCKSDB) set(SWIG_DEFINES ${SWIG_DEFINES} -DIFOPSH_WITH_ROCKSDB)
target_link_libraries( # Shared binaries for `rocksdb` only support limited API (only `c.h`), but we use `db.h` API.
IFCOPENSHELL_RocksDB # So rocksdb supported only as a static library.
INTERFACE $<IF:$<TARGET_EXISTS:RocksDB::rocksdb-shared>,RocksDB::rocksdb-shared,RocksDB::rocksdb> # See https://github.com/facebook/rocksdb/issues/981.
) target_link_libraries(IFCOPENSHELL_RocksDB INTERFACE RocksDB::rocksdb)
if(WITH_ZSTD) if(WITH_ZSTD)
# @todo do we actually need the zstd include dir or rather just pass # @todo do we actually need the zstd include dir or rather just pass
@@ -368,12 +368,20 @@ if(ENABLE_BUILD_OPTIMIZATIONS)
# Linker # Linker
# /OPT:REF enables also /OPT:ICF and disables INCREMENTAL # /OPT:REF enables also /OPT:ICF and disables INCREMENTAL
set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /LTCG /OPT:REF") set(LINKER_FLAGS_RELEASE "/LTCG /OPT:REF")
# /OPT:NOICF is recommended when /DEBUG is used (http://msdn.microsoft.com/en-us/library/xe4t6fc1.aspx) # /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(LINKER_FLAGS_RELWITHDEBINFO "/DEBUG /OPT:NOICF")
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /LTCG /OPT:REF")
set(CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /DEBUG /OPT:NOICF") set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} ${LINKER_FLAGS_RELEASE}")
set(CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO
"${CMAKE_SHARED_LINKER_FLAGS_RELEASE} ${LINKER_FLAGS_RELWITHDEBINFO}"
)
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} ${LINKER_FLAGS_RELEASE}")
set(CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_EXE_LINKER_FLAGS_RELEASE} ${LINKER_FLAGS_RELWITHDEBINFO}")
set(CMAKE_MODULE_LINKER_FLAGS_RELEASE "${CMAKE_MODULE_LINKER_FLAGS_RELEASE} ${LINKER_FLAGS_RELEASE}")
set(CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO
"${CMAKE_MODULE_LINKER_FLAGS_RELEASE} ${LINKER_FLAGS_RELWITHDEBINFO}"
)
else() else()
# GCC-like: Release should use O3 but RelWithDebInfo 02 so enforce 03. Anything other useful that could be added here? # 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") set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3")
+11
View File
@@ -43,6 +43,17 @@ if(NOT OCC_INCLUDE_DIR AND NOT OCC_LIBRARY_DIR)
set_target_properties(TKernel PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${OpenCASCADE_INCLUDE_DIR}") set_target_properties(TKernel PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${OpenCASCADE_INCLUDE_DIR}")
endif() 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) if(OpenCASCADE_VERSION VERSION_LESS "7.9.0" AND WIN32)
# Bug in OCCT cmake configs < 7.9.0 - missing linked library. # Bug in OCCT cmake configs < 7.9.0 - missing linked library.
list(APPEND OpenCASCADE_LIBRARIES WSOCK32.lib) list(APPEND OpenCASCADE_LIBRARIES WSOCK32.lib)
+59 -76
View File
@@ -75,27 +75,30 @@ Used environment variables:
# # # #
# for python37 to install correctly additionally: # # for python37 to install correctly additionally: #
# * libffi(-dev[el]) # # * libffi(-dev[el]) #
# for Python build we also needs ssl # # for Python build we also needs ssl and zlib #
# (since we do `pip install numpy` at the end) # # (since we do `pip install numpy` at the end) #
# * libssl-dev # # * libssl-dev #
# # # #
# on debian 7.8 these can be obtained with: # # on debian 7.8 these can be obtained with: #
# $ apt-get install git gcc g++ autoconf bison bzip2 cmake # # $ apt-get install git gcc g++ autoconf bison bzip2 cmake #
# mesa-common-dev libffi-dev libfontconfig1-dev # # mesa-common-dev libffi-dev libfontconfig1-dev #
# libssl-dev xz # # libssl-dev xz zlib1g-dev #
# # # #
# on ubuntu 14.04: # # on ubuntu 14.04: #
# $ apt-get install git gcc g++ autoconf bison make cmake # # $ apt-get install git gcc g++ autoconf bison make cmake #
# mesa-common-dev libffi-dev libfontconfig1-dev # # mesa-common-dev libffi-dev libfontconfig1-dev #
# libssl-dev xz-utils # # libssl-dev xz-utils zlib1g-dev #
# # # #
# on OS X El Capitan with homebrew: # # on OS X El Capitan with homebrew: #
# $ brew install git bison autoconf automake libffi cmake # # $ 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: # # on RHEL-related distros: #
# $ yum install git gcc gcc-c++ autoconf bison make cmake # # $ dnf install git gcc gcc-c++ autoconf bison make cmake #
# mesa-libGL-devel libffi-devel fontconfig-devel bzip2 # # mesa-libGL-devel libffi-devel fontconfig-devel bzip2 #
# automake patch byacc xz # # automake patch byacc xz zlib-devel openssl-devel #
""" """
@@ -147,9 +150,8 @@ OCCT_VERSION = "7.8.1"
BOOST_VERSION = "1.86.0" BOOST_VERSION = "1.86.0"
EIGEN_VERSION = "3.4.0" EIGEN_VERSION = "3.4.0"
PCRE_VERSION = "8.41" PCRE_VERSION = "8.41"
PCRE2_VERSION = "10.32"
LIBXML2_VERSION = "2.13.8" LIBXML2_VERSION = "2.13.8"
SWIG_VERSION = "4.1.0" SWIG_VERSION = "4.2.1"
OPENCOLLADA_VERSION = "v1.6.68" OPENCOLLADA_VERSION = "v1.6.68"
HDF5_VERSION = "1.13.1" HDF5_VERSION = "1.13.1"
@@ -246,15 +248,8 @@ if WASM:
# https://github.com/pyodide/pyodide-build/pull/249 # https://github.com/pyodide/pyodide-build/pull/249
WASM_CMAKE_IS_USING_INIT_VARS = get_pyodide_build_version() >= (99, 0, 0) WASM_CMAKE_IS_USING_INIT_VARS = get_pyodide_build_version() >= (99, 0, 0)
# pyodide provide empty `CXXFLAGS`, leading to issues using C++ files compiled with `-fexceptions` # 0.31 is required for SIDE_MODULE_CXXFLAGS to be provided.
# which is used by OCCT. assert get_pyodide_build_version() >= (0, 31)
# 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 # Set defaults for missing empty environment variables
@@ -294,6 +289,7 @@ DEPS_DIR = os.getenv("DEPS_DIR", DEFAULT_DEPS_DIR)
if not os.path.exists(DEPS_DIR): if not os.path.exists(DEPS_DIR):
os.makedirs(DEPS_DIR) os.makedirs(DEPS_DIR)
INSTALL_DIR = Path(DEPS_DIR) / "install"
BUILD_CFG = os.getenv("BUILD_CFG", "RelWithDebInfo") BUILD_CFG = os.getenv("BUILD_CFG", "RelWithDebInfo")
@@ -319,24 +315,18 @@ cecho(f"* Build Directory = {BUILD_DIR}", MAGENTA)
cecho(f"* Dependency Directory = {DEPS_DIR}", MAGENTA) cecho(f"* Dependency Directory = {DEPS_DIR}", MAGENTA)
cecho(f" - The directory where {PROJECT_NAME} dependencies are installed.") cecho(f" - The directory where {PROJECT_NAME} dependencies are installed.")
cecho(f"* Build Config Type = {BUILD_CFG}", MAGENTA) cecho(f"* Build Config Type = {BUILD_CFG}", MAGENTA)
cecho( cecho(""" - The used build configuration type for the dependencies.
""" - The used build configuration type for the dependencies. Defaults to RelWithDebInfo if not specified.""")
Defaults to RelWithDebInfo if not specified."""
)
if BUILD_CFG == "MinSizeRel": if BUILD_CFG == "MinSizeRel":
cecho(" WARNING: MinSizeRel build can suffer from a significant performance loss.", RED) cecho(" WARNING: MinSizeRel build can suffer from a significant performance loss.", RED)
cecho(f"* IFCOS_NUM_BUILD_PROCS = {IFCOS_NUM_BUILD_PROCS}", MAGENTA) cecho(f"* IFCOS_NUM_BUILD_PROCS = {IFCOS_NUM_BUILD_PROCS}", MAGENTA)
cecho( cecho(""" - How many compiler processes may be run in parallel.
""" - How many compiler processes may be run in parallel. """)
"""
)
cecho(f" * IFCOS_SCHEMAS = '{os.environ.get('IFCOS_SCHEMAS')}'", MAGENTA) cecho(f" * IFCOS_SCHEMAS = '{os.environ.get('IFCOS_SCHEMAS')}'", MAGENTA)
cecho( cecho(""" - IFC Schemas to compile. If not provided, fallback to default provided in cmake.
""" - IFC Schemas to compile. If not provided, fallback to default provided in cmake. """)
"""
)
dependency_tree: "dict[str, tuple[str, ...]]" = { dependency_tree: "dict[str, tuple[str, ...]]" = {
"IfcParse": ("boost", "libxml2", "hdf5", "rocksdb"), "IfcParse": ("boost", "libxml2", "hdf5", "rocksdb"),
@@ -345,13 +335,12 @@ dependency_tree: "dict[str, tuple[str, ...]]" = {
"OpenCOLLADA": ("libxml2", "pcre"), "OpenCOLLADA": ("libxml2", "pcre"),
"IfcGeomServer": ("IfcGeom",), "IfcGeomServer": ("IfcGeom",),
"IfcOpenShell-Python": ("python", "swig", "IfcGeom"), "IfcOpenShell-Python": ("python", "swig", "IfcGeom"),
"swig": ("pcre2",), "swig": (),
"boost": (), "boost": (),
"libxml2": (), "libxml2": (),
"python": (), "python": (),
"occ": (), "occ": (),
"pcre": (), "pcre": (),
"pcre2": (),
"json": (), "json": (),
"hdf5": (), "hdf5": (),
"cgal": (), "cgal": (),
@@ -418,7 +407,6 @@ if WASM:
"opencollada", "opencollada",
"swig", "swig",
"pcre", "pcre",
"pcre2",
"IfcGeom", "IfcGeom",
"IfcConvert", "IfcConvert",
"IfcGeomServer", "IfcGeomServer",
@@ -433,13 +421,16 @@ print("Building:", *sorted(targets, key=lambda t: len(list(gather_dependencies(t
# Check that required tools are in PATH # Check that required tools are in PATH
yacc = "yacc" # Used during swig building process, installed with `bison` on Debian / `byacc` on Red Hat. yacc = "yacc" # Used during swig building process, installed with `bison` on Debian / `byacc` on Red Hat.
bison = "bison"
missing_commands: "list[str]" = [] missing_commands: "list[str]" = []
required_commands = [git, bunzip2, tar, cc, cplusplus, autoconf, automake, make, "patch", "cmake", yacc, xz] required_commands = [git, bunzip2, tar, cc, cplusplus, autoconf, automake, make, "patch", "cmake", yacc, xz, bison]
if "wasm" in flags: if "wasm" in flags:
# Skip swig build for WASM. # Skip swig build for WASM.
required_commands.append("swig") required_commands.append("swig")
required_commands.append("pyodide") required_commands.append("pyodide")
required_commands.remove(yacc) required_commands.remove(yacc)
required_commands.remove(bison)
for cmd in required_commands: for cmd in required_commands:
if shutil.which(cmd) is None: if shutil.which(cmd) is None:
@@ -498,7 +489,7 @@ def run(cmds: "Sequence[str]", cwd: "Union[str, None]" = None, can_fail: bool =
collector.append(line) collector.append(line)
pipe.close() 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] = [] stdout: list[str] = []
stderr: list[str] = [] stderr: list[str] = []
@@ -544,14 +535,14 @@ BOOST_LOCATION = f"https://github.com/boostorg/boost/releases/download/boost-{BO
# Helper functions # Helper functions
def run_autoconf(arg1: str, configure_args: "list[str]", cwd: str) -> None: def run_autoconf(dependency_name: str, configure_args: "list[str]", cwd: str) -> None:
configure_path = os.path.realpath(os.path.join(cwd, "..", "configure")) configure_path = os.path.realpath(os.path.join(cwd, "..", "configure"))
if not os.path.exists(configure_path): if not os.path.exists(configure_path):
run( run(
[bash, "./autogen.sh"], cwd=os.path.realpath(os.path.join(cwd, "..")) [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 ) # 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 # Using `sh` over `bash` fixes issues with building swig
prefix = os.path.realpath(f"{DEPS_DIR}/install/{arg1}") prefix = os.path.realpath(f"{DEPS_DIR}/install/{dependency_name}")
wasm = [] wasm = []
if "wasm" in flags: if "wasm" in flags:
@@ -930,20 +921,15 @@ if "pcre" in targets:
restore_env("CC", OLD_CC) restore_env("CC", OLD_CC)
restore_env("CXX", OLD_CXX) restore_env("CXX", OLD_CXX)
if "pcre2" in targets:
build_dependency(
name=f"pcre2-{PCRE2_VERSION}",
mode="autoconf",
build_tool_args=[DISABLE_FLAG],
download_url=f"https://downloads.sourceforge.net/project/pcre/pcre2/{PCRE2_VERSION}/",
download_name=f"pcre2-{PCRE2_VERSION}.tar.bz2",
)
if "swig" in targets: if "swig" in targets:
dependency_name = f"swig-{SWIG_VERSION}"
build_dependency( build_dependency(
name=f"swig-{SWIG_VERSION}", name=dependency_name,
mode="autoconf", mode="cmake",
build_tool_args=["--disable-ccache", f"--with-pcre2-prefix={DEPS_DIR}/install/pcre2-{PCRE2_VERSION}"], build_tool_args=[
"-DWITH_PCRE=OFF",
f"-DCMAKE_INSTALL_PREFIX={DEPS_DIR}/install/{dependency_name}",
],
download_url="https://github.com/swig/swig.git", download_url="https://github.com/swig/swig.git",
download_name="swig", download_name="swig",
download_tool=download_tool_git, download_tool=download_tool_git,
@@ -951,21 +937,18 @@ if "swig" in targets:
) )
if USE_OCCT and "occ" in targets: if USE_OCCT and "occ" in targets:
patches = [] occt_args: "list[str]" = []
patches: "list[str]" = []
if OCCT_VERSION < "7.4": if OCCT_VERSION < "7.4":
patches.append("./patches/occt/enable-exception-handling.patch") patches.append("./patches/occt/enable-exception-handling.patch")
if OCCT_VERSION == "7.7.1": # Skip ExpToCasExe as we don't need it and it requires additional dependencies.
# Before 7.7.2 ExpToCasExe is part of DataExchange, DETools doesn't exist yet.
# Since we do need DataExchange (used for IgesSerializer), we use a patch to skip only ExpToCasExe.
if "7.7.2" > OCCT_VERSION >= "7.7":
patches.append("./patches/occt/no_ExpToCasExe.patch") patches.append("./patches/occt/no_ExpToCasExe.patch")
elif OCCT_VERSION >= "7.7.2":
if OCCT_VERSION == "7.7.2": occt_args.append("-DBUILD_MODULE_DETools=OFF")
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: if "wasm" in flags:
patches.append("./patches/occt/no_em_js.patch") patches.append("./patches/occt/no_em_js.patch")
@@ -986,6 +969,7 @@ if USE_OCCT and "occ" in targets:
f"-DUSE_GLES2=OFF", f"-DUSE_GLES2=OFF",
f"-DCMAKE_POLICY_VERSION_MINIMUM=3.5", f"-DCMAKE_POLICY_VERSION_MINIMUM=3.5",
*MAC_CROSS_COMPILE_INTEL_ARGS, *MAC_CROSS_COMPILE_INTEL_ARGS,
*occt_args,
], ],
download_url="https://github.com/Open-Cascade-SAS/OCCT", download_url="https://github.com/Open-Cascade-SAS/OCCT",
download_name="occt", download_name="occt",
@@ -1101,23 +1085,19 @@ if "python" in targets and not USE_CURRENT_PYTHON_VERSION and "wasm" not in flag
PYTHON_CONFIGURE_ARGS.extend(["--with-universal-archs=intel-64", "--enable-universalsdk"]) PYTHON_CONFIGURE_ARGS.extend(["--with-universal-archs=intel-64", "--enable-universalsdk"])
for PYTHON_VERSION in PYTHON_VERSIONS: for PYTHON_VERSION in PYTHON_VERSIONS:
try: # Don't fail silently on missing Python dependencies (e.g. openssl or zlib),
build_dependency( # because later ifcopenshell-python build will fail too but in a more confusing way.
f"python-{PYTHON_VERSION}", build_dependency(
"autoconf", f"python-{PYTHON_VERSION}",
PYTHON_CONFIGURE_ARGS, "autoconf",
f"http://www.python.org/ftp/python/{PYTHON_VERSION}/", PYTHON_CONFIGURE_ARGS,
f"Python-{PYTHON_VERSION}.tgz", 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 python_bin = INSTALL_DIR / f"python-{PYTHON_VERSION}" / "bin" / "python3"
# the python installer script to return a non zero exit # `_ssl` module is present -> we will be able to install `numpy` later
# code where actually the headers and dynamic libraries # to verify IfcOpenShell installation
# are installed correctly. This is all we need so we catch run([str(python_bin), "-c", "import _ssl"])
# 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: if MAC_CROSS_COMPILE_INTEL:
assert original_path assert original_path
@@ -1535,13 +1515,16 @@ if "IfcOpenShell-Python" in targets:
) )
# Copy setup.py where pyodide build system expects it. # Copy setup.py where pyodide build system expects it.
shutil.copy(REPO_PATH / "pyodide" / "setup.py", REPO_PATH) 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: elif USE_CURRENT_PYTHON_VERSION:
python_info = sysconfig.get_paths() python_info = sysconfig.get_paths()
compile_python_wrapper(platform.python_version(), python_info["include"], sys.executable) compile_python_wrapper(platform.python_version(), python_info["include"], sys.executable)
else: else:
for python_version in PYTHON_VERSIONS: for python_version in PYTHON_VERSIONS:
python_path = Path(DEPS_DIR) / "install" / f"python-{python_version}" python_path = INSTALL_DIR / f"python-{python_version}"
module_dir = compile_python_wrapper(python_version, python_path=python_path) module_dir = compile_python_wrapper(python_version, python_path=python_path)
assert module_dir assert module_dir
# Not sure why, but added after reading this in the logs # Not sure why, but added after reading this in the logs
@@ -5,9 +5,13 @@ This script is finding common install directory and either
packs each folder into a tar.gz archive, if it wasn't packed before, packs each folder into a tar.gz archive, if it wasn't packed before,
or unpacks existing archives. 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] Usage: python cache_dependencies.py [pack|unpack]
""" """
import platform
import subprocess
import sys import sys
import tarfile import tarfile
from pathlib import Path from pathlib import Path
@@ -17,11 +21,20 @@ CACHE_PREFIX = "cache-"
def get_install_dir() -> Path: def get_install_dir() -> Path:
for data in Path.cwd().glob("*/*/install"): if platform.system() == "Darwin":
pattern = "Darwin/*/*/install"
else:
pattern = "*/*/install"
for data in Path.cwd().glob(pattern):
return data return data
raise Exception("No install dir found") 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: def pack_dependencies(install_dir: Path) -> None:
# Process each install_dir # Process each install_dir
for dependency_path in install_dir.iterdir(): for dependency_path in install_dir.iterdir():
@@ -32,8 +45,8 @@ def pack_dependencies(install_dir: Path) -> None:
if tar_path.exists(): if tar_path.exists():
print(f"Skipping existing cache: '{tar_path}'") print(f"Skipping existing cache: '{tar_path}'")
else: else:
with tarfile.open(tar_path, "w:gz") as tar: # Python's `tarfile` is 10x slower than `tar` cli, so we use `tar`.
tar.add(dependency_path, arcname=dependency_path.name) run(f'tar -czf "{tar_path}" -C "{install_dir}" "{dependency_name}"')
print(f"Created cache: '{tar_path}'") print(f"Created cache: '{tar_path}'")
+9 -13
View File
@@ -1,13 +1,9 @@
diff --git a/CMakeLists.txt b/CMakeLists.txt --- a/adm/MODULES
index fd17283f77..6cecf9dad3 100644 +++ b/adm/MODULES
--- a/CMakeLists.txt @@ -3,5 +3,5 @@ ModelingData TKG2d TKG3d TKGeomBase TKBRep
+++ b/CMakeLists.txt ModelingAlgorithms TKGeomAlgo TKTopAlgo TKPrim TKBO TKBool TKHLR TKFillet TKOffset TKFeat TKMesh TKXMesh TKShHealing
@@ -826,6 +826,8 @@ if (EMSCRIPTEN) Visualization TKService TKV3d TKOpenGl TKOpenGles TKMeshVS TKIVtk TKD3DHost
list (REMOVE_ITEM BUILD_TOOLKITS ExpToCasExe) ApplicationFramework TKCDF TKLCAF TKCAF TKBinL TKXmlL TKBin TKXml TKStdL TKStd TKTObj TKBinTObj TKXmlTObj TKVCAF
endif() -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
+list (REMOVE_ITEM BUILD_TOOLKITS ExpToCasExe) Draw TKDraw TKTopTest TKOpenGlTest TKOpenGlesTest TKD3DHostTest TKViewerTest TKXSDRAW TKDCAF TKXDEDRAW TKTObjDRAW TKQADraw TKIVtkDraw DRAWEXE
+
# bison
if (BUILD_YACCLEX)
OCCT_INCLUDE_CMAKE_FILE ("adm/cmake/bison")
@@ -1,13 +0,0 @@
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 1bacca1a48..11f931ad39 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -820,6 +820,8 @@ else()
OCCT_CHECK_AND_UNSET ("3RDPARTY_DOT_EXECUTABLE")
endif()
+list (REMOVE_ITEM BUILD_TOOLKITS ExpToCasExe)
+
# bison
if (BUILD_YACCLEX)
OCCT_INCLUDE_CMAKE_FILE ("adm/cmake/bison")
@@ -1,13 +0,0 @@
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 86905287dc..9d0bce984c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -828,6 +828,8 @@ else()
OCCT_CHECK_AND_UNSET ("3RDPARTY_DOT_EXECUTABLE")
endif()
+list (REMOVE_ITEM BUILD_TOOLKITS ExpToCasExe)
+
# bison
if (BUILD_YACCLEX)
OCCT_INCLUDE_CMAKE_FILE ("adm/cmake/bison")
@@ -1,13 +0,0 @@
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 34300d41ad..09b2e0d45f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -721,6 +721,8 @@ else()
OCCT_CHECK_AND_UNSET ("3RDPARTY_DOT_EXECUTABLE")
endif()
+list (REMOVE_ITEM BUILD_TOOLKITS ExpToCasExe)
+
# bison
if (BUILD_YACCLEX)
list (APPEND OCCT_3RDPARTY_CMAKE_LIST "adm/cmake/bison")
+7 -2
View File
@@ -1,9 +1,12 @@
#!/usr/bin/bash #!/usr/bin/bash
set -ex 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. # Install uv.
curl -LsSf https://astral.sh/uv/install.sh | sh curl -LsSf https://astral.sh/uv/install.sh | sh
uv venv --python 3.13 uv venv --python 3.13 --clear
source .venv/bin/activate source .venv/bin/activate
# Install pyodide cross build environment. # Install pyodide cross build environment.
@@ -13,7 +16,9 @@ uv pip install pyodide-build
uv run pyodide xbuildenv install uv run pyodide xbuildenv install
# Emscripten doesn't come with xbuildenv. # Emscripten doesn't come with xbuildenv.
git clone https://github.com/emscripten-core/emsdk if [ ! -d emsdk ]; then
git clone https://github.com/emscripten-core/emsdk
fi
pushd emsdk pushd emsdk
PYODIDE_EMSCRIPTEN_VERSION=$(pyodide config get emscripten_version) PYODIDE_EMSCRIPTEN_VERSION=$(pyodide config get emscripten_version)
./emsdk install ${PYODIDE_EMSCRIPTEN_VERSION} ./emsdk install ${PYODIDE_EMSCRIPTEN_VERSION}
+4 -3
View File
@@ -3,9 +3,9 @@ name = "IfcOpenShell"
version = "0.0.0" version = "0.0.0"
dependencies = [ dependencies = [
"black==26.1.0", "black==26.1.0",
"ruff==0.15.0", "ruff==0.15.4",
"poethepoet", "poethepoet",
"gersemi==0.25.4", "gersemi==0.26.0",
] ]
[tool.black] [tool.black]
@@ -15,7 +15,8 @@ include = '''
|nix/.*.pyi?$ |nix/.*.pyi?$
''' '''
extend-exclude = ''' extend-exclude = '''
src/ifcopenshell-python/ifcopenshell/express/* src/ifcopenshell-python/ifcopenshell/express/rules/*
|src/ifcopenshell-python/ifcopenshell/express/express_parser.py
|src/ifcopenshell-python/ifcopenshell/mvd/* |src/ifcopenshell-python/ifcopenshell/mvd/*
|src/ifcopenshell-python/ifcopenshell/simple_spf/* |src/ifcopenshell-python/ifcopenshell/simple_spf/*
|src/ifc2ca/templates/* |src/ifc2ca/templates/*
+2 -2
View File
@@ -34,8 +34,8 @@ client_id, client_secret = "", ""
class OAuthReceiver(http.server.BaseHTTPRequestHandler): class OAuthReceiver(http.server.BaseHTTPRequestHandler):
def do_GET(self) -> None: def do_GET(self) -> None:
query = urllib.parse.parse_qs(urllib.parse.urlparse(self.path).query) query = urllib.parse.parse_qs(urllib.parse.urlparse(self.path).query)
self.server.auth_code = query.get("code", [""])[0] # type:ignore self.server.auth_code = query.get("code", [""])[0] # type: ignore
self.server.auth_state = query.get("state", [""])[0] # type:ignore self.server.auth_state = query.get("state", [""])[0] # type: ignore
self.send_response(200) self.send_response(200)
self.send_header("Content-type", "text/plain") self.send_header("Content-type", "text/plain")
self.end_headers() self.end_headers()
+2 -2
View File
@@ -104,7 +104,7 @@ endif
endif # def PLATFORM endif # def PLATFORM
# Current build commit hash. # Current build commit hash.
OLD:=e8eb5e4 OLD:=1c5b825
.PHONY: bump .PHONY: bump
bump: bump:
ifndef NEW ifndef NEW
@@ -371,7 +371,7 @@ test-tool:
ifndef MODULE ifndef MODULE
pytest test/tool pytest test/tool
else else
pytest test/tool/test_$(MODULE).py pytest test/tool/test_$(MODULE).py --maxfail=1
endif endif
# Reregistering test is not added to the standard test suite because during unregister # Reregistering test is not added to the standard test suite because during unregister
-1
View File
@@ -34,7 +34,6 @@ IN_PACKAGE = __package__ == "bonsai"
import platform import platform
import re import re
import shutil
import traceback import traceback
import uuid import uuid
import webbrowser import webbrowser
-8
View File
@@ -24,21 +24,14 @@ import os
import tempfile import tempfile
import zipfile import zipfile
from logging import Logger from logging import Logger
from math import radians
from typing import Union from typing import Union
import bpy import bpy
import ifcopenshell import ifcopenshell
import ifcopenshell.api
import ifcopenshell.util.element import ifcopenshell.util.element
import ifcopenshell.util.placement
import ifcopenshell.util.unit import ifcopenshell.util.unit
from mathutils import Vector
import bonsai.core.aggregate
import bonsai.core.geometry import bonsai.core.geometry
import bonsai.core.spatial
import bonsai.core.style
import bonsai.tool as tool import bonsai.tool as tool
from bonsai.bim.ifc import IfcStore from bonsai.bim.ifc import IfcStore
@@ -52,7 +45,6 @@ class IfcExporter:
self.set_header() self.set_header()
IfcStore.update_cache() IfcStore.update_cache()
self.sync_all_objects() self.sync_all_objects()
tool.Project.save_linked_models_to_ifc()
extension = self.ifc_export_settings.output_file.split(".")[-1].lower() extension = self.ifc_export_settings.output_file.split(".")[-1].lower()
if extension == "ifczip": if extension == "ifczip":
with tempfile.TemporaryDirectory() as unzipped_path: with tempfile.TemporaryDirectory() as unzipped_path:
-1
View File
@@ -28,7 +28,6 @@ import bpy
import ifcopenshell import ifcopenshell
import ifcopenshell.ifcopenshell_wrapper as W import ifcopenshell.ifcopenshell_wrapper as W
import ifcopenshell.util.attribute import ifcopenshell.util.attribute
import ifcopenshell.util.element
import ifcopenshell.util.unit import ifcopenshell.util.unit
from ifcopenshell.util.doc import ( from ifcopenshell.util.doc import (
get_attribute_doc, get_attribute_doc,
+5 -45
View File
@@ -32,7 +32,6 @@ import ifcopenshell.api.pset
import ifcopenshell.geom import ifcopenshell.geom
import ifcopenshell.ifcopenshell_wrapper as W import ifcopenshell.ifcopenshell_wrapper as W
import ifcopenshell.util.element import ifcopenshell.util.element
import ifcopenshell.util.geolocation
import ifcopenshell.util.placement import ifcopenshell.util.placement
import ifcopenshell.util.representation import ifcopenshell.util.representation
import ifcopenshell.util.shape import ifcopenshell.util.shape
@@ -85,7 +84,7 @@ class MaterialCreator:
if element.is_a("IfcTypeProduct"): if element.is_a("IfcTypeProduct"):
self.parse_element_type_material_styles(element) self.parse_element_type_material_styles(element)
self.parsed_meshes.add(self.mesh.name) self.parsed_meshes.add(self.mesh.name)
if not self.ifc_import_settings.load_indexed_maps: if self.ifc_import_settings.load_indexed_maps:
self.load_texture_maps(shape_has_openings) self.load_texture_maps(shape_has_openings)
self.assign_material_slots_to_faces() self.assign_material_slots_to_faces()
tool.Geometry.record_object_materials(obj) tool.Geometry.record_object_materials(obj)
@@ -117,7 +116,6 @@ class MaterialCreator:
for texture in texture_style.Textures or []: for texture in texture_style.Textures or []:
if coords := getattr(texture, "IsMappedBy", None): if coords := getattr(texture, "IsMappedBy", None):
coords = coords[0] coords = coords[0]
# IfcTextureCoordinateGenerator handled in the style shader graph
if coords.is_a("IfcIndexedTextureMap"): if coords.is_a("IfcIndexedTextureMap"):
return coords return coords
# TODO: support IfcTextureMap # TODO: support IfcTextureMap
@@ -135,6 +133,10 @@ class MaterialCreator:
if shape_has_openings and coords.is_a("IfcIndexedTextureMap"): if shape_has_openings and coords.is_a("IfcIndexedTextureMap"):
continue continue
tool.Loader.load_indexed_map(coords, self.mesh) 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: def assign_material_slots_to_faces(self) -> None:
if not self.mesh["ios_materials"]: if not self.mesh["ios_materials"]:
@@ -892,48 +894,6 @@ class IfcImporter:
obj, tool.Loader.apply_blender_offset_to_matrix_world(obj, self.get_element_matrix(element)) 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 return obj
def load_existing_meshes(self) -> None: def load_existing_meshes(self) -> None:
@@ -19,7 +19,6 @@
import blf import blf
import bpy import bpy
import gpu import gpu
import ifcopenshell
import ifcopenshell.util.element import ifcopenshell.util.element
from bpy.types import SpaceView3D from bpy.types import SpaceView3D
from bpy_extras import view3d_utils from bpy_extras import view3d_utils
@@ -27,7 +26,6 @@ from gpu_extras.batch import batch_for_shader
from mathutils import Vector from mathutils import Vector
import bonsai.tool as tool import bonsai.tool as tool
from bonsai.bim.module.geometry.decorator import ItemDecorator
def transparent_color(color, alpha=0.1): def transparent_color(color, alpha=0.1):
@@ -19,8 +19,6 @@
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
import bpy import bpy
import ifcopenshell
import ifcopenshell.api
import ifcopenshell.api.group import ifcopenshell.api.group
import ifcopenshell.api.pset import ifcopenshell.api.pset
import ifcopenshell.api.root import ifcopenshell.api.root
@@ -23,12 +23,7 @@ import ifcopenshell.util.element
from bpy.props import ( from bpy.props import (
BoolProperty, BoolProperty,
CollectionProperty, CollectionProperty,
EnumProperty,
FloatProperty,
FloatVectorProperty,
IntProperty,
PointerProperty, PointerProperty,
StringProperty,
) )
from bpy.types import PropertyGroup from bpy.types import PropertyGroup
@@ -37,8 +32,6 @@ from bonsai.bim.module.aggregate.decorator import (
AggregateDecorator, AggregateDecorator,
AggregateModeDecorator, AggregateModeDecorator,
) )
from bonsai.bim.module.spatial.data import SpatialData
from bonsai.bim.prop import Attribute, StrProperty
def can_aggregate(relating_obj: bpy.types.Object, related_obj: bpy.types.Object) -> bool: def can_aggregate(relating_obj: bpy.types.Object, related_obj: bpy.types.Object) -> bool:
@@ -21,7 +21,6 @@ from bpy.types import Panel
import bonsai.tool as tool import bonsai.tool as tool
from bonsai.bim.ifc import IfcStore from bonsai.bim.ifc import IfcStore
from bonsai.bim.module.aggregate.data import AggregateData from bonsai.bim.module.aggregate.data import AggregateData
from bonsai.bim.module.group.data import GroupsData, ObjectGroupsData
class BIM_PT_aggregate(Panel): class BIM_PT_aggregate(Panel):
@@ -18,24 +18,14 @@
# pyright: reportUnnecessaryTypeIgnoreComment=error # pyright: reportUnnecessaryTypeIgnoreComment=error
import calendar
import json
import os
import time import time
from datetime import datetime
import bpy import bpy
import ifcopenshell.api.alignment import ifcopenshell.api.alignment
import ifcopenshell.api.spatial import ifcopenshell.api.spatial
import ifcopenshell.geom import ifcopenshell.geom
import ifcopenshell.util.selector
import ifcopenshell.util.sequence
import isodate
from bpy_extras.io_utils import ImportHelper from bpy_extras.io_utils import ImportHelper
from dateutil import parser, relativedelta
import bonsai.bim.module.sequence.helper as helper
import bonsai.core.sequence as core
import bonsai.tool as tool import bonsai.tool as tool
@@ -23,16 +23,12 @@ from bpy.props import (
BoolProperty, BoolProperty,
CollectionProperty, CollectionProperty,
EnumProperty, EnumProperty,
FloatProperty,
FloatVectorProperty,
IntProperty, IntProperty,
PointerProperty,
StringProperty,
) )
from bpy.types import PropertyGroup from bpy.types import PropertyGroup
import bonsai.tool as tool import bonsai.tool as tool
from bonsai.bim.prop import Attribute, StrProperty from bonsai.bim.prop import Attribute
class BIMAttributeProperties(PropertyGroup): class BIMAttributeProperties(PropertyGroup):
@@ -19,9 +19,7 @@
import os import os
from typing import Union from typing import Union
import bcf
import bcf.bcfxml import bcf.bcfxml
import bcf.v2.bcfxml
import bpy import bpy
import bonsai.tool as tool import bonsai.tool as tool
+2 -7
View File
@@ -16,22 +16,18 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>. # along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
import os
import tempfile import tempfile
import uuid import uuid
import webbrowser import webbrowser
from math import atan, cos, degrees, radians, sin, tan from math import atan, degrees, radians, tan
from pathlib import Path from pathlib import Path
import bcf
import bcf.agnostic.topic import bcf.agnostic.topic
import bcf.agnostic.visinfo import bcf.agnostic.visinfo
import bcf.bcfxml
import bcf.v2.bcfxml import bcf.v2.bcfxml
import bcf.v2.model import bcf.v2.model
import bcf.v2.topic import bcf.v2.topic
import bcf.v2.visinfo import bcf.v2.visinfo
import bcf.v3
import bcf.v3.bcfxml import bcf.v3.bcfxml
import bcf.v3.document import bcf.v3.document
import bcf.v3.model import bcf.v3.model
@@ -43,11 +39,10 @@ import ifcopenshell.util.geolocation
import ifcopenshell.util.unit import ifcopenshell.util.unit
import numpy as np import numpy as np
from bpy_extras.io_utils import ExportHelper, ImportHelper from bpy_extras.io_utils import ExportHelper, ImportHelper
from mathutils import Euler, Matrix, Vector, geometry from mathutils import Matrix, Vector
from xsdata.models.datatype import XmlDateTime from xsdata.models.datatype import XmlDateTime
import bonsai.bim.module.bcf.bcfstore as bcfstore import bonsai.bim.module.bcf.bcfstore as bcfstore
import bonsai.bim.module.bcf.prop as bcf_prop
import bonsai.tool as tool import bonsai.tool as tool
-2
View File
@@ -24,8 +24,6 @@ from bpy.props import (
BoolProperty, BoolProperty,
CollectionProperty, CollectionProperty,
EnumProperty, EnumProperty,
FloatProperty,
FloatVectorProperty,
IntProperty, IntProperty,
PointerProperty, PointerProperty,
StringProperty, StringProperty,
-1
View File
@@ -18,7 +18,6 @@
from __future__ import annotations from __future__ import annotations
import os
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
import bpy import bpy
@@ -20,7 +20,6 @@ import bmesh
import gpu import gpu
from bpy.types import SpaceView3D from bpy.types import SpaceView3D
from gpu_extras.batch import batch_for_shader from gpu_extras.batch import batch_for_shader
from mathutils import Vector
import bonsai.tool as tool import bonsai.tool as tool
@@ -29,18 +29,15 @@ import ifcopenshell.api.root
import ifcopenshell.geom import ifcopenshell.geom
import ifcopenshell.util.element import ifcopenshell.util.element
import ifcopenshell.util.placement import ifcopenshell.util.placement
import ifcopenshell.util.representation
import ifcopenshell.util.shape import ifcopenshell.util.shape
import ifcopenshell.util.unit import ifcopenshell.util.unit
import mathutils import mathutils
import numpy as np
import shapely import shapely
import shapely.ops import shapely.ops
from ifcopenshell.util.shape_builder import ShapeBuilder from ifcopenshell.util.shape_builder import ShapeBuilder
from mathutils import Matrix, Vector from mathutils import Matrix, Vector
import bonsai.bim.import_ifc as import_ifc import bonsai.bim.import_ifc as import_ifc
import bonsai.core
import bonsai.core.geometry import bonsai.core.geometry
import bonsai.tool as tool import bonsai.tool as tool
from bonsai.bim.ifc import IfcStore from bonsai.bim.ifc import IfcStore
@@ -21,13 +21,7 @@ from typing import TYPE_CHECKING, Union
import bpy import bpy
from bpy.props import ( from bpy.props import (
BoolProperty, BoolProperty,
CollectionProperty,
EnumProperty,
FloatProperty,
FloatVectorProperty,
IntProperty,
PointerProperty, PointerProperty,
StringProperty,
) )
from bpy.types import PropertyGroup from bpy.types import PropertyGroup
+1 -2
View File
@@ -16,8 +16,7 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>. # along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
import bpy from bpy.types import Panel
from bpy.types import Panel, UIList
import bonsai.tool as tool import bonsai.tool as tool
from bonsai.bim.module.boundary.data import SpaceBoundariesData from bonsai.bim.module.boundary.data import SpaceBoundariesData
+2 -6
View File
@@ -63,8 +63,7 @@ class BrickschemaData:
if namespace == "https://brickschema.org/schema/Brick": if namespace == "https://brickschema.org/schema/Brick":
return [] return []
results = [] results = []
query = BrickStore.graph.query( query = BrickStore.graph.query("""
"""
PREFIX brick: <https://brickschema.org/schema/Brick#> PREFIX brick: <https://brickschema.org/schema/Brick#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
@@ -81,10 +80,7 @@ class BrickschemaData:
} }
} }
GROUP BY ?object GROUP BY ?object
""".replace( """.replace("{uri}", uri))
"{uri}", uri
)
)
for row in query: for row in query:
predicate_uri = row.get("predicate") predicate_uri = row.get("predicate")
predicate_name = predicate_uri.toPython().split("#")[-1] predicate_name = predicate_uri.toPython().split("#")[-1]
@@ -19,7 +19,6 @@
import os import os
import bpy import bpy
import ifcopenshell.api
from bpy_extras.io_utils import ExportHelper, ImportHelper from bpy_extras.io_utils import ExportHelper, ImportHelper
import bonsai.bim.handler import bonsai.bim.handler
+1 -4
View File
@@ -23,10 +23,7 @@ from bpy.props import (
BoolProperty, BoolProperty,
CollectionProperty, CollectionProperty,
EnumProperty, EnumProperty,
FloatProperty,
FloatVectorProperty,
IntProperty, IntProperty,
PointerProperty,
StringProperty, StringProperty,
) )
from bpy.types import PropertyGroup from bpy.types import PropertyGroup
@@ -34,7 +31,7 @@ from bpy.types import PropertyGroup
import bonsai.core.brick as core import bonsai.core.brick as core
import bonsai.tool.brick as tool import bonsai.tool.brick as tool
from bonsai.bim.module.brick.data import BrickschemaData, BrickschemaReferencesData from bonsai.bim.module.brick.data import BrickschemaData, BrickschemaReferencesData
from bonsai.bim.prop import Attribute, StrProperty from bonsai.bim.prop import StrProperty
from bonsai.tool.brick import BrickStore from bonsai.tool.brick import BrickStore
@@ -16,13 +16,8 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>. # along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
import bpy
import ifcopenshell
import ifcopenshell.util.classification
import ifcopenshell.util.date
import bonsai.tool as tool import bonsai.tool as tool
from bonsai.bim.ifc import IfcStore
def refresh(): def refresh():
@@ -19,7 +19,6 @@ import textwrap
from typing import Any from typing import Any
import bpy import bpy
import bsdd
import ifcopenshell.api.pset import ifcopenshell.api.pset
import ifcopenshell.util.element import ifcopenshell.util.element
+1 -4
View File
@@ -23,10 +23,7 @@ from bpy.props import (
BoolProperty, BoolProperty,
CollectionProperty, CollectionProperty,
EnumProperty, EnumProperty,
FloatProperty,
FloatVectorProperty,
IntProperty, IntProperty,
PointerProperty,
StringProperty, StringProperty,
) )
from bpy.types import PropertyGroup from bpy.types import PropertyGroup
@@ -34,7 +31,7 @@ from bpy.types import PropertyGroup
import bonsai.tool as tool import bonsai.tool as tool
from bonsai.bim.module.bsdd.data import BSDDData from bonsai.bim.module.bsdd.data import BSDDData
from bonsai.bim.module.classification.data import ClassificationsData from bonsai.bim.module.classification.data import ClassificationsData
from bonsai.bim.prop import Attribute, StrProperty from bonsai.bim.prop import Attribute
def get_active_dictionary(self: "BIMBSDDProperties", context: object) -> tool.Blender.BLENDER_ENUM_ITEMS: def get_active_dictionary(self: "BIMBSDDProperties", context: object) -> tool.Blender.BLENDER_ENUM_ITEMS:
+1 -3
View File
@@ -17,13 +17,11 @@
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>. # along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
import math import math
from math import cos, pi, radians, sin, sqrt from math import pi, sqrt
from typing import Union
import bmesh import bmesh
import bpy import bpy
import bpy_extras import bpy_extras
import ifcopenshell.util.unit
import mathutils import mathutils
from mathutils import Matrix, Vector from mathutils import Matrix, Vector
-2
View File
@@ -22,8 +22,6 @@ from typing import TYPE_CHECKING
import bpy import bpy
from bpy.types import PropertyGroup from bpy.types import PropertyGroup
from bonsai.bim.module.model.data import AuthoringData
class BIMCadProperties(PropertyGroup): class BIMCadProperties(PropertyGroup):
resolution: bpy.props.IntProperty(name="Arc Resolution", min=1, default=1) resolution: bpy.props.IntProperty(name="Arc Resolution", min=1, default=1)
@@ -20,12 +20,10 @@ import os
from functools import partial from functools import partial
import bpy import bpy
import ifcopenshell.util.unit
from bpy.types import WorkSpaceTool from bpy.types import WorkSpaceTool
import bonsai.bim.module.type.prop as type_prop
import bonsai.tool as tool import bonsai.tool as tool
from bonsai.bim.module.model.data import AuthoringData, RailingData, RoofData from bonsai.bim.module.model.data import RailingData, RoofData
def load_custom_icons(): def load_custom_icons():
@@ -18,9 +18,6 @@
import json import json
import bpy
import ifcopenshell.util.element
import bonsai.tool as tool import bonsai.tool as tool
@@ -17,7 +17,6 @@
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>. # along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
import blf import blf
import bmesh
import gpu import gpu
from bpy.types import SpaceView3D from bpy.types import SpaceView3D
from bpy_extras.view3d_utils import location_3d_to_region_2d from bpy_extras.view3d_utils import location_3d_to_region_2d
@@ -18,16 +18,13 @@
import json import json
import logging import logging
import os
import tempfile import tempfile
from math import radians from math import radians
from pathlib import Path from pathlib import Path
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
import bmesh
import bpy import bpy
import ifcopenshell import ifcopenshell
import numpy as np
from bpy_extras.io_utils import ExportHelper, ImportHelper from bpy_extras.io_utils import ExportHelper, ImportHelper
from mathutils import Matrix, Vector from mathutils import Matrix, Vector
+1 -2
View File
@@ -26,7 +26,6 @@ from bpy.props import (
FloatProperty, FloatProperty,
FloatVectorProperty, FloatVectorProperty,
IntProperty, IntProperty,
PointerProperty,
StringProperty, StringProperty,
) )
from bpy.types import PropertyGroup from bpy.types import PropertyGroup
@@ -34,7 +33,7 @@ from ifcopenshell.geom.main import CLASH_TYPE_ITEMS, ClashType
from mathutils import Vector from mathutils import Vector
import bonsai.tool as tool import bonsai.tool as tool
from bonsai.bim.prop import Attribute, BIMFilterGroup, StrProperty from bonsai.bim.prop import BIMFilterGroup, StrProperty
class ClashSource(PropertyGroup): class ClashSource(PropertyGroup):
@@ -18,7 +18,6 @@
import bpy import bpy
import ifcopenshell import ifcopenshell
import ifcopenshell.api
import ifcopenshell.api.classification import ifcopenshell.api.classification
import ifcopenshell.api.pset import ifcopenshell.api.pset
import ifcopenshell.util.classification import ifcopenshell.util.classification
@@ -23,10 +23,7 @@ from bpy.props import (
BoolProperty, BoolProperty,
CollectionProperty, CollectionProperty,
EnumProperty, EnumProperty,
FloatProperty,
FloatVectorProperty,
IntProperty, IntProperty,
PointerProperty,
StringProperty, StringProperty,
) )
from bpy.types import PropertyGroup from bpy.types import PropertyGroup
@@ -25,7 +25,6 @@ import ifcopenshell.util.classification
from bpy.types import Panel, UIList from bpy.types import Panel, UIList
import bonsai.bim.helper import bonsai.bim.helper
import bonsai.bim.module.classification.prop as classification_prop
import bonsai.tool as tool import bonsai.tool as tool
from bonsai.bim.module.classification.data import ( from bonsai.bim.module.classification.data import (
ClassificationsData, ClassificationsData,
@@ -19,7 +19,6 @@
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
import bpy import bpy
import ifcopenshell.api
import ifcopenshell.api.constraint import ifcopenshell.api.constraint
import bonsai.bim.helper import bonsai.bim.helper
@@ -20,19 +20,13 @@ from typing import TYPE_CHECKING, Literal
import bpy import bpy
from bpy.props import ( from bpy.props import (
BoolProperty,
CollectionProperty, CollectionProperty,
EnumProperty, EnumProperty,
FloatProperty,
FloatVectorProperty,
IntProperty, IntProperty,
PointerProperty,
StringProperty, StringProperty,
) )
from bpy.types import PropertyGroup from bpy.types import PropertyGroup
from ifcopenshell.util.doc import get_entity_doc
import bonsai.tool as tool
from bonsai.bim.module.constraint.data import ConstraintsData from bonsai.bim.module.constraint.data import ConstraintsData
from bonsai.bim.prop import Attribute from bonsai.bim.prop import Attribute
@@ -18,7 +18,6 @@
from typing import Any from typing import Any
import bpy
import ifcopenshell import ifcopenshell
import bonsai.tool as tool import bonsai.tool as tool
+1 -7
View File
@@ -20,19 +20,13 @@ from typing import TYPE_CHECKING
import bpy import bpy
from bpy.props import ( from bpy.props import (
BoolProperty,
CollectionProperty, CollectionProperty,
EnumProperty, EnumProperty,
FloatProperty,
FloatVectorProperty,
IntProperty, IntProperty,
PointerProperty,
StringProperty,
) )
from bpy.types import PropertyGroup from bpy.types import PropertyGroup
from bonsai.bim.module.context.data import ContextData from bonsai.bim.prop import Attribute
from bonsai.bim.prop import Attribute, StrProperty
class BIMContextProperties(PropertyGroup): class BIMContextProperties(PropertyGroup):
@@ -18,13 +18,11 @@
from typing import Any, Union from typing import Any, Union
import bpy
import ifcopenshell import ifcopenshell
import ifcopenshell.util.cost import ifcopenshell.util.cost
import ifcopenshell.util.date import ifcopenshell.util.date
import ifcopenshell.util.element import ifcopenshell.util.element
import ifcopenshell.util.unit import ifcopenshell.util.unit
from ifcopenshell.util.doc import get_entity_doc, get_predefined_type_doc
import bonsai.tool as tool import bonsai.tool as tool
@@ -987,10 +987,10 @@ class ExportCostSchedulesToPDF(bpy.types.Operator, ExportHelper):
@classmethod @classmethod
def poll(cls, context): def poll(cls, context):
try: try:
import typst import typst # noqa: F401
return True return True
except: except ModuleNotFoundError:
cls.poll_message_set( cls.poll_message_set(
"Typst not available.\nIt can be installed from Quality and\nControl -> Debug and using 'typst' with Pip Install.\n(Run Blender as Administrator)" "Typst not available.\nIt can be installed from Quality and\nControl -> Debug and using 'typst' with Pip Install.\n(Run Blender as Administrator)"
) )
@@ -19,16 +19,13 @@
from typing import TYPE_CHECKING, Literal, Union from typing import TYPE_CHECKING, Literal, Union
import bpy import bpy
import ifcopenshell.api
import ifcopenshell.api.cost import ifcopenshell.api.cost
from bpy.props import ( from bpy.props import (
BoolProperty, BoolProperty,
CollectionProperty, CollectionProperty,
EnumProperty, EnumProperty,
FloatProperty, FloatProperty,
FloatVectorProperty,
IntProperty, IntProperty,
PointerProperty,
StringProperty, StringProperty,
) )
from bpy.types import PropertyGroup from bpy.types import PropertyGroup
@@ -21,7 +21,6 @@ import os
from functools import partial from functools import partial
import bpy import bpy
import ifcopenshell
from bpy.types import WorkSpaceTool from bpy.types import WorkSpaceTool
import bonsai.tool as tool import bonsai.tool as tool
@@ -20,7 +20,6 @@ import json
from math import atan2, degrees from math import atan2, degrees
import bpy import bpy
import ifcopenshell
import ifcopenshell.util.element import ifcopenshell.util.element
import bonsai.tool as tool import bonsai.tool as tool
@@ -19,14 +19,10 @@
from __future__ import annotations from __future__ import annotations
import json import json
import logging
import os
import tempfile
from collections import Counter from collections import Counter
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
import bpy import bpy
import ifccsv
import ifcopenshell import ifcopenshell
import ifcopenshell.util.selector import ifcopenshell.util.selector
from bpy_extras.io_utils import ExportHelper, ImportHelper from bpy_extras.io_utils import ExportHelper, ImportHelper
+1 -5
View File
@@ -23,15 +23,11 @@ from bpy.props import (
BoolProperty, BoolProperty,
CollectionProperty, CollectionProperty,
EnumProperty, EnumProperty,
FloatProperty,
FloatVectorProperty,
IntProperty,
PointerProperty,
StringProperty, StringProperty,
) )
from bpy.types import PropertyGroup from bpy.types import PropertyGroup
from bonsai.bim.prop import BIMFilterGroup, StrProperty from bonsai.bim.prop import BIMFilterGroup
class CsvAttribute(PropertyGroup): class CsvAttribute(PropertyGroup):
@@ -29,7 +29,6 @@ from typing import TYPE_CHECKING, Any, Literal, Union, assert_never, get_args
import bpy import bpy
import ifcopenshell import ifcopenshell
import ifcopenshell.api
import ifcopenshell.api.pset import ifcopenshell.api.pset
import ifcopenshell.geom import ifcopenshell.geom
import ifcopenshell.ifcopenshell_wrapper as W import ifcopenshell.ifcopenshell_wrapper as W
@@ -20,13 +20,9 @@ from typing import TYPE_CHECKING, Literal, get_args
import bpy import bpy
from bpy.props import ( from bpy.props import (
BoolProperty,
CollectionProperty, CollectionProperty,
EnumProperty, EnumProperty,
FloatProperty,
FloatVectorProperty,
IntProperty, IntProperty,
PointerProperty,
StringProperty, StringProperty,
) )
from bpy.types import PropertyGroup from bpy.types import PropertyGroup
@@ -32,18 +32,10 @@
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
import bpy
# Properties have many different data types. We won't use all of them in this # Properties have many different data types. We won't use all of them in this
# demo module, but this is a list for your reference. # demo module, but this is a list for your reference.
from bpy.props import ( from bpy.props import (
BoolProperty, BoolProperty,
CollectionProperty,
EnumProperty,
FloatProperty,
FloatVectorProperty,
IntProperty,
PointerProperty,
StringProperty, StringProperty,
) )
from bpy.types import PropertyGroup from bpy.types import PropertyGroup
+1 -5
View File
@@ -23,16 +23,12 @@ from bpy.props import (
BoolProperty, BoolProperty,
CollectionProperty, CollectionProperty,
EnumProperty, EnumProperty,
FloatProperty,
FloatVectorProperty,
IntProperty,
PointerProperty,
StringProperty, StringProperty,
) )
from bpy.types import PropertyGroup from bpy.types import PropertyGroup
from bonsai.bim.module.diff.data import DiffData from bonsai.bim.module.diff.data import DiffData
from bonsai.bim.prop import BIMFilterGroup, StrProperty from bonsai.bim.prop import BIMFilterGroup
def update_diff_json_file(self: "DiffProperties", context: bpy.types.Context) -> None: def update_diff_json_file(self: "DiffProperties", context: bpy.types.Context) -> None:
@@ -19,8 +19,6 @@
import os import os
import bpy import bpy
import ifcopenshell
import ifcopenshell.util.schema
from natsort import natsorted from natsort import natsorted
import bonsai.tool as tool import bonsai.tool as tool
@@ -20,10 +20,9 @@ import json
import bpy import bpy
import bonsai.bim.handler
import bonsai.core.document as core import bonsai.core.document as core
import bonsai.tool as tool import bonsai.tool as tool
from bonsai.bim.module.document.data import DocumentData, ObjectDocumentData from bonsai.bim.module.document.data import ObjectDocumentData
class LoadProjectDocuments(bpy.types.Operator): class LoadProjectDocuments(bpy.types.Operator):
@@ -5,17 +5,14 @@ from bpy.props import (
BoolProperty, BoolProperty,
CollectionProperty, CollectionProperty,
EnumProperty, EnumProperty,
FloatProperty,
FloatVectorProperty,
IntProperty, IntProperty,
PointerProperty,
StringProperty, StringProperty,
) )
from bpy.types import PropertyGroup from bpy.types import PropertyGroup
import bonsai.tool as tool import bonsai.tool as tool
from bonsai.bim.module.document.data import DocumentData, refresh from bonsai.bim.module.document.data import DocumentData, refresh
from bonsai.bim.prop import Attribute, StrProperty from bonsai.bim.prop import Attribute
def update_document_name(self: "Document", context: bpy.types.Context) -> None: def update_document_name(self: "Document", context: bpy.types.Context) -> None:
@@ -16,7 +16,6 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>. # along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
import bpy
from bpy.types import Panel, UIList from bpy.types import Panel, UIList
import bonsai.tool as tool import bonsai.tool as tool
@@ -18,15 +18,12 @@
from __future__ import annotations from __future__ import annotations
import math
import os
from pathlib import Path
from typing import Optional from typing import Optional
import bmesh import bmesh
import bpy import bpy
import ifcopenshell.util.element import ifcopenshell.util.element
from mathutils import Matrix, Vector from mathutils import Vector
import bonsai.tool as tool import bonsai.tool as tool
@@ -23,8 +23,6 @@ from typing import Any, Union
import bpy import bpy
import ifcopenshell.util.element import ifcopenshell.util.element
import ifcopenshell.util.representation
import ifcopenshell.util.selector
import ifcopenshell.util.unit import ifcopenshell.util.unit
from natsort import natsorted from natsort import natsorted
@@ -23,7 +23,7 @@ from functools import cache
from math import acos, atan, cos, degrees, pi, radians, sin from math import acos, atan, cos, degrees, pi, radians, sin
from pathlib import Path from pathlib import Path
from timeit import default_timer as timer from timeit import default_timer as timer
from typing import Optional, Union from typing import Optional
import blf import blf
import bmesh import bmesh
@@ -34,7 +34,6 @@ import ifcopenshell.util.element
import ifcopenshell.util.representation import ifcopenshell.util.representation
import ifcopenshell.util.unit import ifcopenshell.util.unit
import numpy as np import numpy as np
import shapely
from bpy.types import SpaceView3D from bpy.types import SpaceView3D
from bpy_extras.view3d_utils import location_3d_to_region_2d from bpy_extras.view3d_utils import location_3d_to_region_2d
from gpu_extras.batch import batch_for_shader from gpu_extras.batch import batch_for_shader
@@ -17,10 +17,8 @@
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>. # along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
import math import math
from typing import Union
import bpy import bpy
import ifcopenshell
import ifcopenshell.util.element import ifcopenshell.util.element
import ifcopenshell.util.unit import ifcopenshell.util.unit
import mathutils.geometry import mathutils.geometry
+104 -189
View File
@@ -18,9 +18,9 @@
import hashlib import hashlib
import json import json
import logging
import multiprocessing import multiprocessing
import os import os
import re
import shutil import shutil
import subprocess import subprocess
import time import time
@@ -41,7 +41,6 @@ from typing import (
import bmesh import bmesh
import bpy import bpy
import ifcopenshell import ifcopenshell
import ifcopenshell.api
import ifcopenshell.api.document import ifcopenshell.api.document
import ifcopenshell.api.pset import ifcopenshell.api.pset
import ifcopenshell.api.style import ifcopenshell.api.style
@@ -50,19 +49,18 @@ import ifcopenshell.ifcopenshell_wrapper
import ifcopenshell.util.element import ifcopenshell.util.element
import ifcopenshell.util.representation import ifcopenshell.util.representation
import ifcopenshell.util.selector import ifcopenshell.util.selector
import ifcopenshell.util.shape_builder
import ifcopenshell.util.unit import ifcopenshell.util.unit
import numpy as np import numpy as np
import shapely import shapely
import shapely.ops
from bpy_extras.image_utils import load_image from bpy_extras.image_utils import load_image
from bpy_extras.io_utils import ImportHelper from bpy_extras.io_utils import ImportHelper
from lxml import etree from lxml import etree
from mathutils import Color, Matrix, Vector from mathutils import Color, Vector
import bonsai.bim.export_ifc import bonsai.bim.export_ifc
import bonsai.bim.handler import bonsai.bim.handler
import bonsai.bim.helper import bonsai.bim.import_ifc
import bonsai.bim.module.drawing.annotation as annotation
import bonsai.bim.module.drawing.sheeter as sheeter import bonsai.bim.module.drawing.sheeter as sheeter
import bonsai.bim.module.drawing.svgwriter as svgwriter import bonsai.bim.module.drawing.svgwriter as svgwriter
import bonsai.core.drawing as core import bonsai.core.drawing as core
@@ -138,7 +136,7 @@ class AddAnnotationType(bpy.types.Operator, tool.Ifc.Operator):
element.ApplicableOccurrence = f"IfcAnnotation/{object_type}" element.ApplicableOccurrence = f"IfcAnnotation/{object_type}"
if props.create_representation_for_type and object_type == "IMAGE": if props.create_representation_for_type and object_type == "IMAGE":
bpy.ops.bim.add_reference_image("INVOKE_DEFAULT", use_existing_object_by_name=obj.name) bpy.ops.bim.add_reference_image("INVOKE_DEFAULT", existing_object_by_name=obj.name)
class EnableAddAnnotationType(bpy.types.Operator): class EnableAddAnnotationType(bpy.types.Operator):
@@ -928,7 +926,7 @@ class CreateDrawing(bpy.types.Operator):
props = tool.Project.get_project_props() props = tool.Project.get_project_props()
for link in props.get_loaded_links_for_drawings(): for link in props.get_loaded_links_for_drawings():
files[link.name] = self.get_linked_file(link) files[link.filepath] = self.get_linked_file(link)
target_view = ifcopenshell.util.element.get_psets(self.camera_element)["EPset_Drawing"]["TargetView"] target_view = ifcopenshell.util.element.get_psets(self.camera_element)["EPset_Drawing"]["TargetView"]
self.setup_serialiser(target_view) self.setup_serialiser(target_view)
@@ -1374,7 +1372,7 @@ class CreateDrawing(bpy.types.Operator):
return True return True
def get_linked_file(self, link: "Link") -> ifcopenshell.file: def get_linked_file(self, link: "Link") -> ifcopenshell.file:
link_path = link.name link_path = link.filepath
ifc_file = IfcStore.session_files.get(link_path, None) ifc_file = IfcStore.session_files.get(link_path, None)
if ifc_file is not None: if ifc_file is not None:
return ifc_file return ifc_file
@@ -1759,7 +1757,7 @@ class AddAnnotation(bpy.types.Operator, tool.Ifc.Operator):
enable_editing=True, enable_editing=True,
) )
if props.object_type == "IMAGE": if props.object_type == "IMAGE":
bpy.ops.bim.add_reference_image("INVOKE_DEFAULT", use_existing_object_by_name=obj.name) bpy.ops.bim.add_reference_image("INVOKE_DEFAULT", existing_object_by_name=obj.name)
class AddSheet(bpy.types.Operator, tool.Ifc.Operator): class AddSheet(bpy.types.Operator, tool.Ifc.Operator):
@@ -2896,12 +2894,16 @@ class AddSchedule(bpy.types.Operator, tool.Ifc.Operator, ImportHelper):
bl_options = {"REGISTER", "UNDO"} bl_options = {"REGISTER", "UNDO"}
bl_description = "Add an .ods, .xls or .xlsx file as a schedule" bl_description = "Add an .ods, .xls or .xlsx file as a schedule"
files: bpy.props.CollectionProperty(name="Files", type=bpy.types.OperatorFileListElement)
directory: bpy.props.StringProperty(subtype="DIR_PATH")
filter_glob: bpy.props.StringProperty(default="*.ods;*.xls;*.xlsx", options={"HIDDEN"}) filter_glob: bpy.props.StringProperty(default="*.ods;*.xls;*.xlsx", options={"HIDDEN"})
use_relative_path: bpy.props.BoolProperty(name="Use Relative Path", default=True) use_relative_path: bpy.props.BoolProperty(name="Use Relative Path", default=True)
def _execute(self, context): def _execute(self, context):
filepath = tool.Ifc.get_uri(self.filepath, use_relative_path=self.use_relative_path) for filepath in tool.Blender.get_selected_files(
core.add_document(tool.Ifc, tool.Drawing, "SCHEDULE", uri=filepath) self.directory, self.files, use_relative_path=self.use_relative_path
):
core.add_document(tool.Ifc, tool.Drawing, "SCHEDULE", uri=filepath)
class RemoveSchedule(bpy.types.Operator, tool.Ifc.Operator): class RemoveSchedule(bpy.types.Operator, tool.Ifc.Operator):
@@ -3090,23 +3092,16 @@ class AddReference(bpy.types.Operator, tool.Ifc.Operator, ImportHelper):
bl_description = "Import a .svg file to the project as a reference" bl_description = "Import a .svg file to the project as a reference"
bl_options = {"REGISTER", "UNDO"} bl_options = {"REGISTER", "UNDO"}
files: bpy.props.CollectionProperty(name="Files", type=bpy.types.OperatorFileListElement)
directory: bpy.props.StringProperty(subtype="DIR_PATH")
filter_glob: bpy.props.StringProperty(default="*.svg", options={"HIDDEN"}) filter_glob: bpy.props.StringProperty(default="*.svg", options={"HIDDEN"})
use_relative_path: bpy.props.BoolProperty(name="Use Relative Path", default=True) use_relative_path: bpy.props.BoolProperty(name="Use Relative Path", default=True)
filename_ext = ".svg" filename_ext = ".svg"
files: bpy.props.CollectionProperty(type=bpy.types.OperatorFileListElement)
directory: bpy.props.StringProperty(subtype="DIR_PATH")
def _execute(self, context): def _execute(self, context):
# Handle both single and multiple file selection for filepath in tool.Blender.get_selected_files(
if self.files: self.directory, self.files, use_relative_path=self.use_relative_path
for file_elem in self.files: ):
filepath = os.path.join(self.directory, file_elem.name)
uri = tool.Ifc.get_uri(filepath, use_relative_path=self.use_relative_path)
core.add_document(tool.Ifc, tool.Drawing, "REFERENCE", uri=uri)
else:
# Fallback for single file (backward compatibility)
filepath = tool.Ifc.get_uri(self.filepath, use_relative_path=self.use_relative_path)
core.add_document(tool.Ifc, tool.Drawing, "REFERENCE", uri=filepath) core.add_document(tool.Ifc, tool.Drawing, "REFERENCE", uri=filepath)
@@ -3165,6 +3160,7 @@ class EditTextPopup(bpy.types.Operator):
bpy.ops.bim.disable_editing_text() bpy.ops.bim.disable_editing_text()
def execute(self, context): def execute(self, context):
# TODO: check for possible subtle undo bug here
# can't use invoke() because this operator # can't use invoke() because this operator
# will be run indirectly by hotkey # will be run indirectly by hotkey
# so we use execute() and track whether it's the first run of the operator # so we use execute() and track whether it's the first run of the operator
@@ -3804,83 +3800,51 @@ class AddReferenceImage(bpy.types.Operator, tool.Ifc.Operator, ImportHelper):
use_relative_path: bpy.props.BoolProperty(name="Use Relative Path", default=True) use_relative_path: bpy.props.BoolProperty(name="Use Relative Path", default=True)
filter_image: bpy.props.BoolProperty(default=True, options={"HIDDEN", "SKIP_SAVE"}) filter_image: bpy.props.BoolProperty(default=True, options={"HIDDEN", "SKIP_SAVE"})
filter_folder: bpy.props.BoolProperty(default=True, options={"HIDDEN", "SKIP_SAVE"}) filter_folder: bpy.props.BoolProperty(default=True, options={"HIDDEN", "SKIP_SAVE"})
override_existing_image: bpy.props.BoolProperty(
name="Override Existing Image",
default=True,
description=(
"Override image if it was previously loaded to Blender. If disabled, will always create a new image"
),
)
use_existing_object_by_name: bpy.props.StringProperty(
name="Use Existing Object By Name",
description="Existing object name to add a style with reference image to. If not provided will create a new object.",
options={"SKIP_SAVE"},
)
x_length: bpy.props.FloatProperty( x_length: bpy.props.FloatProperty(
name="X Length", name="X Length",
description="Width of the reference image in project units", description="Width of the reference image",
default=1.0, default=1.0,
min=0.001, min=0.001,
soft_min=0.01, soft_min=0.01,
precision=3, precision=3,
unit="LENGTH",
) )
y_length: bpy.props.FloatProperty( y_length: bpy.props.FloatProperty(
name="Y Length", name="Y Length",
description="Height of the reference image in project units", description="Height of the reference image",
default=1.0, default=1.0,
min=0.001, min=0.001,
soft_min=0.01, soft_min=0.01,
precision=3, precision=3,
unit="LENGTH",
)
show_texture_solid_mode: bpy.props.BoolProperty(
name="Show Texture in Solid mode (slow)",
description="Show Texture in Solid mode (slow)",
default=False,
) )
show_dimensions_dialog: bpy.props.BoolProperty(default=False, options={"HIDDEN", "SKIP_SAVE"}) @classmethod
def poll(cls, context):
def draw(self, context): if not tool.Ifc.get():
layout = self.layout cls.poll_message_set("No IFC project is loaded.")
return False
if getattr(self, "show_dimensions_dialog", False): return True
if tool.Ifc.get():
length_unit = ifcopenshell.util.unit.get_project_unit(tool.Ifc.get(), "LENGTHUNIT")
if length_unit:
unit_name = ifcopenshell.util.unit.get_full_unit_name(length_unit).lower()
else:
unit_name = "project units"
layout.label(text=f"Set Reference Image Dimensions (in {unit_name}):")
else:
layout.label(text="Set Reference Image Dimensions (in project units):")
layout.separator()
layout.prop(self, "x_length")
layout.prop(self, "y_length")
else:
if Path(tool.Ifc.get_path()).is_file():
layout.prop(self, "use_relative_path")
else:
self.use_relative_path = False
layout.label(text="Save the .ifc file first ")
layout.label(text="to use relative paths.")
layout.prop(self, "override_existing_image")
layout.prop(self, "use_existing_object_by_name")
def invoke(self, context, event): def invoke(self, context, event):
if not getattr(self, "show_dimensions_dialog", False): self._last_filepath = ""
context.window_manager.fileselect_add(self) return super().invoke(context, event)
return {"RUNNING_MODAL"}
else: def check(self, context):
return context.window_manager.invoke_props_dialog(self) if not hasattr(self, "_last_filepath"):
self._last_filepath = ""
if self.filepath and self.filepath != self._last_filepath:
self._last_filepath = self.filepath
def execute(self, context):
if not getattr(self, "show_dimensions_dialog", False):
abs_path = Path(self.filepath).absolute().resolve() abs_path = Path(self.filepath).absolute().resolve()
if self.override_existing_image: if abs_path.exists() and abs_path.is_file():
params = {"check_existing": True, "force_reload": True} image = load_image(abs_path.name, str(abs_path.parent), check_existing=False)
else:
params = {"check_existing": False}
try:
image = load_image(abs_path.name, str(abs_path.parent), **params)
image_width_px = image.size[0] image_width_px = image.size[0]
image_height_px = image.size[1] image_height_px = image.size[1]
aspect_ratio = image_width_px / image_height_px aspect_ratio = image_width_px / image_height_px
@@ -3893,17 +3857,23 @@ class AddReferenceImage(bpy.types.Operator, tool.Ifc.Operator, ImportHelper):
self.y_length = 1.0 self.y_length = 1.0
bpy.data.images.remove(image) bpy.data.images.remove(image)
return True
except Exception as e: return False
self.report({"ERROR"}, f"Failed to load image: {str(e)}")
return {"CANCELLED"}
self.show_dimensions_dialog = True def draw(self, context):
return context.window_manager.invoke_props_dialog(self) layout = self.layout
if Path(tool.Ifc.get_path()).is_file():
return self._execute(context) layout.prop(self, "use_relative_path")
else:
self.use_relative_path = False
layout.prop(self, "show_texture_solid_mode")
layout.prop(self, "x_length")
layout.prop(self, "y_length")
def _execute(self, context): def _execute(self, context):
project_props = tool.Project.get_project_props()
project_props.load_indexed_maps = self.show_texture_solid_mode
space = tool.Blender.get_view3d_space() space = tool.Blender.get_view3d_space()
if space.shading.color_type != "TEXTURE": if space.shading.color_type != "TEXTURE":
space.shading.color_type = "TEXTURE" space.shading.color_type = "TEXTURE"
@@ -3916,121 +3886,66 @@ class AddReferenceImage(bpy.types.Operator, tool.Ifc.Operator, ImportHelper):
image_filepath = Path(tool.Ifc.get_uri(self.filepath, use_relative_path=self.use_relative_path)) image_filepath = Path(tool.Ifc.get_uri(self.filepath, use_relative_path=self.use_relative_path))
ifc_file = tool.Ifc.get() ifc_file = tool.Ifc.get()
if self.override_existing_image: params = {"check_existing": False}
params = {"check_existing": True, "force_reload": True}
else:
params = {"check_existing": False}
image = load_image(abs_path.name, str(abs_path.parent), **params) image = load_image(abs_path.name, str(abs_path.parent), **params)
def bm_add_image_plane(mesh): mesh = bpy.data.meshes.new(image_filepath.stem)
bm = tool.Blender.get_bmesh_for_mesh(mesh, clean=True) obj = bpy.data.objects.new(image_filepath.stem, mesh)
element = tool.Drawing.run_root_assign_class(
obj=obj, ifc_class="IfcAnnotation", predefined_type="IMAGE", should_add_representation=False
)
unit_scale = ifcopenshell.util.unit.calculate_unit_scale(ifc_file) builder = ifcopenshell.util.shape_builder.ShapeBuilder(ifc_file)
plane_scale = Vector((self.x_length * unit_scale / 2.0, self.y_length * unit_scale / 2.0, 1.0)) unit_scale = ifcopenshell.util.unit.calculate_unit_scale(ifc_file)
matrix = Matrix.LocRotScale(None, None, plane_scale) hx = self.x_length * 0.5 / unit_scale
bmesh.ops.create_grid(bm, x_segments=1, y_segments=1, size=1, matrix=matrix, calc_uvs=False) hy = self.y_length * 0.5 / unit_scale
verts = [(-hx, -hy, 0.0), (hx, -hy, 0.0), (hx, hy, 0.0), (-hx, hy, 0.0)]
item = builder.mesh(verts, [[0, 1, 2, 3]])
if not bm.loops.layers.uv: ifc_context = ifcopenshell.util.representation.get_context(ifc_file, "Model", "Body", "MODEL_VIEW")
uv_layer = bm.loops.layers.uv.new() representation = builder.get_representation(ifc_context, [item])
else: ifcopenshell.api.geometry.assign_representation(ifc_file, element, representation)
uv_layer = bm.loops.layers.uv.active
min_x = min(v.co.x for v in bm.verts) style = ifcopenshell.api.style.add_style(tool.Ifc.get(), name=image_filepath.stem)
max_x = max(v.co.x for v in bm.verts) ifcopenshell.api.style.assign_representation_styles(
min_y = min(v.co.y for v in bm.verts) ifc_file, shape_representation=representation, styles=[style]
max_y = max(v.co.y for v in bm.verts) )
width = max_x - min_x
height = max_y - min_y
for face in bm.faces:
for loop in face.loops:
vert = loop.vert
u = (vert.co.x - min_x) / width if width > 0 else 0.5
v = (vert.co.y - min_y) / height if height > 0 else 0.5
u = max(0.0, min(1.0, u))
v = max(0.0, min(1.0, v))
loop[uv_layer].uv = (u, v)
tool.Blender.apply_bmesh(mesh, bm)
if self.use_existing_object_by_name:
obj = bpy.data.objects[self.use_existing_object_by_name]
bm_add_image_plane(obj.data)
bpy.ops.bim.update_representation(obj=obj.name, ifc_representation_class="")
else:
temp_mesh = bpy.data.meshes.new("temp_mesh")
bm_add_image_plane(temp_mesh)
obj = bpy.data.objects.new(image_filepath.stem, temp_mesh)
tool.Drawing.run_root_assign_class(
obj=obj,
ifc_class="IfcAnnotation",
predefined_type="IMAGE",
should_add_representation=True,
context=ifcopenshell.util.representation.get_context(ifc_file, "Model", "Body", "MODEL_VIEW"),
ifc_representation_class=None,
)
tool.Blender.remove_data_block(temp_mesh)
element = tool.Ifc.get_entity(obj)
if element and isinstance(obj.data, bpy.types.Mesh):
representation = ifcopenshell.util.representation.get_representation(element, "Model", "Body", "MODEL_VIEW")
if representation and representation.Items:
item_id = representation.Items[0].id()
num_faces = len(obj.data.polygons)
obj.data["ios_item_ids"] = [item_id] * num_faces
tool.Blender.Attribute.fill_attribute(obj.data, "ios_item_ids", "FACE", "INT", [item_id] * num_faces)
for item in representation.Items:
if item.is_a("IfcPolygonalFaceSet") and item.Coordinates:
new_coords = []
for vertex in obj.data.vertices:
co = obj.matrix_world @ vertex.co
new_coords.append([co.x, co.y, co.z])
item.Coordinates.CoordList = new_coords
tool.Blender.set_active_object(obj)
material = bpy.data.materials.new(name=image_filepath.stem)
obj.data.materials.append(None) # new slot
obj.material_slots[0].material = material
bpy.ops.bim.add_style()
style = tool.Ifc.get_entity(material)
assert style
tool.Style.assign_style_to_object(style, obj)
# TODO: IfcSurfaceStyleRendering is unnecessary here, added it only because # TODO: IfcSurfaceStyleRendering is unnecessary here, added it only because
# we don't support IfcSurfaceStyleWithTextures without Rendering yet # we don't support IfcSurfaceStyleWithTextures without Rendering yet
shading_attributes = { shading_attributes = {
"SurfaceColour": { "SurfaceColour": {"Red": 1.0, "Green": 1.0, "Blue": 1.0},
"Red": 1.0,
"Green": 1.0,
"Blue": 1.0,
},
"Transparency": 0.0, "Transparency": 0.0,
"ReflectanceMethod": "NOTDEFINED", "ReflectanceMethod": "NOTDEFINED",
} }
ifcopenshell.api.style.add_surface_style( ifcopenshell.api.style.add_surface_style(
tool.Ifc.get(), tool.Ifc.get(), style=style, ifc_class="IfcSurfaceStyleRendering", attributes=shading_attributes
style=style,
ifc_class="IfcSurfaceStyleRendering",
attributes=shading_attributes,
) )
texture = ifc_file.create_entity("IfcImageTexture", Mode="DIFFUSE", URLReference=image_filepath.as_posix())
textures = [texture]
ifc_file.create_entity("IfcTextureCoordinateGenerator", Maps=textures, Mode="COORD") # UV map
ifcopenshell.api.style.add_surface_style(
ifc_file,
style=style,
ifc_class="IfcSurfaceStyleWithTextures",
attributes={"Textures": textures},
)
tool.Style.reload_material_from_ifc(material)
tool.Geometry.record_object_materials(obj)
return {"FINISHED"} if tool.Ifc.get_schema() == "IFC2X3":
texture = ifc_file.create_entity(
"IfcImageTexture",
RepeatS=True,
RepeatT=True,
TextureType="TEXTURE",
UrlReference=image_filepath.as_posix(),
)
else:
texture = ifc_file.create_entity("IfcImageTexture", Mode="DIFFUSE", URLReference=image_filepath.as_posix())
ifc_file.create_entity("IfcTextureCoordinateGenerator", Maps=[texture], Mode="COORD")
textures = [texture]
ifcopenshell.api.style.add_surface_style(
ifc_file, style=style, ifc_class="IfcSurfaceStyleWithTextures", attributes={"Textures": textures}
)
logger = logging.getLogger("ImportIFC")
ifc_import_settings = bonsai.bim.import_ifc.IfcImportSettings.factory(bpy.context, None, logger)
ifc_importer = bonsai.bim.import_ifc.IfcImporter(ifc_import_settings)
ifc_importer.file = tool.Ifc.get()
ifc_importer.create_style(style)
bonsai.core.geometry.switch_representation(tool.Ifc, tool.Geometry, obj=obj, representation=representation)
class ConvertSVGToDXF(bpy.types.Operator): class ConvertSVGToDXF(bpy.types.Operator):
+2 -8
View File
@@ -18,14 +18,11 @@
import enum import enum
import json import json
import os
from collections.abc import Callable from collections.abc import Callable
from pathlib import Path from typing import TYPE_CHECKING, Any, Literal, Union
from typing import TYPE_CHECKING, Any, Literal, Union, get_args
import bpy import bpy
import ifcopenshell import ifcopenshell
import ifcopenshell.api
import ifcopenshell.api.pset import ifcopenshell.api.pset
import ifcopenshell.util.element import ifcopenshell.util.element
from bpy.props import ( from bpy.props import (
@@ -34,7 +31,6 @@ from bpy.props import (
CollectionProperty, CollectionProperty,
EnumProperty, EnumProperty,
FloatProperty, FloatProperty,
FloatVectorProperty,
IntProperty, IntProperty,
PointerProperty, PointerProperty,
StringProperty, StringProperty,
@@ -42,19 +38,17 @@ from bpy.props import (
from bpy.types import PropertyGroup from bpy.types import PropertyGroup
from mathutils import Matrix from mathutils import Matrix
import bonsai.bim.module.drawing.annotation as annotation
import bonsai.bim.module.drawing.decoration as decoration import bonsai.bim.module.drawing.decoration as decoration
import bonsai.core.drawing as core import bonsai.core.drawing as core
import bonsai.tool as tool import bonsai.tool as tool
from bonsai.bim.module.drawing.data import ( from bonsai.bim.module.drawing.data import (
AnnotationData, AnnotationData,
DecoratorData,
DrawingsData, DrawingsData,
ElementValuesData, ElementValuesData,
SheetsData, SheetsData,
) )
from bonsai.bim.module.drawing.data import refresh as refresh_drawing_data from bonsai.bim.module.drawing.data import refresh as refresh_drawing_data
from bonsai.bim.prop import Attribute, BIMFilterGroup, StrProperty from bonsai.bim.prop import Attribute, BIMFilterGroup
diagram_scales_enum = [] diagram_scales_enum = []
@@ -22,7 +22,6 @@ import string
from pathlib import Path from pathlib import Path
from textwrap import wrap from textwrap import wrap
import bpy
import openpyxl import openpyxl
import openpyxl.cell # Unnecessary, bug in typeshed. import openpyxl.cell # Unnecessary, bug in typeshed.
import openpyxl.utils # Unnecessary, bug in typeshed. import openpyxl.utils # Unnecessary, bug in typeshed.
@@ -33,7 +32,6 @@ from odf.table import Table, TableCell, TableColumn, TableRow
from odf.text import P from odf.text import P
import bonsai.tool as tool import bonsai.tool as tool
from bonsai.bim.ifc import IfcStore
from bonsai.bim.module.drawing.svgwriter import SvgWriter from bonsai.bim.module.drawing.svgwriter import SvgWriter
DEBUG = False DEBUG = False
@@ -335,12 +335,9 @@ class BaseLinesShader(BaseShader):
TYPE = "LINES" TYPE = "LINES"
DEF_GLSL = ( DEF_GLSL = BaseShader.DEF_GLSL + """
BaseShader.DEF_GLSL
+ """
#define GAP_SIZE {gap_size} #define GAP_SIZE {gap_size}
""" """
)
GEOM_GLSL = """ GEOM_GLSL = """
layout(lines) in; layout(lines) in;
@@ -401,13 +398,10 @@ class DotsGizmoShader(GizmoShader):
TYPE = "POINTS" TYPE = "POINTS"
DEF_GLSL = ( DEF_GLSL = BaseShader.DEF_GLSL + """
BaseShader.DEF_GLSL
+ """
#define CIRCLE_SEGMENTS 12 #define CIRCLE_SEGMENTS 12
#define CIRCLE_RADIUS 8 #define CIRCLE_RADIUS 8
""" """
)
GEOM_GLSL = """ GEOM_GLSL = """
layout(points) in; layout(points) in;
@@ -26,7 +26,6 @@ import xml.etree.ElementTree as ET
from pathlib import Path from pathlib import Path
from xml.dom import minidom from xml.dom import minidom
import bpy
import ifcopenshell.util.geolocation import ifcopenshell.util.geolocation
import pystache import pystache
from mathutils import Vector from mathutils import Vector
@@ -18,7 +18,6 @@
import math import math
import os import os
import re
import shutil import shutil
import xml.etree.ElementTree as ET import xml.etree.ElementTree as ET
from collections.abc import Callable, Sequence from collections.abc import Callable, Sequence
@@ -30,10 +29,8 @@ import bmesh
import bpy import bpy
import ifcopenshell import ifcopenshell
import ifcopenshell.util.element import ifcopenshell.util.element
import ifcopenshell.util.representation
import ifcopenshell.util.selector import ifcopenshell.util.selector
import ifcopenshell.util.unit import ifcopenshell.util.unit
import mathutils
import svgwrite import svgwrite
import svgwrite.container import svgwrite.container
import svgwrite.text import svgwrite.text
@@ -1026,7 +1023,8 @@ class SvgWriter:
for text_literal in text_literals: for text_literal in text_literals:
text = tool.Drawing.replace_text_literal_variables(text_literal.Literal, product or element) text = tool.Drawing.replace_text_literal_variables(text_literal.Literal, product or element)
if newline_at:
text = helper.add_newline_between_words(text, newline_at)
text_segments = parse_markdown_it(text) text_segments = parse_markdown_it(text)
if len(text_segments) == 1 and text_segments[0]["url"] is None and not text_segments[0].get("break", False): if len(text_segments) == 1 and text_segments[0]["url"] is None and not text_segments[0].get("break", False):
+1 -2
View File
@@ -30,7 +30,6 @@ from bonsai.bim.module.drawing.data import (
DocumentsData, DocumentsData,
DrawingsData, DrawingsData,
ElementFiltersData, ElementFiltersData,
ElementValuesData,
ProductAssignmentsData, ProductAssignmentsData,
SheetsData, SheetsData,
) )
@@ -89,7 +88,7 @@ class BIM_PT_camera(Panel):
for link in links: for link in links:
row = panel.row(align=True) row = panel.row(align=True)
split = row.split(factor=0.9) split = row.split(factor=0.9)
split.label(text=link.name, icon="FILE") split.label(text=link.filepath, icon="FILE")
split.prop(link, "include_in_drawings", text="") split.prop(link, "include_in_drawings", text="")
else: else:
panel.label(text="No IFC projects linked and loaded.") panel.label(text="No IFC projects linked and loaded.")
-2
View File
@@ -16,8 +16,6 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>. # along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
import importlib
import os
import ifcfm import ifcfm
@@ -16,10 +16,7 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>. # along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
import json
import logging
import os import os
import tempfile
import bpy import bpy
import ifcfm import ifcfm
-4
View File
@@ -23,11 +23,7 @@ from bpy.props import (
BoolProperty, BoolProperty,
CollectionProperty, CollectionProperty,
EnumProperty, EnumProperty,
FloatProperty,
FloatVectorProperty,
IntProperty,
PointerProperty, PointerProperty,
StringProperty,
) )
from bpy.types import PropertyGroup from bpy.types import PropertyGroup
@@ -16,8 +16,6 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>. # along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
import math
import bpy import bpy
import ifcopenshell.util.element import ifcopenshell.util.element
from bpy.app.handlers import persistent from bpy.app.handlers import persistent
@@ -19,7 +19,6 @@
from collections.abc import Sequence from collections.abc import Sequence
import blf import blf
import bmesh
import bpy import bpy
import gpu import gpu
import ifcopenshell import ifcopenshell
@@ -16,22 +16,17 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>. # along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
from math import pi, pow from math import pi
from typing import Any, Optional, TypeVar, Union from typing import Any, Optional, TypeVar, Union
import bmesh import bmesh
import bpy import bpy
import ifcopenshell import ifcopenshell
import ifcopenshell.util.shape
import ifcopenshell.util.unit import ifcopenshell.util.unit
import mathutils import mathutils
import numpy as np
import shapely
from ifcopenshell.util.shape_builder import ShapeBuilder from ifcopenshell.util.shape_builder import ShapeBuilder
from mathutils import Matrix, Vector, geometry from mathutils import Matrix, Vector, geometry
import bonsai.tool as tool
T = TypeVar("T") T = TypeVar("T")
@@ -16,7 +16,6 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>. # along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
import re
from collections.abc import Sequence from collections.abc import Sequence
from time import time from time import time
from typing import ( from typing import (
@@ -32,11 +31,9 @@ from typing import (
import bmesh import bmesh
import bpy import bpy
import ifcopenshell import ifcopenshell
import ifcopenshell.api
import ifcopenshell.api.boundary import ifcopenshell.api.boundary
import ifcopenshell.api.drawing import ifcopenshell.api.drawing
import ifcopenshell.api.geometry import ifcopenshell.api.geometry
import ifcopenshell.api.grid
import ifcopenshell.api.group import ifcopenshell.api.group
import ifcopenshell.api.layer import ifcopenshell.api.layer
import ifcopenshell.api.material import ifcopenshell.api.material
@@ -61,10 +58,8 @@ import bonsai.core.geometry as core
import bonsai.core.nest import bonsai.core.nest
import bonsai.core.root import bonsai.core.root
import bonsai.core.spatial import bonsai.core.spatial
import bonsai.core.style
import bonsai.tool as tool import bonsai.tool as tool
from bonsai.bim.ifc import IfcStore from bonsai.bim.ifc import IfcStore
from bonsai.bim.module.model.data import AuthoringData
from bonsai.bim.module.model.decorator import ProfileDecorator from bonsai.bim.module.model.decorator import ProfileDecorator
if TYPE_CHECKING: if TYPE_CHECKING:
@@ -902,6 +897,7 @@ class OverrideDelete(bpy.types.Operator):
if not is_valid_data_block: if not is_valid_data_block:
continue continue
element = tool.Ifc.get_entity(obj) element = tool.Ifc.get_entity(obj)
if element: if element:
if tool.Geometry.is_locked(element): if tool.Geometry.is_locked(element):
@@ -912,6 +908,9 @@ class OverrideDelete(bpy.types.Operator):
if ifcopenshell.util.element.get_pset(element, "BBIM_Array"): if ifcopenshell.util.element.get_pset(element, "BBIM_Array"):
self.report({"INFO"}, "Elements that are part of an array cannot be deleted.") self.report({"INFO"}, "Elements that are part of an array cannot be deleted.")
continue continue
if element.is_a("IfcDocumentReference"):
self.report({"INFO"}, "Linked models cannot be deleted.")
continue
if element.is_a("IfcGridAxis"): if element.is_a("IfcGridAxis"):
# Deleting the last W axis is OK # Deleting the last W axis is OK
if ((grid := element.PartOfU) and len(grid[0].UAxes) == 1) or ( if ((grid := element.PartOfU) and len(grid[0].UAxes) == 1) or (
@@ -1208,6 +1207,11 @@ class OverrideDuplicateMove(bpy.types.Operator):
operator.report({"ERROR"}, f"Drawing '{obj.name}' not duplicated.") operator.report({"ERROR"}, f"Drawing '{obj.name}' not duplicated.")
continue continue
if element.is_a("IfcDocumentReference"):
objects_to_remove.add(obj)
operator.report({"ERROR"}, f"Linked model '{obj.name}' not duplicated.")
continue
if tool.Geometry.is_locked(element): if tool.Geometry.is_locked(element):
objects_to_remove.add(obj) objects_to_remove.add(obj)
operator.report({"ERROR"}, lock_error_message(obj.name)) operator.report({"ERROR"}, lock_error_message(obj.name))
@@ -24,8 +24,6 @@ from bpy.props import (
BoolProperty, BoolProperty,
CollectionProperty, CollectionProperty,
EnumProperty, EnumProperty,
FloatProperty,
FloatVectorProperty,
IntProperty, IntProperty,
PointerProperty, PointerProperty,
StringProperty, StringProperty,
@@ -34,7 +32,6 @@ from bpy.types import PropertyGroup
import bonsai.tool as tool import bonsai.tool as tool
from bonsai.bim.module.geometry.data import RepresentationsData, ViewportData from bonsai.bim.module.geometry.data import RepresentationsData, ViewportData
from bonsai.bim.prop import Attribute, ObjProperty, StrProperty
def get_contexts(self: "BIMObjectGeometryProperties", context: bpy.types.Context) -> list[tuple[str, str, str]]: def get_contexts(self: "BIMObjectGeometryProperties", context: bpy.types.Context) -> list[tuple[str, str, str]]:
@@ -17,7 +17,6 @@
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>. # along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
import bpy
import ifcopenshell.util.element import ifcopenshell.util.element
import ifcopenshell.util.geolocation import ifcopenshell.util.geolocation
import ifcopenshell.util.schema import ifcopenshell.util.schema
@@ -19,10 +19,7 @@
from math import radians from math import radians
import blf import blf
import bmesh
import bpy
import gpu import gpu
import ifcopenshell
import ifcopenshell.util.geolocation import ifcopenshell.util.geolocation
from bpy.types import SpaceView3D from bpy.types import SpaceView3D
from bpy_extras.view3d_utils import location_3d_to_region_2d from bpy_extras.view3d_utils import location_3d_to_region_2d
@@ -21,7 +21,6 @@ from bpy_extras.io_utils import ImportHelper
import bonsai.core.georeference as core import bonsai.core.georeference as core
import bonsai.tool as tool import bonsai.tool as tool
from bonsai.bim.module.georeference.decorator import GeoreferenceDecorator
class AddGeoreferencing(bpy.types.Operator, tool.Ifc.Operator): class AddGeoreferencing(bpy.types.Operator, tool.Ifc.Operator):
@@ -51,7 +50,7 @@ class RemoveGeoreferencing(bpy.types.Operator, tool.Ifc.Operator):
bl_description = "Remove the georeferencing" bl_description = "Remove the georeferencing"
def _execute(self, context): def _execute(self, context):
core.remove_georeferencing(tool.Ifc) core.remove_georeferencing(tool.Ifc, tool.Georeference)
class EditGeoreferencing(bpy.types.Operator, tool.Ifc.Operator): class EditGeoreferencing(bpy.types.Operator, tool.Ifc.Operator):
@@ -23,11 +23,7 @@ import ifcopenshell.util.geolocation
from bpy.props import ( from bpy.props import (
BoolProperty, BoolProperty,
CollectionProperty, CollectionProperty,
EnumProperty,
FloatProperty, FloatProperty,
FloatVectorProperty,
IntProperty,
PointerProperty,
StringProperty, StringProperty,
) )
from bpy.types import PropertyGroup from bpy.types import PropertyGroup
@@ -224,16 +220,12 @@ class BIMGeoreferenceProperties(PropertyGroup):
x_axis_ordinate: StringProperty(name="X Axis Ordinate", update=update_grid_north_vector) x_axis_ordinate: StringProperty(name="X Axis Ordinate", update=update_grid_north_vector)
x_axis_is_null: BoolProperty(name="X Axis Is Null") x_axis_is_null: BoolProperty(name="X Axis Is Null")
# These are only for reference to capture data about a host model from a linked model
# If you relink a model from a new host origin, we can autodetect it in theory with this
host_model_origin: StringProperty(name="Host Model Origin")
host_model_origin_si: StringProperty(name="Host Model Origin SI")
host_model_project_north: StringProperty(name="Host Model Angle to Grid North")
# This is the ENH in project units and SI units of the Blender session's 0,0,0. # This is the ENH in project units and SI units of the Blender session's 0,0,0.
# These are only for reference, using tool.Georeference.set_model_origin on # These are only for reference, using tool.Georeference.set_model_origin on
# project load, project create, and when linking for the first time from an # project load, project create, and when linking for the first time from an
# empty Blender session. # empty Blender session.
model_is_georeferenced: BoolProperty(name="Model Is Georeferenced")
model_crs: StringProperty(name="Model CRS")
model_origin: StringProperty(name="Model Origin") model_origin: StringProperty(name="Model Origin")
model_origin_si: StringProperty(name="Model Origin SI") model_origin_si: StringProperty(name="Model Origin SI")
model_project_north: StringProperty(name="Model Angle to Grid North") model_project_north: StringProperty(name="Model Angle to Grid North")
@@ -275,10 +267,6 @@ class BIMGeoreferenceProperties(PropertyGroup):
x_axis_ordinate: str x_axis_ordinate: str
x_axis_is_null: bool x_axis_is_null: bool
host_model_origin: str
host_model_origin_si: str
host_model_project_north: str
model_origin: str model_origin: str
model_origin_si: str model_origin_si: str
model_project_north: str model_project_north: str
@@ -17,9 +17,6 @@
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>. # along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
import bpy import bpy
import ifcopenshell
import ifcopenshell.util.cost
import ifcopenshell.util.element
import bonsai.tool as tool import bonsai.tool as tool

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