mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-08 17:01:40 +00:00
Compare commits
273 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0b3967609c | |||
| 9a7cd5b373 | |||
| 701635b81c | |||
| 88f6c7cf65 | |||
| cbdf1a193e | |||
| 95048ea2dd | |||
| 0e1a2510ff | |||
| fff653b882 | |||
| 160348df1f | |||
| 278a35e729 | |||
| e1bf717af5 | |||
| be30f9cbea | |||
| 4971546de9 | |||
| d9a3c2d5c2 | |||
| 5066fc5a29 | |||
| 9041857277 | |||
| 7e93a73c6a | |||
| 99640912c1 | |||
| 798ed0d502 | |||
| c3f325861c | |||
| 8433999575 | |||
| bba1ff3786 | |||
| a39e4c552a | |||
| 21c6384b7e | |||
| 418d410b5c | |||
| a5461c0748 | |||
| 291e815770 | |||
| 07ef382c7e | |||
| ed500d58ba | |||
| 8023a992da | |||
| fcc80ad14a | |||
| c6b14d1474 | |||
| 37fe0ad993 | |||
| e20e286168 | |||
| 8c0bed0c61 | |||
| 8cfb162851 | |||
| 379c74b31f | |||
| 1d1f158fe2 | |||
| 65d5df7801 | |||
| b246998f68 | |||
| a88c5938dc | |||
| 7978f1fb08 | |||
| 7b4889d2ec | |||
| 65af40e7d5 | |||
| cfe30a505e | |||
| 04677c1b80 | |||
| f06873d24e | |||
| cd6e531120 | |||
| f9f0f1915f | |||
| 740fcf7768 | |||
| 067e04b564 | |||
| cd95f46db5 | |||
| 348e48b49c | |||
| 6bb8abdc5a | |||
| b7a8c9b330 | |||
| e6780973da | |||
| c6072e416c | |||
| f5686fff26 | |||
| e0a1577ae0 | |||
| a46cdbb907 | |||
| a4d5d4e19a | |||
| 17b88fff22 | |||
| 3fe9980aa4 | |||
| dffa3515c0 | |||
| 1d5108f934 | |||
| 02fab6eee2 | |||
| 5e9f97a0c7 | |||
| 2692341d3a | |||
| a54b21b838 | |||
| 79ef6eb55c | |||
| 7e1843b962 | |||
| 7411da2ae8 | |||
| 2f586d6b9e | |||
| f10d4602fc | |||
| 50d00eba20 | |||
| 95480a231c | |||
| a62b177b19 | |||
| d6b636909f | |||
| abf0d6f81a | |||
| 015431fa1f | |||
| 95cc52a6f3 | |||
| 9dff1441d7 | |||
| fdf23ece85 | |||
| 1445f89f19 | |||
| 33a4639de5 | |||
| a3038528bb | |||
| eea060b72d | |||
| 862697baae | |||
| 9a3ae628aa | |||
| 46da629c8b | |||
| fd85b29777 | |||
| fe395f9024 | |||
| 95952d03f8 | |||
| 5ad40612fb | |||
| 950e147bde | |||
| 6294c35a11 | |||
| de2a7c9527 | |||
| c385b93701 | |||
| 2d2e8e51aa | |||
| 13f03b7487 | |||
| a37de44a24 | |||
| c0b7256832 | |||
| c6257a4b3a | |||
| 9b8b05a570 | |||
| 611a898ada | |||
| 6409f41cdf | |||
| 35dc029898 | |||
| 2f72346845 | |||
| 40e4894f8e | |||
| 91ee2b9222 | |||
| ac4ffd91e7 | |||
| d74588246a | |||
| e8a4590d0a | |||
| 38f9f309e7 | |||
| 47ac909a81 | |||
| 6a63c651d3 | |||
| 2727bec929 | |||
| 22f91e11b3 | |||
| 398cd7571e | |||
| 83d97d7e95 | |||
| e47694458f | |||
| 98a3b2b132 | |||
| d06f5a6cb9 | |||
| 966751a928 | |||
| c1aa1dedba | |||
| cc995db98b | |||
| 0e8c98a7bb | |||
| 5ce6d927f3 | |||
| 34303c2cfe | |||
| 6cfb6d74fe | |||
| e76c2a70e6 | |||
| 53e5f84730 | |||
| bcff5c7449 | |||
| 6f78d60c9f | |||
| ff35666ad9 | |||
| 79fa47fc2f | |||
| 35ae1e927d | |||
| 42db172827 | |||
| f52e95a05a | |||
| 04ad0b92bd | |||
| 24a58cba40 | |||
| 8a32d7bea0 | |||
| bbf8fc2b64 | |||
| 2a60f46516 | |||
| 6ad9949571 | |||
| e41df68124 | |||
| de6f6cc8b2 | |||
| fed98451d4 | |||
| 44a52863a2 | |||
| f725e05655 | |||
| 953c5fddc6 | |||
| 1319391a6b | |||
| bc675ef9b2 | |||
| c6766cefb7 | |||
| c4c1e2ebf9 | |||
| dbb4e91d55 | |||
| 44f0a4a39b | |||
| 6d4eb06d89 | |||
| 72f8218fcd | |||
| 4edcad13b8 | |||
| d4d10b2eb5 | |||
| 523bcf3443 | |||
| b96a21350c | |||
| 2f5bcccd2c | |||
| d62a6186b5 | |||
| a6394d8628 | |||
| b4caf3b2dd | |||
| 0e4f2fada1 | |||
| 12f8863014 | |||
| 884661a454 | |||
| 0d8c4c7795 | |||
| 8f3715c0f1 | |||
| cf52607528 | |||
| 7636ff3fdb | |||
| 0577dbe865 | |||
| a86c333a99 | |||
| 3983bfa467 | |||
| 1137e7b77b | |||
| cc542ad074 | |||
| b41d3ae2b7 | |||
| 5c31ae4c37 | |||
| 92ad7d2ba2 | |||
| ad0c97a6bb | |||
| 3d530b1d39 | |||
| f0308962aa | |||
| 9c6a8bdb90 | |||
| a6a9f9d0a7 | |||
| ab3108ff59 | |||
| 128fdcb62e | |||
| a609bc61b9 | |||
| c739b93389 | |||
| 6b7b834ac0 | |||
| ac128e3395 | |||
| 5dd771c5e5 | |||
| 247f0c41d9 | |||
| bbda8d2aff | |||
| c2cc6f80be | |||
| 8416ca46a7 | |||
| 4c47eb573a | |||
| 84d55d8969 | |||
| 587fc63843 | |||
| 3c3525f205 | |||
| 4da0b04162 | |||
| a3801a0ce9 | |||
| aafa1b95e8 | |||
| f89cf88bc0 | |||
| 0cc3ce8709 | |||
| 421d454ce8 | |||
| 64865c58a5 | |||
| 784415e464 | |||
| c33969d589 | |||
| 41c6eba193 | |||
| 10ce30b2ac | |||
| db52703ce3 | |||
| e55955b72a | |||
| 00c971fa2d | |||
| b86bf45167 | |||
| 22fd318d21 | |||
| 4c1b3221ce | |||
| 9e2b7ba7c8 | |||
| 1576ade147 | |||
| db8a1b9262 | |||
| 09d193045a | |||
| f3295e2663 | |||
| 16a90cadb5 | |||
| 2065d4ce78 | |||
| 5cadfd693f | |||
| 9d1dcf9034 | |||
| ed38d2347c | |||
| 47e259ff2f | |||
| 413530bb0a | |||
| a3bcea008a | |||
| d93363b9bb | |||
| 77a912c756 | |||
| 668b63a323 | |||
| dbc0cca36e | |||
| 009652f97d | |||
| c77c4ce968 | |||
| a0b81e333e | |||
| dfc91e6639 | |||
| 233ad63bca | |||
| 242f1aab35 | |||
| d79524b087 | |||
| 8060c790ed | |||
| 47a2c1d21a | |||
| ed81a0a4b3 | |||
| 26fb6ebd3c | |||
| bb50be389e | |||
| df7318973d | |||
| 46a6356f93 | |||
| 9adbd47181 | |||
| 96a0e9f72d | |||
| 791a41d649 | |||
| 249e68f163 | |||
| 3c8ab26274 | |||
| 18a25ffb0e | |||
| cc341b5ffd | |||
| c8ac61a9d0 | |||
| 7d49113407 | |||
| 153de70a71 | |||
| 1f845569a5 | |||
| 1eb2b65268 | |||
| d7ad0a352e | |||
| d29cecab30 | |||
| 7f87f1fb89 | |||
| e5ccd26762 | |||
| 0243519a68 | |||
| 7ef11361b0 | |||
| dfbaa6ac8e | |||
| c41496a9c3 | |||
| ed7ae0da9c | |||
| 4463235728 | |||
| 628a76e487 |
@@ -139,7 +139,7 @@ jobs:
|
||||
cd ..
|
||||
|
||||
- name: Configure AWS credentials
|
||||
uses: aws-actions/configure-aws-credentials@v5
|
||||
uses: aws-actions/configure-aws-credentials@v6
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_UPLOAD_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_UPLOAD_SECRET_ACCESS_KEY }}
|
||||
|
||||
@@ -77,7 +77,7 @@ jobs:
|
||||
git push || echo "Push failed"
|
||||
|
||||
- name: Configure AWS credentials
|
||||
uses: aws-actions/configure-aws-credentials@v5
|
||||
uses: aws-actions/configure-aws-credentials@v6
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_UPLOAD_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_UPLOAD_SECRET_ACCESS_KEY }}
|
||||
|
||||
@@ -118,7 +118,7 @@ jobs:
|
||||
cd ..
|
||||
|
||||
- name: Configure AWS credentials
|
||||
uses: aws-actions/configure-aws-credentials@v5
|
||||
uses: aws-actions/configure-aws-credentials@v6
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_UPLOAD_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_UPLOAD_SECRET_ACCESS_KEY }}
|
||||
|
||||
@@ -118,7 +118,7 @@ jobs:
|
||||
cd ..
|
||||
|
||||
- name: Configure AWS credentials
|
||||
uses: aws-actions/configure-aws-credentials@v5
|
||||
uses: aws-actions/configure-aws-credentials@v6
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_UPLOAD_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_UPLOAD_SECRET_ACCESS_KEY }}
|
||||
|
||||
@@ -73,7 +73,7 @@ jobs:
|
||||
git push || echo "Push failed"
|
||||
|
||||
- name: Configure AWS Credentials
|
||||
uses: aws-actions/configure-aws-credentials@v5
|
||||
uses: aws-actions/configure-aws-credentials@v6
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_UPLOAD_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_UPLOAD_SECRET_ACCESS_KEY }}
|
||||
|
||||
@@ -35,7 +35,7 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
pyver: [py311, py312]
|
||||
pyver: [py311, py312, py313]
|
||||
config:
|
||||
- {
|
||||
name: "Windows Build",
|
||||
@@ -53,6 +53,11 @@ jobs:
|
||||
name: "MacOS ARM Build",
|
||||
short_name: macosm1,
|
||||
}
|
||||
exclude:
|
||||
# Python 3.13 is needed for Blender 5.1+ and Blender dropped Intel Mac support in 5.0.
|
||||
- pyver: py313
|
||||
config:
|
||||
short_name: macos
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/setup-python@v6 # https://github.com/actions/setup-python
|
||||
@@ -104,7 +109,7 @@ jobs:
|
||||
# Ensure Bonsai and ifcsverchok enable/disable works before uploading to extensions repo.
|
||||
|
||||
# Download Blender.
|
||||
wget -q -O blender.tar.xz https://download.blender.org/release/Blender4.5/blender-4.5.0-linux-x64.tar.xz
|
||||
wget -q -O blender.tar.xz https://download.blender.org/release/Blender5.0/blender-5.0.1-linux-x64.tar.xz
|
||||
tar -xf blender.tar.xz
|
||||
|
||||
# Setup Blender.
|
||||
|
||||
@@ -53,7 +53,6 @@ jobs:
|
||||
python -m pip install --upgrade pip
|
||||
pip install xmlschema xsdata numpy lxml pytest isodate lark networkx tabulate python-dateutil shapely
|
||||
pip install src/bcf --no-deps
|
||||
pip install git+https://github.com/zdhoward/aud
|
||||
pip install pytest-xdist==3.8.0
|
||||
|
||||
- name: Install C++ dependencies
|
||||
@@ -209,17 +208,36 @@ jobs:
|
||||
|
||||
- name: Build standalone examples to test cmake package
|
||||
run: |
|
||||
set -x
|
||||
cd src/examples
|
||||
mkdir build && cd build
|
||||
cmake .. -DCMAKE_BUILD_TYPE=Release \
|
||||
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache
|
||||
cmake --build .
|
||||
./arbitrary_open_profile_def && test -f arbitrary_open_profile_def.ifc
|
||||
./composite_profile_def && test -f composite_profile_def.ifc
|
||||
./csg_primitive && test -f csg_primitive.ifc
|
||||
./ellipse_pies && test -f ellipse_pies.ifc
|
||||
./faces && test -f faces.ifc
|
||||
./ifc_curve_rebar && test -f ifc_curve_rebar.ifc
|
||||
./profiles
|
||||
test -f IfcUShapeProfileDef.ifc
|
||||
test -f IfcTShapeProfileDef.ifc
|
||||
test -f IfcZShapeProfileDef.ifc
|
||||
test -f IfcEllipseProfileDef.ifc
|
||||
test -f IfcIShapeProfileDef.ifc
|
||||
test -f IfcLShapeProfileDef.ifc
|
||||
test -f IfcCShapeProfileDef.ifc
|
||||
test -f IfcCircleProfileDef.ifc
|
||||
test -f IfcRectangleProfileDef.ifc
|
||||
test -f IfcTrapeziumProfileDef.ifc
|
||||
./IfcParseExamples "../IfcParseExamples_test.ifc"
|
||||
./IfcOpenHouse
|
||||
./IfcAdvancedHouse
|
||||
./IfcAlignment
|
||||
./IfcSimplifiedAlignment
|
||||
./IfcOpenHouse && test -f IfcOpenHouse.ifc
|
||||
./IfcAdvancedHouse && test -f IfcAdvancedHouse.ifc
|
||||
./IfcAlignment && test -f IfcAlignment.ifc
|
||||
./IfcSimplifiedAlignment && test -f IfcSimplifiedAlignment.ifc
|
||||
./triangulated_faceset && test -f triangulated_faceset.ifc
|
||||
|
||||
- name: Test ifcopenshell-python
|
||||
run: |
|
||||
|
||||
@@ -22,6 +22,8 @@ venv
|
||||
|
||||
# Visual Studio Code files
|
||||
.vscode
|
||||
!.vscode/launch.json
|
||||
!.vscode/tasks.json
|
||||
.vs
|
||||
|
||||
# PyCharm files
|
||||
@@ -80,6 +82,8 @@ src/bonsai/bonsai/translations.py
|
||||
|
||||
# bonsai test temp files
|
||||
src/bonsai/test/files/temp
|
||||
src/bonsai/test/files/basic.ifc.cache.blend
|
||||
src/bonsai/test/files/basic.ifc.cache.sqlite
|
||||
|
||||
# bonsai data
|
||||
src/bonsai/bonsai/bim/data/build/
|
||||
@@ -111,3 +115,8 @@ dev_environment.bat
|
||||
|
||||
src/ifcopenshell-python/ifcopenshell/express/*.exp
|
||||
src/ifcopenshell-python/ifcopenshell/express/*.exp.cache.dat
|
||||
|
||||
# Claude Code local config (managed via dotfiles repo)
|
||||
CLAUDE.md
|
||||
CLAUDE.local.md
|
||||
.mcp.json
|
||||
|
||||
Vendored
+24
@@ -0,0 +1,24 @@
|
||||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
|
||||
{
|
||||
"name": "Python Debugger: Remote Attach",
|
||||
"type": "debugpy",
|
||||
"request": "attach",
|
||||
"connect": {
|
||||
"host": "localhost",
|
||||
"port": 5678
|
||||
},
|
||||
"pathMappings": [
|
||||
{
|
||||
"localRoot": "${config:bonsai.localRoot}",
|
||||
"remoteRoot": "${config:bonsai.remoteRoot}"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
Vendored
+53
@@ -0,0 +1,53 @@
|
||||
{
|
||||
// See https://go.microsoft.com/fwlink/?LinkId=733558
|
||||
// for the documentation about the tasks.json format
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"label": "Configure bonsai/vscode development environment",
|
||||
"type": "shell",
|
||||
"command": "${input:blenderPath}",
|
||||
"args": [
|
||||
"--background",
|
||||
"--python", "${workspaceFolder}/src/bonsai/scripts/dev_environment_vscode_config.py"
|
||||
],
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"label": "Launch blender with debugpy",
|
||||
"type": "shell",
|
||||
"command": "blender",
|
||||
"options": {
|
||||
"cwd": "${config:bonsai.blenderPath}"
|
||||
},
|
||||
"args": [
|
||||
"--python-expr",
|
||||
"import debugpy; debugpy.listen(5678)"
|
||||
],
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"label": "Install debugpy in Blender",
|
||||
"type": "shell",
|
||||
"command": "blender",
|
||||
"options": {
|
||||
"cwd": "${config:bonsai.blenderPath}"
|
||||
},
|
||||
"args": [
|
||||
"--background",
|
||||
"--python-expr",
|
||||
"import os, sys, subprocess; path=os.path.abspath(sys.executable); subprocess.call([path, '-m', 'ensurepip']); subprocess.call([path, '-m', 'pip', 'install', '--upgrade', 'debugpy'])"
|
||||
],
|
||||
"problemMatcher": []
|
||||
}
|
||||
|
||||
],
|
||||
"inputs": [
|
||||
{
|
||||
"id": "blenderPath",
|
||||
"type": "promptString",
|
||||
"description": "Enter the path to the blender executable",
|
||||
"default": "blender"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -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.
|
||||
@@ -13,7 +13,14 @@ include(CMakeFindDependencyMacro)
|
||||
set(Boost_USE_STATIC_LIBS ON)
|
||||
set(Boost_USE_STATIC_RUNTIME OFF)
|
||||
set(Boost_USE_MULTITHREADED ON)
|
||||
set(Boost_COMPONENTS system program_options regex thread date_time iostreams)
|
||||
set(Boost_COMPONENTS
|
||||
system
|
||||
program_options
|
||||
regex
|
||||
thread
|
||||
date_time
|
||||
iostreams
|
||||
)
|
||||
find_dependency(Boost CONFIG COMPONENTS ${Boost_COMPONENTS})
|
||||
find_dependency(Eigen3 CONFIG)
|
||||
|
||||
@@ -39,7 +46,6 @@ if(IFCOPENSHELL_IFCXML)
|
||||
find_dependency(LibXml2 CONFIG)
|
||||
endif()
|
||||
|
||||
|
||||
if(IFCOPENSHELL_WITH_CGAL)
|
||||
find_dependency(CGAL CONFIG)
|
||||
endif()
|
||||
@@ -48,9 +54,7 @@ if(IFCOPENSHELL_WITH_OPENCASCADE)
|
||||
find_dependency(OpenCASCADE CONFIG)
|
||||
if(OpenCASCADE_VERSION VERSION_LESS "7.7.0")
|
||||
# cmake configs < 7.7.0 were not adding include directories to targets automatically.
|
||||
set_target_properties(TKernel PROPERTIES
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${OpenCASCADE_INCLUDE_DIR}"
|
||||
)
|
||||
set_target_properties(TKernel PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${OpenCASCADE_INCLUDE_DIR}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
||||
@@ -25,19 +25,12 @@ file(READ "@CMAKE_BINARY_DIR@/install_manifest.txt" files)
|
||||
string(REGEX REPLACE "\n" ";" files "${files}")
|
||||
|
||||
foreach(file ${files})
|
||||
message(STATUS "Uninstalling $ENV{DESTDIR}${file}")
|
||||
set(filepath "$ENV{DESTDIR}${file}")
|
||||
message(STATUS "Uninstalling ${filepath}")
|
||||
|
||||
if(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
|
||||
exec_program(
|
||||
"@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\""
|
||||
OUTPUT_VARIABLE rm_out
|
||||
RETURN_VALUE rm_retval
|
||||
)
|
||||
|
||||
if(NOT "${rm_retval}" STREQUAL 0)
|
||||
message(FATAL_ERROR "Problem when removing $ENV{DESTDIR}${file}")
|
||||
endif()
|
||||
else(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
|
||||
message(STATUS "File $ENV{DESTDIR}${file} does not exist.")
|
||||
if(IS_SYMLINK "${filepath}" OR EXISTS "${filepath}")
|
||||
file(REMOVE "${filepath}")
|
||||
else(NOT EXISTS "${filepath}")
|
||||
message(STATUS "File ${filepath} does not exist.")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
+19
-24
@@ -1,14 +1,10 @@
|
||||
#Look for an executable called sphinx-build
|
||||
find_program(SPHINX_EXECUTABLE
|
||||
NAMES sphinx-build
|
||||
DOC "Path to sphinx-build executable")
|
||||
find_program(SPHINX_EXECUTABLE NAMES sphinx-build DOC "Path to sphinx-build executable")
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
|
||||
#Handle standard arguments to find_package like REQUIRED and QUIET
|
||||
find_package_handle_standard_args(Sphinx
|
||||
"Failed to find sphinx-build executable"
|
||||
SPHINX_EXECUTABLE)
|
||||
find_package_handle_standard_args(Sphinx "Failed to find sphinx-build executable" SPHINX_EXECUTABLE)
|
||||
|
||||
find_package(Doxygen REQUIRED)
|
||||
#find_package(Sphinx REQUIRED)
|
||||
@@ -16,25 +12,24 @@ find_package(Doxygen REQUIRED)
|
||||
set(SPHINX_SOURCE ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
set(SPHINX_BUILD ${CMAKE_CURRENT_BINARY_DIR}/docs/sphinx)
|
||||
|
||||
MESSAGE(STATUS "SPHINX BUILD ${CMAKE_CURRENT_BINARY_DIR}")
|
||||
message(STATUS "SPHINX BUILD ${CMAKE_CURRENT_BINARY_DIR}")
|
||||
|
||||
file(MAKE_DIRECTORY ./output/doxygen)
|
||||
|
||||
if (DOXYGEN_FOUND)
|
||||
if(DOXYGEN_FOUND)
|
||||
add_custom_target(
|
||||
Sphinx
|
||||
ALL
|
||||
COMMAND ${SPHINX_EXECUTABLE} -v -T -b html ${SPHINX_SOURCE} ${CMAKE_CURRENT_SOURCE_DIR}/output
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/output
|
||||
COMMENT "Generating documentation with Sphinx"
|
||||
)
|
||||
|
||||
add_custom_target(Sphinx ALL
|
||||
COMMAND
|
||||
${SPHINX_EXECUTABLE} -v -T -b html
|
||||
${SPHINX_SOURCE} ${CMAKE_CURRENT_SOURCE_DIR}/output
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/output
|
||||
COMMENT "Generating documentation with Sphinx")
|
||||
|
||||
# add_custom_target(ifcopenshell_python_docs ALL
|
||||
# COMMAND make html
|
||||
# WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/../src/ifcblenderexport/docs
|
||||
# OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/../src/ifcblenderexport/docs
|
||||
# COMMENT "Generating documentation with Sphinx")
|
||||
|
||||
else (DOXYGEN_FOUND)
|
||||
message("Doxygen need to be installed to generate the doxygen documentation")
|
||||
endif (DOXYGEN_FOUND)
|
||||
# add_custom_target(ifcopenshell_python_docs ALL
|
||||
# COMMAND make html
|
||||
# WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/../src/ifcblenderexport/docs
|
||||
# OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/../src/ifcblenderexport/docs
|
||||
# COMMENT "Generating documentation with Sphinx")
|
||||
else(DOXYGEN_FOUND)
|
||||
message("Doxygen need to be installed to generate the doxygen documentation")
|
||||
endif(DOXYGEN_FOUND)
|
||||
|
||||
@@ -1177,6 +1177,8 @@ if "cgal" in targets:
|
||||
# Disable assembly, otherwise `emcc -c conftest.s` will crash due to assembly mismatch.
|
||||
gmp_args.extend(("--disable-assembly", "--enable-cxx"))
|
||||
mpfr_args.extend(("--host", "none"))
|
||||
elif "x86" in arch:
|
||||
gmp_args.append("--enable-fat") # See issues #7458 #7556
|
||||
|
||||
OLD_CC = None
|
||||
if MAC_CROSS_COMPILE_INTEL:
|
||||
|
||||
+4
-4
@@ -2,10 +2,10 @@
|
||||
name = "IfcOpenShell"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"black==25.12",
|
||||
"ruff==0.14.10",
|
||||
"black==26.1.0",
|
||||
"ruff==0.15.1",
|
||||
"poethepoet",
|
||||
"gersemi==0.24",
|
||||
"gersemi==0.25.4",
|
||||
]
|
||||
|
||||
[tool.black]
|
||||
@@ -82,4 +82,4 @@ black = "black ."
|
||||
|
||||
format.sequence = ["black", "ruff-main", "ruff-old"]
|
||||
|
||||
cmake-format = "gersemi cmake src --in-place"
|
||||
cmake-format = "gersemi . --in-place"
|
||||
|
||||
@@ -2,6 +2,8 @@ import tempfile
|
||||
from pathlib import Path
|
||||
from typing import Optional, Union
|
||||
|
||||
from typing_extensions import assert_never
|
||||
|
||||
import bcf.agnostic.model as mdl
|
||||
import bcf.v2.bcfxml
|
||||
import bcf.v2.model
|
||||
@@ -9,7 +11,6 @@ import bcf.v2.topic
|
||||
import bcf.v3.bcfxml
|
||||
import bcf.v3.model
|
||||
import bcf.v3.topic
|
||||
from typing_extensions import assert_never
|
||||
|
||||
TopicHandler = Union[bcf.v2.topic.TopicHandler, bcf.v3.topic.TopicHandler]
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
# Currently extensions support for v2 is only read-only.
|
||||
|
||||
|
||||
from dataclasses import dataclass, field, fields
|
||||
from dataclasses import dataclass, field
|
||||
from typing import Optional
|
||||
|
||||
|
||||
|
||||
@@ -3,11 +3,10 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import datetime
|
||||
import tempfile
|
||||
import uuid
|
||||
import zipfile
|
||||
from pathlib import Path
|
||||
from typing import Any, NoReturn, Optional, Union
|
||||
from typing import Any, NoReturn, Optional
|
||||
|
||||
import numpy as np
|
||||
from ifcopenshell import entity_instance
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import uuid
|
||||
import zipfile
|
||||
from collections.abc import Iterable
|
||||
from typing import Any, Literal, Optional, Union
|
||||
from typing import Literal, Optional, Union
|
||||
|
||||
import ifcopenshell.util.placement
|
||||
import ifcopenshell.util.unit
|
||||
|
||||
@@ -24,7 +24,6 @@ import time
|
||||
import urllib.parse
|
||||
import uuid
|
||||
import webbrowser
|
||||
from re import A
|
||||
from typing import Any, Optional
|
||||
|
||||
import requests
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"""BCF XML V3 Documents handler."""
|
||||
|
||||
import zipfile
|
||||
from typing import Any, Optional
|
||||
from typing import Optional
|
||||
|
||||
import bcf.v3.model as mdl
|
||||
from bcf.inmemory_zipfile import ZipFileInterface
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import uuid
|
||||
import zipfile
|
||||
from collections.abc import Iterable
|
||||
from typing import Any, Literal, Optional, Union
|
||||
from typing import Literal, Optional, Union
|
||||
|
||||
import ifcopenshell.util.placement
|
||||
import ifcopenshell.util.unit
|
||||
|
||||
@@ -140,3 +140,9 @@ max-attributes = 10
|
||||
[tool.pylint.format]
|
||||
expected-line-ending-format = "LF"
|
||||
max-line-length = 120
|
||||
|
||||
[tool.ruff]
|
||||
extend = "../../pyproject.toml"
|
||||
lint.select = [
|
||||
"F401", # unused imports
|
||||
]
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import pytest
|
||||
|
||||
from bcf.xml_parser import XmlParserSerializer
|
||||
|
||||
|
||||
|
||||
@@ -4,8 +4,9 @@ import uuid
|
||||
from pathlib import Path
|
||||
from tempfile import TemporaryDirectory
|
||||
|
||||
import bcf.v2.model as mdl
|
||||
import pytest
|
||||
|
||||
import bcf.v2.model as mdl
|
||||
from bcf.v2.bcfxml import BcfXml
|
||||
from bcf.v2.topic import TopicHandler
|
||||
from bcf.v2.visinfo import (
|
||||
|
||||
@@ -3,10 +3,11 @@ import os
|
||||
import zipfile
|
||||
from pathlib import Path
|
||||
|
||||
from xsdata.models.datatype import XmlDateTime
|
||||
|
||||
import bcf.v2.model as mdl
|
||||
from bcf.v2.bcfxml import BcfXml
|
||||
from bcf.v2.topic import TopicHandler
|
||||
from xsdata.models.datatype import XmlDateTime
|
||||
|
||||
|
||||
def test_maximum_information() -> None:
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
from bcf.v2.bcfxml import BcfXml
|
||||
|
||||
|
||||
|
||||
@@ -4,8 +4,9 @@ import uuid
|
||||
from pathlib import Path
|
||||
from tempfile import TemporaryDirectory
|
||||
|
||||
import bcf.v3.model as mdl
|
||||
import pytest
|
||||
|
||||
import bcf.v3.model as mdl
|
||||
from bcf.v3.bcfxml import BcfXml
|
||||
from bcf.v3.topic import TopicHandler
|
||||
from bcf.v3.visinfo import (
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
import json
|
||||
import os
|
||||
import zipfile
|
||||
from pathlib import Path
|
||||
|
||||
from xsdata.models.datatype import XmlDateTime
|
||||
|
||||
import bcf.v3.model as mdl
|
||||
from bcf.v3.bcfxml import BcfXml
|
||||
from bcf.v3.topic import TopicHandler
|
||||
from xsdata.models.datatype import XmlDateTime
|
||||
|
||||
|
||||
def test_doc_ref_internal() -> None:
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
from bcf.v3.bcfxml import BcfXml
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
# Build Bonsai .zip.
|
||||
# Usage:
|
||||
# # While in `bonsai` folder.
|
||||
# docker build -t bonsai-dist .
|
||||
# # Output zip file will be in `dist` folder.
|
||||
# # See possible values for variables in `Makefile`'s `dist` target description.
|
||||
# docker run --rm -v "$PWD/../../:/work" -w /work -e PLATFORM=win -e PYVERSION=py313 bonsai-dist
|
||||
|
||||
FROM ubuntu:24.04
|
||||
RUN apt-get update
|
||||
RUN apt-get install -y make git wget unzip zip
|
||||
|
||||
# Python
|
||||
RUN apt-get install -y software-properties-common
|
||||
RUN add-apt-repository ppa:deadsnakes/ppa
|
||||
RUN apt-get update
|
||||
RUN apt-get install -y python3.11 python3.11-venv
|
||||
|
||||
RUN apt-get install -y npm
|
||||
|
||||
WORKDIR /work
|
||||
CMD cd src/bonsai && make dist PLATFORM=$PLATFORM PYVERSION=$PYVERSION
|
||||
+41
-21
@@ -48,18 +48,33 @@ VERSION_PATCH:=$(shell cat '../../VERSION' | cut -d '.' -f 3)
|
||||
VERSION_DATE:=$(shell date '+%y%m%d')
|
||||
LAST_COMMIT_HASH:=$(shell git rev-parse HEAD)
|
||||
LAST_COMMIT_DATE:=$(shell git show -s --format=%cI)
|
||||
PYVERSION:=py310
|
||||
PYPI_IMP:=cp
|
||||
|
||||
ifeq ($(PYVERSION), py311)
|
||||
PYLIBDIR:=python3.11
|
||||
PYNUMBER:=311
|
||||
PYPI_VERSION:=3.11
|
||||
ifdef PYVERSION
|
||||
SUPPORTED_PYVERSIONS := py311 py312 py313
|
||||
|
||||
ifeq ($(filter $(PYVERSION),$(SUPPORTED_PYVERSIONS)),)
|
||||
$(error Unsupported PYVERSION=$(PYVERSION). Must be one of $(SUPPORTED_PYVERSIONS))
|
||||
endif
|
||||
|
||||
PYMINOR:=$(subst py3,,$(PYVERSION))
|
||||
PYLIBDIR:=python3.$(PYMINOR)
|
||||
PYNUMBER:=3$(PYMINOR)
|
||||
PYPI_VERSION:=3.$(PYMINOR)
|
||||
endif # def PYVERSION
|
||||
|
||||
|
||||
ifdef PLATFORM
|
||||
SUPPORTED_PLATFORMS := linux macos macosm1 win
|
||||
|
||||
ifeq ($(filter $(PLATFORM),$(SUPPORTED_PLATFORMS)),)
|
||||
$(error Unsupported PLATFORM=$(PLATFORM). Must be one of $(SUPPORTED_PLATFORMS))
|
||||
endif
|
||||
|
||||
ifeq ($(PLATFORM),macos)
|
||||
ifeq ($(PYVERSION),py313)
|
||||
$(error Blender 5.1 with Python 3.13 doesn't support intel macOS.)
|
||||
endif
|
||||
ifeq ($(PYVERSION), py312)
|
||||
PYLIBDIR:=python3.12
|
||||
PYNUMBER:=312
|
||||
PYPI_VERSION:=3.12
|
||||
endif
|
||||
|
||||
ifeq ($(PLATFORM), linux)
|
||||
@@ -86,6 +101,8 @@ PYPI_PLATFORM:=--platform win_amd64
|
||||
BLENDER_PLATFORM:=windows-x64
|
||||
endif
|
||||
|
||||
endif # def PLATFORM
|
||||
|
||||
# Current build commit hash.
|
||||
OLD:=e8eb5e4
|
||||
.PHONY: bump
|
||||
@@ -99,7 +116,10 @@ endif
|
||||
.PHONY: dist
|
||||
dist:
|
||||
ifndef PLATFORM
|
||||
$(error PLATFORM is not set)
|
||||
$(error PLATFORM is not set. Example values: $(SUPPORTED_PLATFORMS).)
|
||||
endif
|
||||
ifndef PYVERSION
|
||||
$(error PYVERSION is not set. Example values: $(SUPPORTED_PYVERSIONS). )
|
||||
endif
|
||||
rm -rf build
|
||||
mkdir -p build
|
||||
@@ -125,9 +145,6 @@ endif
|
||||
cd ../ifc5d && make dist && mv dist/*.whl ../bonsai/build/wheels/
|
||||
cd ../ifccityjson && make dist && mv dist/*.whl ../bonsai/build/wheels/
|
||||
cd build && . env/$(VENV_ACTIVATE) && $(PIP) download GitPython --dest=./wheels
|
||||
# Provides audio playback for costing
|
||||
# This is a REALLY IMPORTANT feature
|
||||
cd build && . env/$(VENV_ACTIVATE) && $(PIP) wheel git+https://github.com/zdhoward/aud --wheel-dir=./wheels
|
||||
# IfcOpenShell dependency - support for new typing features
|
||||
cd build && . env/$(VENV_ACTIVATE) && $(PIP) download typing_extensions --dest=./wheels
|
||||
# Required by IfcCSV
|
||||
@@ -189,7 +206,7 @@ endif
|
||||
cd build && . env/$(VENV_ACTIVATE) && $(PIP) download tzfpy $(PYPI_PLATFORM) --python-version $(PYPI_VERSION) --implementation $(PYPI_IMP) --only-binary=:all: --dest=./wheels
|
||||
# pyradiance is using different platform versions than defaults in our makefile.
|
||||
ifeq ($(PLATFORM), linux)
|
||||
cd build && . env/$(VENV_ACTIVATE) && $(PIP) download pyradiance --platform manylinux_2_35_x86_64 --python-version $(PYPI_VERSION) --implementation $(PYPI_IMP) --only-binary=:all: --dest=./wheels
|
||||
cd build && . env/$(VENV_ACTIVATE) && $(PIP) download pyradiance --platform manylinux_2_28_x86_64 --python-version $(PYPI_VERSION) --implementation $(PYPI_IMP) --only-binary=:all: --dest=./wheels
|
||||
else ifeq ($(PLATFORM), macos)
|
||||
cd build && . env/$(VENV_ACTIVATE) && $(PIP) download pyradiance --platform macosx_10_13_x86_64 --python-version $(PYPI_VERSION) --implementation $(PYPI_IMP) --only-binary=:all: --dest=./wheels
|
||||
else
|
||||
@@ -267,6 +284,11 @@ else
|
||||
$(SED) 's/version = "0.0.0"/version = "$(VERSION)-alpha$(VERSION_DATE)"/' build/pyproject.toml
|
||||
endif
|
||||
|
||||
# Blender 5.1+ requires Python 3.13.
|
||||
ifeq ($(PYVERSION), py313)
|
||||
$(SED) 's/blender_version_min = "4\.2\.0"/blender_version_min = "5.1.0"/' build/bonsai/blender_manifest.toml
|
||||
endif
|
||||
|
||||
$(SED) "s/os-arch/$(BLENDER_PLATFORM)/" build/bonsai/blender_manifest.toml
|
||||
|
||||
# Provides bonsai Add-on functionality
|
||||
@@ -288,12 +310,6 @@ endif
|
||||
fi
|
||||
mv build/wheels/*.whl build/bonsai/wheels/
|
||||
|
||||
# Temporary workaround for Blender not handling non-3.11 wheels #5743.
|
||||
# Use '-n' as on macos x86-64 doesn't have a binary wheel and it autoincludes 'cp311'.
|
||||
prev_whl_name=$$(find build/bonsai/wheels/tzfpy-*.whl); \
|
||||
whl_name=$$(echo $$prev_whl_name | sed "s/-cp39-/-cp$(PYNUMBER)-/"); \
|
||||
mv --update=none "$$prev_whl_name" "$$whl_name";
|
||||
|
||||
ifneq ($(PLATFORM), linux)
|
||||
# Safeguard: in case one of `pip download` will break,
|
||||
# it will produce a linux wheel for non-linux build (our github action machine is using linux).
|
||||
@@ -336,7 +352,11 @@ test:
|
||||
|
||||
.PHONY: test-core
|
||||
test-core:
|
||||
ifndef MODULE
|
||||
pytest -p no:pytest-blender test/core
|
||||
else
|
||||
pytest -p no:pytest-blender test/core/test_${MODULE}.py
|
||||
endif
|
||||
|
||||
.PHONY: test-bim
|
||||
test-bim:
|
||||
@@ -351,7 +371,7 @@ test-tool:
|
||||
ifndef MODULE
|
||||
pytest test/tool
|
||||
else
|
||||
pytest test/tool/test_$(MODULE).py
|
||||
pytest test/tool/test_$(MODULE).py --maxfail=1
|
||||
endif
|
||||
|
||||
# Reregistering test is not added to the standard test suite because during unregister
|
||||
|
||||
@@ -32,17 +32,16 @@ if IN_BLENDER:
|
||||
# and then as a bonsai-package.
|
||||
IN_PACKAGE = __package__ == "bonsai"
|
||||
|
||||
import re
|
||||
import platform
|
||||
import traceback
|
||||
import webbrowser
|
||||
import uuid
|
||||
import re
|
||||
import shutil
|
||||
import traceback
|
||||
import uuid
|
||||
import webbrowser
|
||||
from collections import deque
|
||||
from pathlib import Path
|
||||
from typing import Union, Any
|
||||
from collections.abc import Generator
|
||||
|
||||
from pathlib import Path
|
||||
from typing import Any, Union
|
||||
|
||||
last_commit_hash = "8888888"
|
||||
last_commit_date = "9999999"
|
||||
|
||||
@@ -16,14 +16,16 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import importlib
|
||||
import os
|
||||
from collections.abc import Callable
|
||||
from typing import Union
|
||||
|
||||
import bpy
|
||||
import bpy.utils.previews
|
||||
import importlib
|
||||
from bpy_extras.io_utils import ImportHelper, ExportHelper
|
||||
from . import handler, ui, prop, operator
|
||||
from typing import Union
|
||||
from collections.abc import Callable
|
||||
from bpy_extras.io_utils import ExportHelper, ImportHelper
|
||||
|
||||
from . import handler, operator, prop, ui
|
||||
|
||||
try:
|
||||
from bonsai.translations import translations_dict
|
||||
@@ -130,12 +132,7 @@ classes = [
|
||||
prop.StrProperty,
|
||||
operator.BIM_OT_enum_property_search, # /!\ Register AFTER prop.StrProperty
|
||||
operator.BIM_OT_attribute_search_values,
|
||||
operator.BIM_UL_tab_panels,
|
||||
operator.BIM_OT_toggle_panel_visibility,
|
||||
operator.BIM_OT_bookmark_panel,
|
||||
operator.BIM_OT_manage_tab_panels,
|
||||
operator.BIM_OT_manage_tab_visibility,
|
||||
operator.BIM_OT_toggle_tab_visibility,
|
||||
operator.BIM_OT_reset_ui_layout,
|
||||
prop.ObjProperty,
|
||||
prop.MultipleFileSelect,
|
||||
@@ -144,7 +141,7 @@ classes = [
|
||||
prop.BIMAreaProperties,
|
||||
prop.BIMTabProperties,
|
||||
prop.BIMTabVisibility, # Must be registered before BIMProperties
|
||||
prop.BIMPanelProperties, # Must be registered before BIMProperties
|
||||
prop.BIMPanelVisibility, # Must be registered before BIMProperties
|
||||
prop.BIMProperties,
|
||||
prop.IfcParameter,
|
||||
prop.PsetQto,
|
||||
@@ -157,6 +154,8 @@ classes = [
|
||||
prop.BIMSnapGroups,
|
||||
ui.BIM_UL_clipping_plane,
|
||||
ui.BIM_UL_generic,
|
||||
ui.BIM_UL_tab_visibilities,
|
||||
ui.BIM_UL_panel_visibilities,
|
||||
ui.DocPreferences,
|
||||
ui.GizmoPreferencesDoor, # Register before GizmoPreferences
|
||||
ui.GizmoPreferencesWindow, # Register before GizmoPreferences
|
||||
@@ -185,6 +184,8 @@ classes = [
|
||||
ui.BIM_PT_tab_materials,
|
||||
ui.BIM_PT_tab_styles,
|
||||
ui.BIM_PT_tab_profiles,
|
||||
# Civil infrastructure
|
||||
ui.BIM_PT_tab_horizontal_alignment,
|
||||
# Drawings and documents
|
||||
ui.BIM_PT_tab_sheets,
|
||||
ui.BIM_PT_tab_drawings,
|
||||
@@ -318,10 +319,6 @@ def register():
|
||||
# RestrictedContext doesn't allow accessing scene attribute, postpone it for a bit.
|
||||
bpy.app.timers.register(tool.Blender.setup_user_data_dir, first_interval=0.1)
|
||||
|
||||
bpy.types.Scene.active_tab_name = bpy.props.StringProperty()
|
||||
bpy.types.Scene.tab_panels = bpy.props.CollectionProperty(type=bpy.types.PropertyGroup)
|
||||
bpy.types.Scene.active_tab_panel_index = bpy.props.IntProperty()
|
||||
|
||||
|
||||
def unregister():
|
||||
global icons
|
||||
@@ -363,7 +360,3 @@ def unregister():
|
||||
tool.Blender.remove_scene_panel_override(panel)
|
||||
|
||||
bpy.app.translations.unregister("bonsai")
|
||||
|
||||
del bpy.types.Scene.active_tab_name
|
||||
del bpy.types.Scene.tab_panels
|
||||
del bpy.types.Scene.active_tab_panel_index
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import sys
|
||||
import os
|
||||
|
||||
import sys
|
||||
|
||||
bonsai_lib_path = os.environ.get("BONSAI_LIB_PATH")
|
||||
bonsai_version = os.environ.get("BONSAI_VERSION")
|
||||
@@ -9,13 +8,14 @@ if bonsai_lib_path:
|
||||
sys.path.insert(0, bonsai_lib_path)
|
||||
|
||||
import argparse
|
||||
from aiohttp import web
|
||||
import socketio
|
||||
import pystache
|
||||
import json
|
||||
import base64
|
||||
import json
|
||||
import xml.etree.ElementTree as ET
|
||||
|
||||
import pystache
|
||||
import socketio
|
||||
from aiohttp import web
|
||||
|
||||
sio_port = 8080 # default port
|
||||
|
||||
sio = socketio.AsyncServer(cors_allowed_origins="*", async_mode="aiohttp", max_http_buffer_size=10000000)
|
||||
|
||||
@@ -17,27 +17,30 @@
|
||||
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from __future__ import annotations
|
||||
import os
|
||||
import bpy
|
||||
import json
|
||||
|
||||
import datetime
|
||||
import zipfile
|
||||
import json
|
||||
import os
|
||||
import tempfile
|
||||
import zipfile
|
||||
from logging import Logger
|
||||
from math import radians
|
||||
from typing import Union
|
||||
|
||||
import bpy
|
||||
import ifcopenshell
|
||||
import ifcopenshell.api
|
||||
import ifcopenshell.util.element
|
||||
import ifcopenshell.util.placement
|
||||
import ifcopenshell.util.unit
|
||||
import bonsai.tool as tool
|
||||
import bonsai.core.geometry
|
||||
from mathutils import Vector
|
||||
|
||||
import bonsai.core.aggregate
|
||||
import bonsai.core.geometry
|
||||
import bonsai.core.spatial
|
||||
import bonsai.core.style
|
||||
import bonsai.tool as tool
|
||||
from bonsai.bim.ifc import IfcStore
|
||||
from mathutils import Vector
|
||||
from typing import Union
|
||||
from logging import Logger
|
||||
from math import radians
|
||||
|
||||
|
||||
class IfcExporter:
|
||||
@@ -49,7 +52,6 @@ class IfcExporter:
|
||||
self.set_header()
|
||||
IfcStore.update_cache()
|
||||
self.sync_all_objects()
|
||||
tool.Project.save_linked_models_to_ifc()
|
||||
extension = self.ifc_export_settings.output_file.split(".")[-1].lower()
|
||||
if extension == "ifczip":
|
||||
with tempfile.TemporaryDirectory() as unzipped_path:
|
||||
|
||||
@@ -17,26 +17,31 @@
|
||||
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import os
|
||||
import weakref
|
||||
from collections.abc import Callable
|
||||
from math import cos
|
||||
from typing import Union
|
||||
|
||||
import bpy
|
||||
import ifcopenshell.api.owner.settings
|
||||
import ifcopenshell.util.element
|
||||
import ifcopenshell.util.representation
|
||||
import ifcopenshell.util.unit
|
||||
import ifcopenshell.api.owner.settings
|
||||
from bpy.app.handlers import persistent
|
||||
from mathutils import Vector
|
||||
|
||||
import bonsai.bim
|
||||
import bonsai.tool as tool
|
||||
import weakref
|
||||
from bpy.app.handlers import persistent
|
||||
from bonsai.bim.ifc import IfcStore
|
||||
from bonsai.bim.module.model.data import AuthoringData
|
||||
from bonsai.bim.module.aggregate.decorator import AggregateDecorator
|
||||
from bonsai.bim.module.georeference.decorator import GeoreferenceDecorator
|
||||
from bonsai.bim.module.model.decorator import WallAxisDecorator, SlabDirectionDecorator, BoundingBoxDecorator
|
||||
from bonsai.bim.module.model.data import AuthoringData
|
||||
from bonsai.bim.module.model.decorator import (
|
||||
BoundingBoxDecorator,
|
||||
SlabDirectionDecorator,
|
||||
WallAxisDecorator,
|
||||
)
|
||||
from bonsai.bim.module.nest.decorator import NestDecorator
|
||||
from mathutils import Vector
|
||||
from math import cos
|
||||
from typing import Union
|
||||
from collections.abc import Callable
|
||||
|
||||
|
||||
cwd = os.path.dirname(os.path.realpath(__file__))
|
||||
global_subscription_owner = object()
|
||||
@@ -202,8 +207,8 @@ def refresh_ui_data():
|
||||
Note that calling non-ifc-operators by itself doesn't refresh the UI data
|
||||
and it need to be refreshed manually if needed.
|
||||
"""
|
||||
from bonsai.bim import modules
|
||||
import bonsai.bim.ui
|
||||
from bonsai.bim import modules
|
||||
|
||||
bonsai.bim.ui.refresh()
|
||||
|
||||
|
||||
+33
-179
@@ -17,24 +17,31 @@
|
||||
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import importlib
|
||||
import bpy
|
||||
import json
|
||||
from collections.abc import Callable, Iterable, Sequence
|
||||
from types import EllipsisType
|
||||
from typing import TYPE_CHECKING, Any, Optional, Union
|
||||
|
||||
import bpy
|
||||
import ifcopenshell
|
||||
import ifcopenshell.ifcopenshell_wrapper as W
|
||||
import ifcopenshell.util.attribute
|
||||
import ifcopenshell.util.element
|
||||
import ifcopenshell.util.unit
|
||||
from ifcopenshell.util.doc import get_attribute_doc, get_predefined_type_doc, get_property_doc
|
||||
from ifcopenshell.util.doc import (
|
||||
get_attribute_doc,
|
||||
get_predefined_type_doc,
|
||||
get_property_doc,
|
||||
)
|
||||
|
||||
import bonsai.tool as tool
|
||||
from types import EllipsisType
|
||||
from typing import Optional, Any, Union, TYPE_CHECKING
|
||||
from collections.abc import Callable, Iterable, Sequence
|
||||
|
||||
if TYPE_CHECKING:
|
||||
import bonsai.bim.prop
|
||||
from bonsai.bim.prop import Attribute
|
||||
from bonsai.bim.module.search.prop import BIMFilterGroup
|
||||
from bonsai.bim.prop import Attribute
|
||||
|
||||
# ImportCallback return values:
|
||||
# - None - property should be imported by default workflow
|
||||
@@ -511,14 +518,15 @@ def draw_filter(
|
||||
row.operator("bim.edit_element_filter", icon="CHECKMARK", text="").filter_mode = "EXCLUDE"
|
||||
row.operator("bim.enable_editing_element_filter", icon="CANCEL", text="").filter_mode = "NONE"
|
||||
row = layout.row(align=True)
|
||||
if not tool.Blender.get_addon_preferences().chain_filter_with_set_operations:
|
||||
preferences = tool.Blender.get_addon_preferences()
|
||||
if not preferences.chain_filter_with_set_operations:
|
||||
row.operator("bim.add_filter_group", text="Add Search Group", icon="ADD").module = module
|
||||
else:
|
||||
if not filter_groups or not any(fg.filters for fg in filter_groups):
|
||||
op = row.operator("bim.add_filter", text="Add Filter", icon="ADD")
|
||||
op.type = "entity"
|
||||
op.index = 0
|
||||
op.module = module
|
||||
row.prop(sprops, "facet", text="")
|
||||
op = row.operator("bim.add_filter", text="Add Filter", icon="ADD")
|
||||
op.type = sprops.facet
|
||||
op.index = 0
|
||||
op.module = module
|
||||
op = row.operator("bim.edit_filter_query", text="", icon="FILTER")
|
||||
if "module" in op.bl_rna.properties:
|
||||
op.module = module
|
||||
@@ -526,26 +534,23 @@ def draw_filter(
|
||||
for i, filter_group in enumerate(filter_groups):
|
||||
box = layout.box()
|
||||
|
||||
row = box.row(align=True)
|
||||
row.prop(sprops, "facet", text="")
|
||||
op = row.operator("bim.add_filter", text="Add Filter", icon="ADD")
|
||||
op.type = sprops.facet
|
||||
op.index = i
|
||||
op.module = module
|
||||
op = row.operator("bim.remove_filter_group", text="", icon="X")
|
||||
op.index = i
|
||||
op.module = module
|
||||
preferences = tool.Blender.get_addon_preferences()
|
||||
if not preferences.chain_filter_with_set_operations:
|
||||
row = box.row(align=True)
|
||||
row.prop(sprops, "facet", text="")
|
||||
op = row.operator("bim.add_filter", text="Add Filter", icon="ADD")
|
||||
op.type = sprops.facet
|
||||
op.index = i
|
||||
op.module = module
|
||||
op = row.operator("bim.remove_filter_group", text="", icon="X")
|
||||
op.index = i
|
||||
op.module = module
|
||||
|
||||
for j, ifc_filter in enumerate(filter_group.filters):
|
||||
if ifc_filter.type == "entity":
|
||||
row = box.row(align=True)
|
||||
preferences = tool.Blender.get_addon_preferences()
|
||||
if preferences.chain_filter_with_set_operations:
|
||||
show_mode_toggle = j > 0
|
||||
else:
|
||||
show_mode_toggle = (
|
||||
preferences.default_filter_with_set_operations_for_globalid_and_class and j > 0
|
||||
) # PR 7315 mode
|
||||
show_mode_toggle = preferences.chain_filter_with_set_operations and j > 0
|
||||
if show_mode_toggle:
|
||||
mode_icons = {"ADD": "ADD", "SUBTRACT": "REMOVE", "FILTER": "FILTER"}
|
||||
op = row.operator(
|
||||
@@ -761,12 +766,7 @@ def draw_filter(
|
||||
elif ifc_filter.type == "instance":
|
||||
row = box.row(align=True)
|
||||
preferences = tool.Blender.get_addon_preferences()
|
||||
if preferences.chain_filter_with_set_operations:
|
||||
show_mode_toggle = j > 0
|
||||
else:
|
||||
show_mode_toggle = (
|
||||
preferences.default_filter_with_set_operations_for_globalid_and_class and j > 0
|
||||
) # PR 7315 mode
|
||||
show_mode_toggle = preferences.chain_filter_with_set_operations and j > 0
|
||||
if show_mode_toggle:
|
||||
mode_icons = {"ADD": "ADD", "SUBTRACT": "REMOVE", "FILTER": "FILTER"}
|
||||
op = row.operator(
|
||||
@@ -792,149 +792,3 @@ def draw_filter(
|
||||
op.group_index = i
|
||||
op.index = j
|
||||
op.module = module
|
||||
|
||||
|
||||
# ============================================================================
|
||||
# UI Panel Visibility Helpers
|
||||
# ============================================================================
|
||||
|
||||
|
||||
def get_tab_names():
|
||||
from bonsai.bim.prop import get_tab
|
||||
|
||||
enum_items = get_tab(None, None)
|
||||
# Exclude None separators and the BLENDER tab (not part of BIM tab system)
|
||||
return [item[0] for item in enum_items if item is not None and item[0] != "BLENDER"]
|
||||
|
||||
|
||||
def get_panel_tab_name(panel_class):
|
||||
if hasattr(panel_class, "bim_tab_name"):
|
||||
return panel_class.bim_tab_name
|
||||
return "PROJECT" # Default fallback
|
||||
|
||||
|
||||
def should_show_panel(panel_id, panel_tab_name, context):
|
||||
if tool.Blender.is_tab(context, "BOOKMARK"):
|
||||
return is_panel_bookmarked(panel_id) and get_panel_visibility(panel_id, "BOOKMARK")
|
||||
|
||||
if tool.Blender.is_tab(context, panel_tab_name):
|
||||
return get_tab_visibility(panel_tab_name) and get_panel_visibility(panel_id, panel_tab_name)
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def get_tab_visibility(tab_name):
|
||||
bim_props = tool.Blender.get_bim_props()
|
||||
tab_vis = bim_props.tab_visibilities.get(tab_name)
|
||||
return tab_vis.is_visible if tab_vis else True
|
||||
|
||||
|
||||
def set_tab_visibility(tab_name, visible):
|
||||
bim_props = tool.Blender.get_bim_props()
|
||||
tab_vis = bim_props.tab_visibilities.get(tab_name)
|
||||
if tab_vis:
|
||||
tab_vis.is_visible = visible
|
||||
else:
|
||||
new_tab = bim_props.tab_visibilities.add()
|
||||
new_tab.name = tab_name
|
||||
new_tab.is_visible = visible
|
||||
|
||||
|
||||
def get_panel_visibility(panel_id, current_tab=None):
|
||||
panel_config = get_panel_config(panel_id)
|
||||
if panel_config:
|
||||
if current_tab == "BOOKMARK":
|
||||
return panel_config.is_visible_in_bookmarks
|
||||
else:
|
||||
return panel_config.is_visible_in_tab
|
||||
return True
|
||||
|
||||
|
||||
def is_panel_bookmarked(panel_id):
|
||||
panel_config = get_panel_config(panel_id)
|
||||
if panel_config:
|
||||
return panel_config.is_bookmarked
|
||||
return False
|
||||
|
||||
|
||||
def get_panel_config(panel_id, create_if_missing=False):
|
||||
try:
|
||||
bim_props = tool.Blender.get_bim_props()
|
||||
except (AttributeError, AssertionError):
|
||||
return None
|
||||
|
||||
for prop in bim_props.panel_properties:
|
||||
if prop.name == panel_id:
|
||||
return prop
|
||||
|
||||
if create_if_missing:
|
||||
try:
|
||||
prop = bim_props.panel_properties.add()
|
||||
prop.name = panel_id
|
||||
prop.is_visible_in_tab = True
|
||||
prop.is_visible_in_bookmarks = True
|
||||
prop.is_bookmarked = False
|
||||
return prop
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def get_all_tab_panels(force_refresh=False):
|
||||
panels = {tab_name: [] for tab_name in get_tab_names() if tab_name != "BOOKMARK"}
|
||||
panels["BOOKMARK"] = []
|
||||
|
||||
bim_props = tool.Blender.get_bim_props()
|
||||
for prop in bim_props.panel_properties:
|
||||
panel_class = getattr(bpy.types, prop.name, None)
|
||||
if panel_class:
|
||||
tab_name = get_panel_tab_name(panel_class)
|
||||
if tab_name and tab_name != "BOOKMARK":
|
||||
bl_label = getattr(panel_class, "bl_label", prop.name)
|
||||
panels[tab_name].append({"bl_idname": prop.name, "bl_label": bl_label})
|
||||
|
||||
if prop.is_bookmarked:
|
||||
panel_class = getattr(bpy.types, prop.name, None)
|
||||
if panel_class:
|
||||
bl_label = getattr(panel_class, "bl_label", prop.name)
|
||||
panels["BOOKMARK"].append({"bl_idname": prop.name, "bl_label": bl_label})
|
||||
|
||||
if not panels["BOOKMARK"]:
|
||||
panels["BOOKMARK"] = [{}]
|
||||
|
||||
return panels
|
||||
|
||||
|
||||
def initialize_tab_visibilities():
|
||||
bim_props = tool.Blender.get_bim_props()
|
||||
|
||||
if len(bim_props.tab_visibilities) > 0:
|
||||
return
|
||||
|
||||
for tab_name in get_tab_names():
|
||||
tab_vis = bim_props.tab_visibilities.add()
|
||||
tab_vis.name = tab_name
|
||||
tab_vis.is_visible = True
|
||||
|
||||
|
||||
def initialize_panel_properties():
|
||||
|
||||
bim_props = tool.Blender.get_bim_props()
|
||||
|
||||
if len(bim_props.panel_properties) > 0:
|
||||
return
|
||||
|
||||
for attr_name in dir(bpy.types):
|
||||
if attr_name.startswith("BIM_PT_tab_"):
|
||||
panel_class = getattr(bpy.types, attr_name)
|
||||
if not hasattr(panel_class, "bl_idname"):
|
||||
continue
|
||||
|
||||
panel_id = panel_class.bl_idname
|
||||
|
||||
prop = bim_props.panel_properties.add()
|
||||
prop.name = panel_id
|
||||
prop.is_visible_in_tab = True
|
||||
prop.is_visible_in_bookmarks = True
|
||||
prop.is_bookmarked = False
|
||||
|
||||
@@ -17,26 +17,28 @@
|
||||
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from __future__ import annotations
|
||||
import os
|
||||
import bpy
|
||||
import uuid
|
||||
import shutil
|
||||
|
||||
import hashlib
|
||||
import zipfile
|
||||
import os
|
||||
import shutil
|
||||
import tempfile
|
||||
import traceback
|
||||
import uuid
|
||||
import zipfile
|
||||
from collections.abc import Callable
|
||||
from pathlib import Path
|
||||
from typing import Literal, NotRequired, Optional, TypedDict, Union
|
||||
|
||||
import bpy
|
||||
import ifcopenshell
|
||||
import ifcopenshell.geom
|
||||
import ifcopenshell.ifcopenshell_wrapper
|
||||
from ifcopenshell.file import UndoSystemError
|
||||
|
||||
import bonsai
|
||||
import bonsai.bim.handler
|
||||
import bonsai.tool as tool
|
||||
from ifcopenshell.file import UndoSystemError
|
||||
from pathlib import Path
|
||||
from bonsai.tool.brick import BrickStore
|
||||
from typing import Union, Optional, TypedDict, NotRequired, Literal
|
||||
from collections.abc import Callable
|
||||
|
||||
|
||||
IFC_CONNECTED_TYPE = Union[bpy.types.Material, bpy.types.Object]
|
||||
|
||||
|
||||
@@ -17,33 +17,36 @@
|
||||
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from __future__ import annotations
|
||||
import bpy
|
||||
import time
|
||||
|
||||
import json
|
||||
import ifcpatch
|
||||
import logging
|
||||
import traceback
|
||||
import mathutils
|
||||
import numpy as np
|
||||
import numpy.typing as npt
|
||||
import multiprocessing
|
||||
import time
|
||||
import traceback
|
||||
from collections.abc import Iterable
|
||||
from typing import Any, Literal, Optional, Union
|
||||
|
||||
import bpy
|
||||
import ifcopenshell
|
||||
import ifcopenshell.api.pset
|
||||
import ifcopenshell.geom
|
||||
import ifcopenshell.ifcopenshell_wrapper as W
|
||||
import ifcopenshell.util.unit
|
||||
import ifcopenshell.util.element
|
||||
import ifcopenshell.util.geolocation
|
||||
import ifcopenshell.util.placement
|
||||
import ifcopenshell.util.representation
|
||||
import ifcopenshell.util.shape
|
||||
import bonsai.tool as tool
|
||||
from bonsai.bim.ifc import IfcStore, IFC_CONNECTED_TYPE
|
||||
from bonsai.tool.loader import OBJECT_DATA_TYPE
|
||||
from typing import Union, Optional, Any, Literal
|
||||
from collections.abc import Iterable
|
||||
import ifcopenshell.util.unit
|
||||
import ifcpatch
|
||||
import mathutils
|
||||
import numpy as np
|
||||
import numpy.typing as npt
|
||||
from ifcopenshell.util.shape import MatrixType
|
||||
|
||||
import bonsai.tool as tool
|
||||
from bonsai.bim.ifc import IFC_CONNECTED_TYPE, IfcStore
|
||||
from bonsai.tool.loader import OBJECT_DATA_TYPE
|
||||
|
||||
|
||||
class MaterialCreator:
|
||||
mesh: bpy.types.Mesh
|
||||
@@ -290,7 +293,6 @@ class IfcImporter:
|
||||
self.profile_code("Load linked models")
|
||||
self.add_project_to_scene()
|
||||
self.profile_code("Add project to scene")
|
||||
self.hide_ifc_spaces()
|
||||
if self.ifc_import_settings.should_clean_mesh and len(self.file.by_type("IfcElement")) < 1000:
|
||||
self.clean_mesh()
|
||||
self.profile_code("Mesh cleaning")
|
||||
@@ -1287,13 +1289,6 @@ class IfcImporter:
|
||||
properties={"Aggregate_Index": aggregate_index, "Name": name},
|
||||
)
|
||||
|
||||
def hide_ifc_spaces(self):
|
||||
"""Hide IfcSpace objects after they've been added to the scene."""
|
||||
for ifc_definition_id, obj in self.added_data.items():
|
||||
if isinstance(obj, bpy.types.Object):
|
||||
element = self.file.by_id(ifc_definition_id)
|
||||
if element.is_a("IfcSpace"):
|
||||
obj.hide_set(True)
|
||||
|
||||
class IfcImportSettings:
|
||||
"""
|
||||
@@ -1311,7 +1306,7 @@ class IfcImportSettings:
|
||||
self.should_load_geometry = True
|
||||
self.should_clean_mesh = False
|
||||
self.should_cache = True
|
||||
self.deflection_tolerance = 0.001
|
||||
self.deflection_tolerance = 0.05 # Default is 0.001, but I find this to be more practical
|
||||
self.angular_tolerance = 0.5
|
||||
self.void_limit = 30
|
||||
self.style_limit = 300
|
||||
|
||||
@@ -17,7 +17,8 @@
|
||||
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import bpy
|
||||
from . import ui, prop, operator
|
||||
|
||||
from . import operator, prop, ui
|
||||
|
||||
classes = (
|
||||
operator.BIM_OT_add_aggregate,
|
||||
|
||||
@@ -16,11 +16,13 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import bpy
|
||||
import bonsai.tool as tool
|
||||
import ifcopenshell.util.element
|
||||
from typing import Union
|
||||
|
||||
import bpy
|
||||
import ifcopenshell.util.element
|
||||
|
||||
import bonsai.tool as tool
|
||||
|
||||
|
||||
def refresh():
|
||||
AggregateData.is_loaded = False
|
||||
|
||||
@@ -21,11 +21,12 @@ import bpy
|
||||
import gpu
|
||||
import ifcopenshell
|
||||
import ifcopenshell.util.element
|
||||
import bonsai.tool as tool
|
||||
from bpy.types import SpaceView3D
|
||||
from bpy_extras import view3d_utils
|
||||
from gpu_extras.batch import batch_for_shader
|
||||
from mathutils import Vector
|
||||
|
||||
import bonsai.tool as tool
|
||||
from bonsai.bim.module.geometry.decorator import ItemDecorator
|
||||
|
||||
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
import bpy
|
||||
import ifcopenshell
|
||||
import ifcopenshell.api
|
||||
@@ -23,10 +25,10 @@ import ifcopenshell.api.group
|
||||
import ifcopenshell.api.pset
|
||||
import ifcopenshell.api.root
|
||||
import ifcopenshell.util.element
|
||||
import bonsai.tool as tool
|
||||
|
||||
import bonsai.core.aggregate as core
|
||||
import bonsai.core.spatial
|
||||
from typing import TYPE_CHECKING
|
||||
import bonsai.tool as tool
|
||||
|
||||
|
||||
class BIM_OT_aggregate_assign_object(bpy.types.Operator, tool.Ifc.Operator):
|
||||
@@ -222,7 +224,7 @@ class BIM_OT_add_aggregate(bpy.types.Operator, tool.Ifc.Operator):
|
||||
tool.Collector,
|
||||
tool.Spatial,
|
||||
container=current_container,
|
||||
element_obj=aggregate,
|
||||
objs=[aggregate],
|
||||
)
|
||||
core.assign_object(tool.Ifc, tool.Aggregate, tool.Collector, relating_obj=aggregate, related_obj=obj)
|
||||
|
||||
|
||||
@@ -16,24 +16,29 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from typing import TYPE_CHECKING, Union
|
||||
|
||||
import bpy
|
||||
import ifcopenshell.util.element
|
||||
import bonsai.tool as tool
|
||||
from bonsai.bim.prop import StrProperty, Attribute
|
||||
from bonsai.bim.module.spatial.data import SpatialData
|
||||
from bpy.types import PropertyGroup
|
||||
from bpy.props import (
|
||||
PointerProperty,
|
||||
StringProperty,
|
||||
EnumProperty,
|
||||
BoolProperty,
|
||||
IntProperty,
|
||||
CollectionProperty,
|
||||
EnumProperty,
|
||||
FloatProperty,
|
||||
FloatVectorProperty,
|
||||
CollectionProperty,
|
||||
IntProperty,
|
||||
PointerProperty,
|
||||
StringProperty,
|
||||
)
|
||||
from bonsai.bim.module.aggregate.decorator import AggregateDecorator, AggregateModeDecorator
|
||||
from typing import TYPE_CHECKING, Union
|
||||
from bpy.types import PropertyGroup
|
||||
|
||||
import bonsai.tool as tool
|
||||
from bonsai.bim.module.aggregate.decorator import (
|
||||
AggregateDecorator,
|
||||
AggregateModeDecorator,
|
||||
)
|
||||
from bonsai.bim.module.spatial.data import SpatialData
|
||||
from bonsai.bim.prop import Attribute, StrProperty
|
||||
|
||||
|
||||
def can_aggregate(relating_obj: bpy.types.Object, related_obj: bpy.types.Object) -> bool:
|
||||
|
||||
@@ -17,10 +17,11 @@
|
||||
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from bpy.types import Panel
|
||||
|
||||
import bonsai.tool as tool
|
||||
from bonsai.bim.ifc import IfcStore
|
||||
from bonsai.bim.module.aggregate.data import AggregateData
|
||||
from bonsai.bim.module.group.data import GroupsData, ObjectGroupsData
|
||||
from bonsai.bim.ifc import IfcStore
|
||||
import bonsai.tool as tool
|
||||
|
||||
|
||||
class BIM_PT_aggregate(Panel):
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Bonsai - OpenBIM Blender Add-on
|
||||
# Copyright (C) 2020, 2021 Dion Moult <dion@thinkmoult.com>
|
||||
# Copyright (C) 2020, 2021 Dion Moult <dion@thinkmoult.com>, 2026 Michael Yoder <myoder@desertspringscivil.com>
|
||||
#
|
||||
# This file is part of Bonsai.
|
||||
#
|
||||
@@ -17,11 +17,37 @@
|
||||
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import bpy
|
||||
from bpy.app.handlers import persistent
|
||||
from . import ui, prop, operator, decorator
|
||||
|
||||
# from . import ui, prop, operator
|
||||
from . import operator
|
||||
|
||||
classes = (operator.ImportAlignmentCSV,)
|
||||
classes = (
|
||||
# Property groups (must be registered before classes that use them)
|
||||
prop.AlignmentPI,
|
||||
prop.AlignmentDisplayRow,
|
||||
prop.CivilAlignmentProperties,
|
||||
# UILists
|
||||
ui.CIVIL_UL_alignment_pis,
|
||||
operator.ImportAlignmentCSV,
|
||||
# Operators - PI Management
|
||||
operator.CIVIL_OT_add_pi,
|
||||
operator.CIVIL_OT_remove_pi,
|
||||
operator.CIVIL_OT_pick_pi_from_viewport,
|
||||
operator.CIVIL_OT_recalculate_pis,
|
||||
operator.CIVIL_OT_clear_pis,
|
||||
# Operators - Creation
|
||||
operator.CIVIL_OT_create_alignment_by_pi,
|
||||
operator.CIVIL_OT_import_alignment_csv,
|
||||
# Operators - Stationing
|
||||
operator.CIVIL_OT_add_stationing_referent,
|
||||
operator.CIVIL_OT_name_segments,
|
||||
# Operators - PI Edit Mode
|
||||
operator.CIVIL_OT_enter_pi_edit_mode,
|
||||
# UI Panels (appear in Properties sidebar under CIVIL tab)
|
||||
ui.CIVIL_PT_alignment_creation,
|
||||
ui.CIVIL_PT_pi_editor,
|
||||
ui.CIVIL_PT_alignment_stationing,
|
||||
)
|
||||
|
||||
|
||||
def menu_func_import(self, context):
|
||||
@@ -29,8 +55,10 @@ def menu_func_import(self, context):
|
||||
|
||||
|
||||
def register():
|
||||
bpy.types.Scene.CivilAlignmentProperties = bpy.props.PointerProperty(type=prop.CivilAlignmentProperties)
|
||||
bpy.types.TOPBAR_MT_file_import.append(menu_func_import)
|
||||
|
||||
|
||||
def unregister():
|
||||
bpy.types.TOPBAR_MT_file_import.remove(menu_func_import)
|
||||
del bpy.types.Scene.CivilAlignmentProperties
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
# Bonsai - OpenBIM Blender Add-on
|
||||
# Copyright (C) 2025, 2026 Michael Yoder <myoder@desertspringscivil.com>
|
||||
#
|
||||
# This file is part of Bonsai.
|
||||
#
|
||||
# Bonsai is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Bonsai is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
"""Data caching layer for the alignment module
|
||||
|
||||
This module provides cached access to alignment data for UI display,
|
||||
following Bonsai's data loading pattern.
|
||||
"""
|
||||
|
||||
import bonsai.tool as tool
|
||||
|
||||
|
||||
class AlignmentData:
|
||||
"""Cached alignment data for UI display"""
|
||||
|
||||
data = {}
|
||||
is_loaded = False
|
||||
|
||||
@classmethod
|
||||
def load(cls):
|
||||
"""Load alignment data from IFC file"""
|
||||
cls.data = {
|
||||
"alignments": [],
|
||||
"active_alignment": None,
|
||||
"segments": [],
|
||||
}
|
||||
|
||||
ifc = tool.Ifc.get()
|
||||
if ifc is None:
|
||||
cls.is_loaded = True
|
||||
return
|
||||
|
||||
# Load all alignments
|
||||
alignments = ifc.by_type("IfcAlignment")
|
||||
cls.data["alignments"] = [
|
||||
{
|
||||
"id": a.id(),
|
||||
"name": a.Name or f"Alignment {a.id()}",
|
||||
"global_id": a.GlobalId,
|
||||
}
|
||||
for a in alignments
|
||||
]
|
||||
|
||||
cls.is_loaded = True
|
||||
|
||||
@classmethod
|
||||
def refresh(cls):
|
||||
"""Force refresh of alignment data"""
|
||||
cls.is_loaded = False
|
||||
cls.load()
|
||||
@@ -0,0 +1,193 @@
|
||||
# Bonsai - OpenBIM Blender Add-on
|
||||
# Copyright (C) 2025, 2026 Michael Yoder <myoder@desertspringscivil.com>
|
||||
#
|
||||
# This file is part of Bonsai.
|
||||
#
|
||||
# Bonsai is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Bonsai is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
"""Alignment module decorators for GPU visualization.
|
||||
|
||||
This module contains decorators for rendering visual feedback during
|
||||
alignment-related operations, such as PI editing.
|
||||
"""
|
||||
|
||||
import bpy
|
||||
import blf
|
||||
import gpu
|
||||
import bonsai.tool as tool
|
||||
from bpy.types import SpaceView3D
|
||||
from gpu_extras.batch import batch_for_shader
|
||||
|
||||
|
||||
class PIEditDecorator:
|
||||
"""Decorator for visualizing PI edit mode.
|
||||
|
||||
This decorator provides visual feedback while the user is editing
|
||||
PI (Point of Intersection) positions with standard Blender transform tools:
|
||||
- Yellow lines connecting PI empties (tangent preview)
|
||||
- HUD text showing instructions
|
||||
|
||||
The decorator reads positions directly from the PI empty objects,
|
||||
which are updated by Blender's transform operators (G key).
|
||||
"""
|
||||
|
||||
# Class-level state (cleared on uninstall)
|
||||
is_installed = False
|
||||
handlers = []
|
||||
|
||||
# References to PI empty objects
|
||||
pi_empties = []
|
||||
|
||||
# Colors
|
||||
COLOR_TANGENT_LINE = (1.0, 0.9, 0.2, 1.0) # Yellow for tangent lines
|
||||
COLOR_HUD_TEXT = (1.0, 1.0, 1.0, 1.0) # White for HUD text
|
||||
COLOR_EDIT_MODE_BG = (0.2, 0.4, 0.8, 0.8) # Blue tint for edit mode indicator
|
||||
|
||||
# Drawing parameters
|
||||
LINE_WIDTH = 2.5
|
||||
|
||||
@classmethod
|
||||
def install(cls, context, pi_empties):
|
||||
"""Install decorator handlers for PI edit mode visualization.
|
||||
|
||||
Args:
|
||||
context: Blender context
|
||||
pi_empties: List of PI EMPTY objects to visualize
|
||||
"""
|
||||
if cls.is_installed:
|
||||
cls.uninstall()
|
||||
|
||||
cls.pi_empties = pi_empties
|
||||
|
||||
handler = cls()
|
||||
# POST_VIEW for 3D world-space drawing (tangent lines in 3D)
|
||||
cls.handlers.append(
|
||||
SpaceView3D.draw_handler_add(handler.draw_tangent_lines_3d, (context,), "WINDOW", "POST_VIEW")
|
||||
)
|
||||
# POST_PIXEL for 2D screen-space drawing (HUD)
|
||||
cls.handlers.append(
|
||||
SpaceView3D.draw_handler_add(handler.draw_hud, (context,), "WINDOW", "POST_PIXEL")
|
||||
)
|
||||
cls.is_installed = True
|
||||
|
||||
@classmethod
|
||||
def uninstall(cls):
|
||||
"""Remove all handlers and clear state."""
|
||||
for handler in cls.handlers:
|
||||
try:
|
||||
SpaceView3D.draw_handler_remove(handler, "WINDOW")
|
||||
except ValueError:
|
||||
pass
|
||||
cls.handlers = []
|
||||
cls.is_installed = False
|
||||
cls.pi_empties = []
|
||||
|
||||
@classmethod
|
||||
def update_positions(cls, pi_empties):
|
||||
"""Update the list of PI empties (called when positions change).
|
||||
|
||||
Args:
|
||||
pi_empties: Updated list of PI EMPTY objects
|
||||
"""
|
||||
cls.pi_empties = pi_empties
|
||||
|
||||
def draw_batch_3d(self, shader_type, content_pos, color, indices=None):
|
||||
"""Draw a batch of 3D primitives using GPU shader.
|
||||
|
||||
Args:
|
||||
shader_type: Type of primitive ("LINES", "POINTS", etc.)
|
||||
content_pos: List of 3D vertex positions
|
||||
color: RGBA color tuple
|
||||
indices: Optional list of index pairs for lines
|
||||
"""
|
||||
if not tool.Blender.validate_shader_batch_data(content_pos, indices):
|
||||
return
|
||||
shader = gpu.shader.from_builtin("POLYLINE_UNIFORM_COLOR")
|
||||
shader.bind()
|
||||
|
||||
# Get viewport size from active region
|
||||
region = bpy.context.region
|
||||
shader.uniform_float("viewportSize", (region.width, region.height))
|
||||
shader.uniform_float("lineWidth", self.LINE_WIDTH)
|
||||
|
||||
batch = batch_for_shader(shader, shader_type, {"pos": content_pos}, indices=indices)
|
||||
shader.uniform_float("color", color)
|
||||
batch.draw(shader)
|
||||
|
||||
def draw_tangent_lines_3d(self, context):
|
||||
"""Draw yellow tangent lines connecting PI empties in 3D space."""
|
||||
if not self.pi_empties or len(self.pi_empties) < 2:
|
||||
return
|
||||
|
||||
# Collect 3D positions from empties
|
||||
positions = []
|
||||
for empty in self.pi_empties:
|
||||
if empty and empty.name in bpy.data.objects:
|
||||
positions.append(tuple(empty.location))
|
||||
|
||||
if len(positions) < 2:
|
||||
return
|
||||
|
||||
# Setup blending for line drawing
|
||||
gpu.state.blend_set("ALPHA")
|
||||
gpu.state.depth_test_set("LESS_EQUAL")
|
||||
gpu.state.depth_mask_set(False)
|
||||
|
||||
# Build edges list
|
||||
edges = [[i, i + 1] for i in range(len(positions) - 1)]
|
||||
|
||||
# Draw lines
|
||||
self.draw_batch_3d("LINES", positions, self.COLOR_TANGENT_LINE, edges)
|
||||
|
||||
# Restore state
|
||||
gpu.state.blend_set("NONE")
|
||||
gpu.state.depth_test_set("NONE")
|
||||
gpu.state.depth_mask_set(True)
|
||||
|
||||
def draw_hud(self, context):
|
||||
"""Draw HUD text with edit mode instructions."""
|
||||
region = context.region
|
||||
if not region:
|
||||
return
|
||||
|
||||
font_id = 0
|
||||
font_size = tool.Blender.scale_font_size(14)
|
||||
blf.size(font_id, font_size)
|
||||
blf.enable(font_id, blf.SHADOW)
|
||||
blf.shadow(font_id, 6, 0, 0, 0, 1) # Black shadow for readability
|
||||
blf.color(font_id, *self.COLOR_HUD_TEXT)
|
||||
|
||||
# Position in top-left of viewport
|
||||
margin = 20
|
||||
line_height = 22
|
||||
y_pos = region.height - margin
|
||||
|
||||
# Count valid empties
|
||||
valid_count = sum(1 for e in self.pi_empties if e and e.name in bpy.data.objects)
|
||||
|
||||
# Instructions
|
||||
instructions = [
|
||||
"PI Edit Mode",
|
||||
f"PIs: {valid_count}",
|
||||
"",
|
||||
"G: Move selected PI",
|
||||
"ENTER: Apply changes",
|
||||
"ESC: Cancel",
|
||||
]
|
||||
|
||||
for i, line in enumerate(instructions):
|
||||
blf.position(font_id, margin, y_pos - (i * line_height), 0)
|
||||
blf.draw(font_id, line)
|
||||
|
||||
blf.disable(font_id, blf.SHADOW)
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,215 @@
|
||||
# Bonsai - OpenBIM Blender Add-on
|
||||
# Copyright (C) 2025, 2026 Michael Yoder <myoder@desertspringscivil.com>
|
||||
#
|
||||
# This file is part of Bonsai.
|
||||
#
|
||||
# Bonsai is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Bonsai is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
"""Property groups for the alignment module"""
|
||||
|
||||
import bpy
|
||||
from bpy.types import PropertyGroup
|
||||
from bpy.props import (
|
||||
StringProperty,
|
||||
FloatProperty,
|
||||
IntProperty,
|
||||
BoolProperty,
|
||||
CollectionProperty,
|
||||
EnumProperty,
|
||||
)
|
||||
|
||||
|
||||
def _on_radius_update(self, context):
|
||||
"""Callback when radius property changes.
|
||||
|
||||
This dynamically imports the operator module to call on_radius_changed,
|
||||
avoiding circular imports since prop.py is imported before operator.py.
|
||||
"""
|
||||
from . import operator as ops
|
||||
|
||||
ops.on_radius_changed(self, context)
|
||||
|
||||
|
||||
class AlignmentPI(PropertyGroup):
|
||||
"""Property group for a single PI (Point of Intersection)
|
||||
|
||||
In the PI method, alignments are defined by:
|
||||
- Endpoint PIs: Start (POB) and End (POE) points
|
||||
- Interior PIs: Points where tangents intersect, optionally with curves
|
||||
"""
|
||||
|
||||
# Coordinates stored as global easting/northing (map coordinates).
|
||||
# Coordinate flow: Blender coords -> xyz2enh() -> global E/N (stored here)
|
||||
# global E/N -> enh2xyz(to_blender=False) -> local IFC coords (for IfcOpenShell API)
|
||||
e: StringProperty(name="E", description="Easting (global map coordinates)", default="0.0")
|
||||
n: StringProperty(name="N", description="Northing (global map coordinates)", default="0.0")
|
||||
|
||||
# PI Type
|
||||
pi_type: EnumProperty(
|
||||
name="Type",
|
||||
description="Type of PI point",
|
||||
items=[
|
||||
("ENDPOINT", "Endpoint", "Start or end point (no curve)"),
|
||||
("TANGENT", "Tangent", "Pass-through point (no curve)"),
|
||||
("CURVE", "Curve", "Point of intersection with curve"),
|
||||
],
|
||||
default="TANGENT",
|
||||
)
|
||||
|
||||
# Curve parameters (only used when pi_type == "CURVE")
|
||||
radius: FloatProperty(
|
||||
name="Radius",
|
||||
description="Curve radius (0 = no curve, sharp angle)",
|
||||
default=0.0,
|
||||
min=0.0,
|
||||
precision=3,
|
||||
unit="LENGTH",
|
||||
update=_on_radius_update,
|
||||
)
|
||||
|
||||
# Computed/display values (updated by recalculate operator)
|
||||
length_to_next: FloatProperty(
|
||||
name="Length",
|
||||
description="Length of tangent to next PI",
|
||||
default=0.0,
|
||||
precision=3,
|
||||
unit="LENGTH",
|
||||
)
|
||||
|
||||
direction_to_next: FloatProperty(
|
||||
name="Direction",
|
||||
description="Bearing/direction to next PI (degrees)",
|
||||
default=0.0,
|
||||
precision=4,
|
||||
subtype="ANGLE",
|
||||
)
|
||||
|
||||
# Station at this PI (computed)
|
||||
station: FloatProperty(
|
||||
name="Station",
|
||||
description="Station value at this PI",
|
||||
default=0.0,
|
||||
precision=2,
|
||||
)
|
||||
|
||||
|
||||
class AlignmentDisplayRow(PropertyGroup):
|
||||
"""Property group for interleaved point/segment display in the table.
|
||||
|
||||
This creates the Civil 3D-style view where points and segments
|
||||
are shown on separate rows:
|
||||
Point 1 (End)
|
||||
Segment 1 (Tan)
|
||||
Point 2 (Tan)
|
||||
Segment 2 (Tan)
|
||||
...
|
||||
"""
|
||||
|
||||
# Row type discriminator
|
||||
row_type: EnumProperty(
|
||||
name="Row Type",
|
||||
items=[
|
||||
("POINT", "Point", "A PI point row"),
|
||||
("SEGMENT", "Segment", "A segment row between points"),
|
||||
],
|
||||
default="POINT",
|
||||
)
|
||||
|
||||
# Segment number (1, 2, 3...) - only for SEGMENT rows
|
||||
segment_number: IntProperty(name="Segment #", default=0)
|
||||
|
||||
# Point index in the pis collection - for both types
|
||||
# For POINT rows: the PI index
|
||||
# For SEGMENT rows: the starting PI index of this segment
|
||||
pi_index: IntProperty(name="PI Index", default=0)
|
||||
|
||||
# Display type string (End, Tan, Curve for points; Tan, Curve for segments)
|
||||
display_type: StringProperty(name="Type", default="")
|
||||
|
||||
# Point coordinates (only for POINT rows)
|
||||
e: StringProperty(name="E", default="0.0")
|
||||
n: StringProperty(name="N", default="0.0")
|
||||
|
||||
# Segment properties (only for SEGMENT rows)
|
||||
length: FloatProperty(name="Length", default=0.0, precision=2, unit="LENGTH")
|
||||
radius: FloatProperty(name="Radius", default=0.0, precision=2, unit="LENGTH")
|
||||
arc_length: FloatProperty(name="Arc Length", default=0.0, precision=2, unit="LENGTH")
|
||||
|
||||
|
||||
class CivilAlignmentProperties(PropertyGroup):
|
||||
"""Properties for the alignment module"""
|
||||
|
||||
# Active alignment selection
|
||||
active_alignment_id: IntProperty(
|
||||
name="Active Alignment ID",
|
||||
description="IFC entity ID of the active alignment",
|
||||
default=0,
|
||||
)
|
||||
|
||||
active_alignment_name: StringProperty(
|
||||
name="Active Alignment",
|
||||
description="Name of the currently active alignment",
|
||||
default="",
|
||||
)
|
||||
|
||||
# New alignment creation properties
|
||||
new_alignment_name: StringProperty(
|
||||
name="Name",
|
||||
description="Name for new alignment",
|
||||
default="Alignment 1",
|
||||
)
|
||||
|
||||
start_station: FloatProperty(
|
||||
name="Start Station",
|
||||
description="Starting station value (e.g., 10000 for 100+00)",
|
||||
default=10000.0,
|
||||
min=0.0,
|
||||
)
|
||||
|
||||
# PI collection for PI method creation
|
||||
pis: CollectionProperty(type=AlignmentPI)
|
||||
active_pi_index: IntProperty(name="Active PI", default=0)
|
||||
|
||||
# Combined point/segment display rows (for Civil 3D-style table)
|
||||
display_rows: CollectionProperty(type=AlignmentDisplayRow)
|
||||
active_display_row_index: IntProperty(name="Active Display Row", default=0)
|
||||
|
||||
# PI Edit Mode state (for moving PIs with G key)
|
||||
is_pi_edit_mode: BoolProperty(
|
||||
name="PI Edit Mode Active",
|
||||
description="Whether PI edit mode is currently active",
|
||||
default=False,
|
||||
)
|
||||
|
||||
pi_edit_alignment_id: IntProperty(
|
||||
name="Editing Alignment ID",
|
||||
description="IFC ID of alignment being edited in PI edit mode",
|
||||
default=0,
|
||||
)
|
||||
|
||||
# Display options
|
||||
show_station_labels: BoolProperty(
|
||||
name="Show Station Labels",
|
||||
description="Show station labels along alignment",
|
||||
default=True,
|
||||
)
|
||||
|
||||
station_interval: FloatProperty(
|
||||
name="Station Interval",
|
||||
description="Interval between station markers",
|
||||
default=100.0,
|
||||
min=1.0,
|
||||
unit="LENGTH",
|
||||
)
|
||||
@@ -0,0 +1,269 @@
|
||||
# Bonsai - OpenBIM Blender Add-on
|
||||
# Copyright (C) 2025, 2026 Michael Yoder <myoder@desertspringscivil.com>
|
||||
#
|
||||
# This file is part of Bonsai.
|
||||
#
|
||||
# Bonsai is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Bonsai is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
"""UI panels for the alignment module
|
||||
|
||||
All panels appear in the Properties sidebar under the CIVIL tab,
|
||||
nested under BIM_PT_tab_horizontal_alignment.
|
||||
"""
|
||||
|
||||
import bpy
|
||||
import bonsai.tool as tool
|
||||
from bpy.types import Panel, UIList
|
||||
|
||||
|
||||
def is_ifc4x3():
|
||||
"""Check if the current IFC file is IFC4X3 schema"""
|
||||
return tool.Ifc.get_schema() == "IFC4X3"
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# UILists
|
||||
# =============================================================================
|
||||
|
||||
|
||||
class CIVIL_UL_alignment_pis(UIList):
|
||||
"""UIList for displaying interleaved points and segments (Civil 3D style)
|
||||
|
||||
Row types:
|
||||
- POINT rows: End (endpoint), Mid (interior PI without curve)
|
||||
- SEGMENT rows: Tan (tangent line), Curve (circular arc)
|
||||
|
||||
When a Mid point has radius > 0, it becomes a Curve segment row.
|
||||
"""
|
||||
|
||||
def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
|
||||
if self.layout_type in {"DEFAULT", "COMPACT"}:
|
||||
row = layout.row(align=True)
|
||||
|
||||
if item.row_type == "POINT":
|
||||
# Point row: No., Type, X, Y, Length, Radius
|
||||
row.label(text="") # No segment number for points
|
||||
|
||||
# Type with point/dot icon
|
||||
# "End" = endpoint (POB/POE), "Mid" = interior PI point
|
||||
row.label(text=item.display_type, icon="DOT")
|
||||
|
||||
# X, Y coordinates - get actual PI for editing
|
||||
pi = data.pis[item.pi_index] if item.pi_index < len(data.pis) else None
|
||||
if pi:
|
||||
sub = row.row(align=True)
|
||||
sub.prop(pi, "e", text="")
|
||||
sub.prop(pi, "n", text="")
|
||||
else:
|
||||
row.label(text=f"{float(item.e):.2f}")
|
||||
row.label(text=f"{float(item.n):.2f}")
|
||||
|
||||
# Length column - empty for point rows
|
||||
row.label(text="")
|
||||
|
||||
# Radius column - editable for Mid points (where curves can be added)
|
||||
if item.display_type == "Mid" and pi:
|
||||
row.prop(pi, "radius", text="")
|
||||
else:
|
||||
row.label(text="")
|
||||
|
||||
elif item.row_type == "SEGMENT":
|
||||
if item.display_type == "Curve":
|
||||
# Curve segment row: No., Type (arc icon), X, Y, Arc Length, Radius
|
||||
row.label(text=f"{item.segment_number}")
|
||||
row.label(text="Curve", icon="SPHERECURVE")
|
||||
|
||||
# Show PI coordinates on curve row
|
||||
row.label(text=f"{float(item.e):.2f}")
|
||||
row.label(text=f"{float(item.n):.2f}")
|
||||
|
||||
# Arc length
|
||||
row.label(text=f"{item.arc_length:.2f}")
|
||||
|
||||
# Radius - editable so user can modify or delete curve (set to 0)
|
||||
pi = data.pis[item.pi_index] if item.pi_index < len(data.pis) else None
|
||||
if pi:
|
||||
row.prop(pi, "radius", text="")
|
||||
else:
|
||||
row.label(text=f"{item.radius:.2f}")
|
||||
else:
|
||||
# Tangent segment row: No., Type (line icon), -, -, Length, -
|
||||
row.label(text=f"{item.segment_number}")
|
||||
row.label(text="Tan", icon="IPO_LINEAR")
|
||||
|
||||
# No X, Y for tangent segments
|
||||
row.label(text="")
|
||||
row.label(text="")
|
||||
|
||||
# Length
|
||||
row.label(text=f"{item.length:.2f}")
|
||||
|
||||
# No radius for tangent segments
|
||||
row.label(text="-")
|
||||
|
||||
elif self.layout_type == "GRID":
|
||||
layout.alignment = "CENTER"
|
||||
layout.label(text="", icon="DECORATE")
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# Creation Sub-Panel
|
||||
# =============================================================================
|
||||
|
||||
|
||||
class CIVIL_PT_alignment_creation(Panel):
|
||||
"""Sub-panel for alignment creation tools"""
|
||||
|
||||
bl_label = "Creation"
|
||||
bl_idname = "CIVIL_PT_alignment_creation"
|
||||
bl_space_type = "PROPERTIES"
|
||||
bl_region_type = "WINDOW"
|
||||
bl_context = "scene"
|
||||
bl_parent_id = "BIM_PT_tab_horizontal_alignment"
|
||||
bl_options = {"DEFAULT_CLOSED"}
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return tool.Blender.should_show_panel(context, "CIVIL", cls.bl_idname) and is_ifc4x3()
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
props = context.scene.CivilAlignmentProperties
|
||||
|
||||
# New alignment properties
|
||||
box = layout.box()
|
||||
box.label(text="New Alignment:", icon="ADD")
|
||||
box.prop(props, "new_alignment_name")
|
||||
box.prop(props, "start_station")
|
||||
|
||||
# Creation operators
|
||||
col = layout.column(align=True)
|
||||
col.operator("civil.create_alignment_by_pi", icon="CURVE_DATA")
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# PI Editor Sub-Panel
|
||||
# =============================================================================
|
||||
|
||||
|
||||
class CIVIL_PT_pi_editor(Panel):
|
||||
"""Sub-panel for PI point table editor (Civil 3D style grid view)"""
|
||||
|
||||
bl_label = "PI Editor"
|
||||
bl_idname = "CIVIL_PT_pi_editor"
|
||||
bl_space_type = "PROPERTIES"
|
||||
bl_region_type = "WINDOW"
|
||||
bl_context = "scene"
|
||||
bl_parent_id = "BIM_PT_tab_horizontal_alignment"
|
||||
bl_options = set() # Open by default
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return tool.Blender.should_show_panel(context, "CIVIL", cls.bl_idname) and is_ifc4x3()
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
props = context.scene.CivilAlignmentProperties
|
||||
|
||||
# PI Edit Mode indicator
|
||||
if props.is_pi_edit_mode:
|
||||
box = layout.box()
|
||||
box.alert = True
|
||||
box.label(text="PI Edit Mode Active", icon="EDITMODE_HLT")
|
||||
col = box.column(align=True)
|
||||
col.label(text="Move PIs with G key")
|
||||
col.label(text="Press Enter to apply")
|
||||
col.label(text="Press Escape to cancel")
|
||||
layout.separator()
|
||||
return # Don't show normal UI while in edit mode
|
||||
|
||||
# Edit existing alignment button
|
||||
if props.active_alignment_id != 0:
|
||||
box = layout.box()
|
||||
box.label(text="Edit Alignment:", icon="EDITMODE_HLT")
|
||||
box.operator("civil.enter_pi_edit_mode", icon="PIVOT_CURSOR", text="Edit PIs (G key)")
|
||||
layout.separator()
|
||||
|
||||
# Header row with column labels
|
||||
header = layout.row(align=True)
|
||||
header.label(text="No.")
|
||||
header.label(text="Type")
|
||||
header.label(text="E")
|
||||
header.label(text="N")
|
||||
header.label(text="Length")
|
||||
header.label(text="Radius")
|
||||
|
||||
# Combined point/segment list (interleaved view)
|
||||
row = layout.row()
|
||||
row.template_list(
|
||||
"CIVIL_UL_alignment_pis",
|
||||
"",
|
||||
props,
|
||||
"display_rows",
|
||||
props,
|
||||
"active_display_row_index",
|
||||
rows=8,
|
||||
)
|
||||
|
||||
# Side buttons for list management
|
||||
col = row.column(align=True)
|
||||
col.operator("civil.add_pi", icon="ADD", text="")
|
||||
col.operator("civil.remove_pi", icon="REMOVE", text="")
|
||||
col.separator()
|
||||
col.operator("civil.pick_pi_from_viewport", icon="EYEDROPPER", text="")
|
||||
|
||||
# Bottom actions
|
||||
layout.separator()
|
||||
row = layout.row(align=True)
|
||||
row.operator("civil.recalculate_pis", icon="FILE_REFRESH", text="Recalculate")
|
||||
row.operator("civil.clear_pis", icon="TRASH", text="Clear All")
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# Stationing Sub-Panel
|
||||
# =============================================================================
|
||||
|
||||
|
||||
class CIVIL_PT_alignment_stationing(Panel):
|
||||
"""Sub-panel for stationing and referents"""
|
||||
|
||||
bl_label = "Stationing"
|
||||
bl_idname = "CIVIL_PT_alignment_stationing"
|
||||
bl_space_type = "PROPERTIES"
|
||||
bl_region_type = "WINDOW"
|
||||
bl_context = "scene"
|
||||
bl_parent_id = "BIM_PT_tab_horizontal_alignment"
|
||||
bl_options = {"DEFAULT_CLOSED"}
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return tool.Blender.should_show_panel(context, "CIVIL", cls.bl_idname) and is_ifc4x3()
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
props = context.scene.CivilAlignmentProperties
|
||||
|
||||
# Station display options
|
||||
box = layout.box()
|
||||
box.label(text="Display:", icon="HIDE_OFF")
|
||||
box.prop(props, "show_station_labels")
|
||||
box.prop(props, "station_interval")
|
||||
|
||||
layout.separator()
|
||||
|
||||
# Stationing operators
|
||||
col = layout.column(align=True)
|
||||
col.operator("civil.add_stationing_referent", icon="EMPTY_AXIS")
|
||||
col.operator("civil.name_segments", icon="FONT_DATA")
|
||||
@@ -17,7 +17,8 @@
|
||||
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import bpy
|
||||
from . import ui, prop, operator
|
||||
|
||||
from . import operator, prop, ui
|
||||
|
||||
classes = (
|
||||
operator.EnableEditingAttributes,
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
import bpy
|
||||
import ifcopenshell
|
||||
|
||||
import bonsai.tool as tool
|
||||
|
||||
|
||||
|
||||
@@ -16,22 +16,25 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import bpy
|
||||
import json
|
||||
from typing import TYPE_CHECKING, Any, Literal, Union
|
||||
|
||||
import bpy
|
||||
import ifcopenshell
|
||||
import ifcopenshell.api.attribute
|
||||
import ifcopenshell.guid
|
||||
import ifcopenshell.util.element
|
||||
|
||||
import bonsai.bim.helper
|
||||
import bonsai.tool as tool
|
||||
import bonsai.core.attribute as core
|
||||
import bonsai.core.spatial
|
||||
from typing import TYPE_CHECKING, Any, Union, Literal
|
||||
import bonsai.tool as tool
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from bonsai.bim.prop import Attribute
|
||||
import bpy.stub_internal.rna_enums as rna_enums
|
||||
|
||||
from bonsai.bim.prop import Attribute
|
||||
|
||||
|
||||
def get_objs_for_operation(
|
||||
operator_properties: "AttributesOperator", context: bpy.types.Context
|
||||
|
||||
@@ -16,21 +16,23 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from typing import TYPE_CHECKING, Union
|
||||
|
||||
import bpy
|
||||
import bonsai.tool as tool
|
||||
from bonsai.bim.prop import StrProperty, Attribute
|
||||
from bpy.types import PropertyGroup
|
||||
from bpy.props import (
|
||||
PointerProperty,
|
||||
StringProperty,
|
||||
EnumProperty,
|
||||
BoolProperty,
|
||||
IntProperty,
|
||||
CollectionProperty,
|
||||
EnumProperty,
|
||||
FloatProperty,
|
||||
FloatVectorProperty,
|
||||
CollectionProperty,
|
||||
IntProperty,
|
||||
PointerProperty,
|
||||
StringProperty,
|
||||
)
|
||||
from typing import TYPE_CHECKING, Union
|
||||
from bpy.types import PropertyGroup
|
||||
|
||||
import bonsai.tool as tool
|
||||
from bonsai.bim.prop import Attribute, StrProperty
|
||||
|
||||
|
||||
class BIMAttributeProperties(PropertyGroup):
|
||||
|
||||
@@ -17,12 +17,15 @@
|
||||
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from __future__ import annotations
|
||||
import bonsai.bim.helper
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
import bpy.types
|
||||
from bpy.types import Panel
|
||||
from bonsai.bim.module.attribute.data import AttributesData
|
||||
|
||||
import bonsai.bim.helper
|
||||
import bonsai.tool as tool
|
||||
from typing import TYPE_CHECKING
|
||||
from bonsai.bim.module.attribute.data import AttributesData
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from bonsai.bim.module.attribute.prop import BIMExplorerProperties, ExplorerEntity
|
||||
|
||||
@@ -17,7 +17,8 @@
|
||||
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import bpy
|
||||
from . import ui, prop, operator
|
||||
|
||||
from . import operator, prop, ui
|
||||
|
||||
classes = (
|
||||
prop.AuginProperties,
|
||||
|
||||
@@ -16,14 +16,16 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import datetime
|
||||
import os
|
||||
import bpy
|
||||
import string
|
||||
import random
|
||||
import shutil
|
||||
import requests
|
||||
import string
|
||||
import tempfile
|
||||
import datetime
|
||||
|
||||
import bpy
|
||||
import requests
|
||||
|
||||
import bonsai.tool as tool
|
||||
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import bpy.types
|
||||
|
||||
import bonsai.tool as tool
|
||||
|
||||
|
||||
|
||||
@@ -17,7 +17,8 @@
|
||||
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import bpy
|
||||
from . import ui, prop, operator
|
||||
|
||||
from . import operator, prop, ui
|
||||
|
||||
classes = (
|
||||
operator.ActivateBcfViewpoint,
|
||||
|
||||
@@ -17,12 +17,14 @@
|
||||
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import os
|
||||
import bpy
|
||||
from typing import Union
|
||||
|
||||
import bcf
|
||||
import bcf.bcfxml
|
||||
import bcf.v2.bcfxml
|
||||
import bpy
|
||||
|
||||
import bonsai.tool as tool
|
||||
from typing import Union
|
||||
|
||||
|
||||
class BcfStore:
|
||||
|
||||
@@ -17,6 +17,20 @@
|
||||
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import os
|
||||
import tempfile
|
||||
import uuid
|
||||
import webbrowser
|
||||
from math import atan, cos, degrees, radians, sin, tan
|
||||
from pathlib import Path
|
||||
|
||||
import bcf
|
||||
import bcf.agnostic.topic
|
||||
import bcf.agnostic.visinfo
|
||||
import bcf.bcfxml
|
||||
import bcf.v2.bcfxml
|
||||
import bcf.v2.model
|
||||
import bcf.v2.topic
|
||||
import bcf.v2.visinfo
|
||||
import bcf.v3
|
||||
import bcf.v3.bcfxml
|
||||
import bcf.v3.document
|
||||
@@ -24,30 +38,18 @@ import bcf.v3.model
|
||||
import bcf.v3.topic
|
||||
import bcf.v3.visinfo
|
||||
import bpy
|
||||
import bcf
|
||||
import bcf.bcfxml
|
||||
import bcf.v2.bcfxml
|
||||
import bcf.v2.model
|
||||
import bcf.v2.topic
|
||||
import bcf.v2.visinfo
|
||||
import bcf.agnostic.topic
|
||||
import bcf.agnostic.visinfo
|
||||
import uuid
|
||||
import numpy as np
|
||||
import tempfile
|
||||
import webbrowser
|
||||
import ifcopenshell
|
||||
import ifcopenshell.util.geolocation
|
||||
import ifcopenshell.util.unit
|
||||
import bonsai.tool as tool
|
||||
import bonsai.bim.module.bcf.prop as bcf_prop
|
||||
import bonsai.bim.module.bcf.bcfstore as bcfstore
|
||||
from bpy_extras.io_utils import ImportHelper, ExportHelper
|
||||
from pathlib import Path
|
||||
from math import radians, degrees, atan, tan, cos, sin
|
||||
from mathutils import Vector, Matrix, Euler, geometry
|
||||
import numpy as np
|
||||
from bpy_extras.io_utils import ExportHelper, ImportHelper
|
||||
from mathutils import Euler, Matrix, Vector, geometry
|
||||
from xsdata.models.datatype import XmlDateTime
|
||||
|
||||
import bonsai.bim.module.bcf.bcfstore as bcfstore
|
||||
import bonsai.bim.module.bcf.prop as bcf_prop
|
||||
import bonsai.tool as tool
|
||||
|
||||
|
||||
class NewBcfProject(bpy.types.Operator):
|
||||
bl_idname = "bim.new_bcf_project"
|
||||
|
||||
@@ -16,24 +16,26 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import bpy
|
||||
import bonsai.tool as tool
|
||||
from . import bcfstore
|
||||
from bonsai.bim.prop import StrProperty
|
||||
from bpy.types import PropertyGroup
|
||||
from bpy.props import (
|
||||
PointerProperty,
|
||||
StringProperty,
|
||||
EnumProperty,
|
||||
BoolProperty,
|
||||
IntProperty,
|
||||
FloatProperty,
|
||||
FloatVectorProperty,
|
||||
CollectionProperty,
|
||||
)
|
||||
from bcf.agnostic.extensions import get_extensions_attributes
|
||||
from typing import TYPE_CHECKING, Union
|
||||
|
||||
import bpy
|
||||
from bcf.agnostic.extensions import get_extensions_attributes
|
||||
from bpy.props import (
|
||||
BoolProperty,
|
||||
CollectionProperty,
|
||||
EnumProperty,
|
||||
FloatProperty,
|
||||
FloatVectorProperty,
|
||||
IntProperty,
|
||||
PointerProperty,
|
||||
StringProperty,
|
||||
)
|
||||
from bpy.types import PropertyGroup
|
||||
|
||||
import bonsai.tool as tool
|
||||
from bonsai.bim.prop import StrProperty
|
||||
|
||||
from . import bcfstore
|
||||
|
||||
bcfviewpoints_enum = None
|
||||
|
||||
|
||||
@@ -17,15 +17,19 @@
|
||||
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import bpy
|
||||
import bonsai.tool as tool
|
||||
from . import bcfstore
|
||||
from bpy.types import Panel
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
import bpy
|
||||
from bpy.types import Panel
|
||||
|
||||
import bonsai.tool as tool
|
||||
|
||||
from . import bcfstore
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from bonsai.bim.module.bcf.prop import BcfTopic, BCFProperties
|
||||
from bonsai.bim.module.bcf.prop import BCFProperties, BcfTopic
|
||||
|
||||
|
||||
class BIM_PT_bcf(Panel):
|
||||
|
||||
@@ -17,7 +17,8 @@
|
||||
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import bpy
|
||||
from . import ui, operator, prop
|
||||
|
||||
from . import operator, prop, ui
|
||||
|
||||
classes = (
|
||||
operator.AddBoundary,
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import bpy
|
||||
|
||||
import bonsai.tool as tool
|
||||
|
||||
|
||||
|
||||
@@ -16,12 +16,13 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import gpu
|
||||
import bmesh
|
||||
import bonsai.tool as tool
|
||||
import gpu
|
||||
from bpy.types import SpaceView3D
|
||||
from mathutils import Vector
|
||||
from gpu_extras.batch import batch_for_shader
|
||||
from mathutils import Vector
|
||||
|
||||
import bonsai.tool as tool
|
||||
|
||||
|
||||
class BoundaryDecorator:
|
||||
|
||||
@@ -16,34 +16,36 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import bpy
|
||||
import bmesh
|
||||
import logging
|
||||
import shapely
|
||||
import shapely.ops
|
||||
import mathutils
|
||||
import numpy as np
|
||||
import multiprocessing
|
||||
from math import acos, degrees, inf, pi, radians
|
||||
from typing import Optional, Union
|
||||
|
||||
import bmesh
|
||||
import bpy
|
||||
import ifcopenshell.api
|
||||
import ifcopenshell.api.boundary
|
||||
import ifcopenshell.api.root
|
||||
import ifcopenshell.geom
|
||||
import ifcopenshell.util.unit
|
||||
import ifcopenshell.util.shape
|
||||
import ifcopenshell.util.element
|
||||
import ifcopenshell.util.placement
|
||||
import ifcopenshell.util.representation
|
||||
import bonsai.tool as tool
|
||||
import bonsai.bim.import_ifc as import_ifc
|
||||
from math import pi, inf, degrees, acos, radians
|
||||
from mathutils import Vector, Matrix
|
||||
from bonsai.bim.ifc import IfcStore
|
||||
from bonsai.bim.module.model.decorator import ProfileDecorator
|
||||
from bonsai.bim.module.boundary.decorator import BoundaryDecorator
|
||||
import ifcopenshell.util.shape
|
||||
import ifcopenshell.util.unit
|
||||
import mathutils
|
||||
import numpy as np
|
||||
import shapely
|
||||
import shapely.ops
|
||||
from ifcopenshell.util.shape_builder import ShapeBuilder
|
||||
from mathutils import Matrix, Vector
|
||||
|
||||
import bonsai.bim.import_ifc as import_ifc
|
||||
import bonsai.core
|
||||
import bonsai.core.geometry
|
||||
from typing import Union, Optional
|
||||
import bonsai.tool as tool
|
||||
from bonsai.bim.ifc import IfcStore
|
||||
from bonsai.bim.module.boundary.decorator import BoundaryDecorator
|
||||
from bonsai.bim.module.model.decorator import ProfileDecorator
|
||||
|
||||
|
||||
def disable_editing_boundary_geometry(context):
|
||||
|
||||
@@ -16,21 +16,23 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from typing import TYPE_CHECKING, Union
|
||||
|
||||
import bpy
|
||||
from bpy.types import PropertyGroup
|
||||
from bonsai.bim.prop import ObjProperty
|
||||
from bpy.props import (
|
||||
PointerProperty,
|
||||
StringProperty,
|
||||
EnumProperty,
|
||||
BoolProperty,
|
||||
IntProperty,
|
||||
CollectionProperty,
|
||||
EnumProperty,
|
||||
FloatProperty,
|
||||
FloatVectorProperty,
|
||||
CollectionProperty,
|
||||
IntProperty,
|
||||
PointerProperty,
|
||||
StringProperty,
|
||||
)
|
||||
from bpy.types import PropertyGroup
|
||||
|
||||
import bonsai.tool as tool
|
||||
from typing import TYPE_CHECKING, Union
|
||||
from bonsai.bim.prop import ObjProperty
|
||||
|
||||
|
||||
def space_filter(self: "BIMObjectBoundaryProperties", object: bpy.types.Object) -> bool:
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
import bpy
|
||||
from bpy.types import Panel, UIList
|
||||
|
||||
import bonsai.tool as tool
|
||||
from bonsai.bim.module.boundary.data import SpaceBoundariesData
|
||||
|
||||
|
||||
@@ -17,7 +17,8 @@
|
||||
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import bpy
|
||||
from . import ui, prop, operator
|
||||
|
||||
from . import operator, prop, ui
|
||||
|
||||
classes = (
|
||||
operator.AddBrick,
|
||||
|
||||
@@ -17,11 +17,12 @@
|
||||
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import bpy
|
||||
|
||||
import bonsai.tool as tool
|
||||
from bonsai.tool.brick import BrickStore
|
||||
|
||||
try:
|
||||
from rdflib import URIRef, BNode
|
||||
from rdflib import BNode, URIRef
|
||||
except:
|
||||
# See #1860
|
||||
print("Warning: brickschema not available.")
|
||||
|
||||
@@ -17,12 +17,14 @@
|
||||
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import os
|
||||
|
||||
import bpy
|
||||
import ifcopenshell.api
|
||||
import bonsai.tool as tool
|
||||
import bonsai.core.brick as core
|
||||
from bpy_extras.io_utils import ExportHelper, ImportHelper
|
||||
|
||||
import bonsai.bim.handler
|
||||
from bpy_extras.io_utils import ImportHelper, ExportHelper
|
||||
import bonsai.core.brick as core
|
||||
import bonsai.tool as tool
|
||||
from bonsai.bim.ifc import IfcStore
|
||||
from bonsai.tool.brick import BrickStore
|
||||
|
||||
|
||||
@@ -16,24 +16,26 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
import bpy
|
||||
from bonsai.bim.module.brick.data import BrickschemaData, BrickschemaReferencesData
|
||||
from bonsai.bim.prop import StrProperty, Attribute
|
||||
from bpy.types import PropertyGroup
|
||||
from bpy.props import (
|
||||
PointerProperty,
|
||||
StringProperty,
|
||||
EnumProperty,
|
||||
BoolProperty,
|
||||
IntProperty,
|
||||
CollectionProperty,
|
||||
EnumProperty,
|
||||
FloatProperty,
|
||||
FloatVectorProperty,
|
||||
CollectionProperty,
|
||||
IntProperty,
|
||||
PointerProperty,
|
||||
StringProperty,
|
||||
)
|
||||
from bpy.types import PropertyGroup
|
||||
|
||||
import bonsai.core.brick as core
|
||||
import bonsai.tool.brick as tool
|
||||
from bonsai.bim.module.brick.data import BrickschemaData, BrickschemaReferencesData
|
||||
from bonsai.bim.prop import Attribute, StrProperty
|
||||
from bonsai.tool.brick import BrickStore
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
|
||||
def update_active_brick_index(self, context):
|
||||
|
||||
@@ -16,8 +16,9 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import bonsai.tool as tool
|
||||
from bpy.types import Panel, UIList
|
||||
|
||||
import bonsai.tool as tool
|
||||
from bonsai.bim.helper import prop_with_search
|
||||
from bonsai.bim.module.brick.data import BrickschemaData, BrickschemaReferencesData
|
||||
from bonsai.tool.brick import BrickStore
|
||||
|
||||
@@ -17,7 +17,8 @@
|
||||
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import bpy
|
||||
from . import ui, prop, operator
|
||||
|
||||
from . import operator, prop, ui
|
||||
|
||||
classes = (
|
||||
operator.AddBSDDProperties,
|
||||
|
||||
@@ -18,8 +18,9 @@
|
||||
|
||||
import bpy
|
||||
import ifcopenshell
|
||||
import ifcopenshell.util.date
|
||||
import ifcopenshell.util.classification
|
||||
import ifcopenshell.util.date
|
||||
|
||||
import bonsai.tool as tool
|
||||
from bonsai.bim.ifc import IfcStore
|
||||
|
||||
|
||||
@@ -16,13 +16,15 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
||||
import textwrap
|
||||
from typing import Any
|
||||
|
||||
import bpy
|
||||
import bsdd
|
||||
import bonsai.tool as tool
|
||||
import ifcopenshell.api.pset
|
||||
import ifcopenshell.util.element
|
||||
|
||||
import bonsai.tool as tool
|
||||
from bonsai.core import bsdd as core
|
||||
from typing import Any
|
||||
|
||||
|
||||
class LoadBSDDDictionaries(bpy.types.Operator):
|
||||
|
||||
@@ -16,23 +16,25 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from typing import TYPE_CHECKING, Literal, Union
|
||||
|
||||
import bpy
|
||||
import bonsai.tool as tool
|
||||
from bpy.props import (
|
||||
BoolProperty,
|
||||
CollectionProperty,
|
||||
EnumProperty,
|
||||
FloatProperty,
|
||||
FloatVectorProperty,
|
||||
IntProperty,
|
||||
PointerProperty,
|
||||
StringProperty,
|
||||
)
|
||||
from bpy.types import PropertyGroup
|
||||
|
||||
import bonsai.tool as tool
|
||||
from bonsai.bim.module.bsdd.data import BSDDData
|
||||
from bonsai.bim.module.classification.data import ClassificationsData
|
||||
from bonsai.bim.prop import Attribute, StrProperty
|
||||
from bpy.props import (
|
||||
PointerProperty,
|
||||
StringProperty,
|
||||
EnumProperty,
|
||||
BoolProperty,
|
||||
IntProperty,
|
||||
FloatProperty,
|
||||
FloatVectorProperty,
|
||||
CollectionProperty,
|
||||
)
|
||||
from typing import Union, TYPE_CHECKING, Literal
|
||||
|
||||
|
||||
def get_active_dictionary(self: "BIMBSDDProperties", context: object) -> tool.Blender.BLENDER_ENUM_ITEMS:
|
||||
@@ -161,7 +163,7 @@ class BIMBSDDProperties(PropertyGroup):
|
||||
default=False,
|
||||
)
|
||||
classification_psets: CollectionProperty(name="Classification Psets", type=BSDDPset)
|
||||
|
||||
|
||||
if TYPE_CHECKING:
|
||||
active_dictionary: str
|
||||
active_dictionary: str
|
||||
@@ -180,7 +182,7 @@ class BIMBSDDProperties(PropertyGroup):
|
||||
should_filter_ifc_class: bool
|
||||
use_only_ifc_properties: bool
|
||||
classification_psets: bpy.types.bpy_prop_collection_idprop[BSDDPset]
|
||||
|
||||
|
||||
@property
|
||||
def active_class(self) -> Union[BSDDClassification, None]:
|
||||
return tool.Blender.get_active_uilist_element(self.classes, self.active_class_index)
|
||||
|
||||
@@ -17,14 +17,23 @@
|
||||
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from __future__ import annotations
|
||||
import bpy
|
||||
import bonsai.tool as tool
|
||||
from bonsai.bim.module.bsdd.data import BSDDData
|
||||
from bpy.types import Panel, UIList
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
import bpy
|
||||
from bpy.types import Panel, UIList
|
||||
|
||||
import bonsai.tool as tool
|
||||
import bsdd
|
||||
from bonsai.bim.module.bsdd.data import BSDDData
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from bonsai.bim.module.bsdd.prop import BIMBSDDProperties, BSDDDictionary, BSDDClassification, BSDDProperty
|
||||
from bonsai.bim.module.bsdd.prop import (
|
||||
BIMBSDDProperties,
|
||||
BSDDClassification,
|
||||
BSDDDictionary,
|
||||
BSDDProperty,
|
||||
)
|
||||
|
||||
|
||||
class BIM_PT_bsdd(Panel):
|
||||
@@ -75,7 +84,6 @@ class BIM_PT_bsdd(Panel):
|
||||
row = self.layout.row()
|
||||
row.operator("bim.load_bsdd_dictionaries")
|
||||
|
||||
|
||||
class BIM_UL_bsdd_dictionaries(UIList):
|
||||
def draw_item(
|
||||
self,
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import bpy
|
||||
|
||||
from . import operator, prop, workspace
|
||||
|
||||
classes = (
|
||||
|
||||
@@ -16,17 +16,18 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import bpy
|
||||
import math
|
||||
import bmesh
|
||||
import mathutils
|
||||
import bpy_extras
|
||||
import bonsai.tool as tool
|
||||
from mathutils import Vector, Matrix
|
||||
from math import pi, radians, sin, cos, sqrt
|
||||
import ifcopenshell.util.unit
|
||||
from math import cos, pi, radians, sin, sqrt
|
||||
from typing import Union
|
||||
|
||||
import bmesh
|
||||
import bpy
|
||||
import bpy_extras
|
||||
import ifcopenshell.util.unit
|
||||
import mathutils
|
||||
from mathutils import Matrix, Vector
|
||||
|
||||
import bonsai.tool as tool
|
||||
|
||||
messages = {
|
||||
"SHARED_VERTEX": "Shared Vertex, no intersection possible",
|
||||
|
||||
@@ -16,12 +16,14 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import bpy
|
||||
from bonsai.bim.module.model.data import AuthoringData
|
||||
from bpy.types import PropertyGroup
|
||||
from math import pi
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
import bpy
|
||||
from bpy.types import PropertyGroup
|
||||
|
||||
from bonsai.bim.module.model.data import AuthoringData
|
||||
|
||||
|
||||
class BIMCadProperties(PropertyGroup):
|
||||
resolution: bpy.props.IntProperty(name="Arc Resolution", min=1, default=1)
|
||||
|
||||
@@ -17,13 +17,15 @@
|
||||
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import os
|
||||
from functools import partial
|
||||
|
||||
import bpy
|
||||
import bonsai.tool as tool
|
||||
import bonsai.bim.module.type.prop as type_prop
|
||||
import ifcopenshell.util.unit
|
||||
from bpy.types import WorkSpaceTool
|
||||
|
||||
import bonsai.bim.module.type.prop as type_prop
|
||||
import bonsai.tool as tool
|
||||
from bonsai.bim.module.model.data import AuthoringData, RailingData, RoofData
|
||||
from functools import partial
|
||||
|
||||
|
||||
def load_custom_icons():
|
||||
|
||||
@@ -17,7 +17,8 @@
|
||||
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import bpy
|
||||
from . import ui, prop, operator
|
||||
|
||||
from . import operator, prop, ui
|
||||
|
||||
classes = (
|
||||
operator.AddClashSet,
|
||||
|
||||
@@ -16,9 +16,11 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import bpy
|
||||
import json
|
||||
|
||||
import bpy
|
||||
import ifcopenshell.util.element
|
||||
|
||||
import bonsai.tool as tool
|
||||
|
||||
|
||||
|
||||
@@ -17,13 +17,14 @@
|
||||
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import blf
|
||||
import gpu
|
||||
import bmesh
|
||||
import bonsai.tool as tool
|
||||
import gpu
|
||||
from bpy.types import SpaceView3D
|
||||
from mathutils import Vector
|
||||
from gpu_extras.batch import batch_for_shader
|
||||
from bpy_extras.view3d_utils import location_3d_to_region_2d
|
||||
from gpu_extras.batch import batch_for_shader
|
||||
from mathutils import Vector
|
||||
|
||||
import bonsai.tool as tool
|
||||
|
||||
|
||||
class ClashDecorator:
|
||||
|
||||
@@ -16,22 +16,24 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import os
|
||||
import bpy
|
||||
import json
|
||||
import tempfile
|
||||
import bmesh
|
||||
import logging
|
||||
import numpy as np
|
||||
import ifcopenshell
|
||||
import bonsai.tool as tool
|
||||
from pathlib import Path
|
||||
from bpy_extras.io_utils import ExportHelper, ImportHelper
|
||||
import os
|
||||
import tempfile
|
||||
from math import radians
|
||||
from pathlib import Path
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
import bmesh
|
||||
import bpy
|
||||
import ifcopenshell
|
||||
import numpy as np
|
||||
from bpy_extras.io_utils import ExportHelper, ImportHelper
|
||||
from mathutils import Matrix, Vector
|
||||
|
||||
import bonsai.tool as tool
|
||||
from bonsai.bim.ifc import IfcStore
|
||||
from bonsai.bim.module.clash.decorator import ClashDecorator
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
|
||||
class ExportClashSets(bpy.types.Operator, ExportHelper):
|
||||
|
||||
@@ -16,23 +16,25 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from typing import TYPE_CHECKING, Literal, Union
|
||||
|
||||
import bpy
|
||||
import bonsai.tool as tool
|
||||
from bonsai.bim.prop import StrProperty, Attribute, BIMFilterGroup
|
||||
from bpy.types import PropertyGroup
|
||||
from bpy.props import (
|
||||
PointerProperty,
|
||||
StringProperty,
|
||||
EnumProperty,
|
||||
BoolProperty,
|
||||
IntProperty,
|
||||
CollectionProperty,
|
||||
EnumProperty,
|
||||
FloatProperty,
|
||||
FloatVectorProperty,
|
||||
CollectionProperty,
|
||||
IntProperty,
|
||||
PointerProperty,
|
||||
StringProperty,
|
||||
)
|
||||
from ifcopenshell.geom.main import ClashType, CLASH_TYPE_ITEMS
|
||||
from bpy.types import PropertyGroup
|
||||
from ifcopenshell.geom.main import CLASH_TYPE_ITEMS, ClashType
|
||||
from mathutils import Vector
|
||||
from typing import TYPE_CHECKING, Literal, Union
|
||||
|
||||
import bonsai.tool as tool
|
||||
from bonsai.bim.prop import Attribute, BIMFilterGroup, StrProperty
|
||||
|
||||
|
||||
class ClashSource(PropertyGroup):
|
||||
|
||||
@@ -17,15 +17,23 @@
|
||||
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from __future__ import annotations
|
||||
import bpy
|
||||
import bonsai.tool as tool
|
||||
import bonsai.bim.helper
|
||||
from bpy.types import Panel
|
||||
from bonsai.bim.module.clash.data import ClashData
|
||||
|
||||
from typing import TYPE_CHECKING, assert_never
|
||||
|
||||
import bpy
|
||||
from bpy.types import Panel
|
||||
|
||||
import bonsai.bim.helper
|
||||
import bonsai.tool as tool
|
||||
from bonsai.bim.module.clash.data import ClashData
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from bonsai.bim.module.clash.prop import BIMClashProperties, ClashSet, SmartClashGroup, Clash
|
||||
from bonsai.bim.module.clash.prop import (
|
||||
BIMClashProperties,
|
||||
Clash,
|
||||
ClashSet,
|
||||
SmartClashGroup,
|
||||
)
|
||||
|
||||
|
||||
class BIM_PT_ifcclash(Panel):
|
||||
|
||||
@@ -17,7 +17,8 @@
|
||||
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import bpy
|
||||
from . import ui, prop, operator
|
||||
|
||||
from . import operator, prop, ui
|
||||
|
||||
classes = (
|
||||
operator.AddClassification,
|
||||
|
||||
@@ -16,12 +16,14 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from typing import Any, Literal, Union
|
||||
|
||||
import bpy
|
||||
import ifcopenshell
|
||||
import ifcopenshell.util.date
|
||||
import ifcopenshell.util.classification
|
||||
import ifcopenshell.util.date
|
||||
|
||||
import bonsai.tool as tool
|
||||
from typing import Any, Literal, Union
|
||||
from bonsai.bim.ifc import IfcStore
|
||||
|
||||
|
||||
|
||||
@@ -19,13 +19,14 @@
|
||||
import bpy
|
||||
import ifcopenshell
|
||||
import ifcopenshell.api
|
||||
import ifcopenshell.api.pset
|
||||
import ifcopenshell.api.classification
|
||||
import ifcopenshell.api.pset
|
||||
import ifcopenshell.util.classification
|
||||
import ifcopenshell.util.element
|
||||
import bonsai.tool as tool
|
||||
import bonsai.bim.helper
|
||||
from bpy_extras.io_utils import ImportHelper
|
||||
|
||||
import bonsai.bim.helper
|
||||
import bonsai.tool as tool
|
||||
from bonsai.bim.ifc import IfcStore
|
||||
|
||||
|
||||
|
||||
@@ -16,22 +16,27 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
import bpy
|
||||
import bonsai.tool as tool
|
||||
from bonsai.bim.prop import Attribute
|
||||
from bonsai.bim.module.classification.data import ClassificationsData, ObjectClassificationsData
|
||||
from bpy.types import PropertyGroup
|
||||
from bpy.props import (
|
||||
PointerProperty,
|
||||
StringProperty,
|
||||
EnumProperty,
|
||||
BoolProperty,
|
||||
IntProperty,
|
||||
CollectionProperty,
|
||||
EnumProperty,
|
||||
FloatProperty,
|
||||
FloatVectorProperty,
|
||||
CollectionProperty,
|
||||
IntProperty,
|
||||
PointerProperty,
|
||||
StringProperty,
|
||||
)
|
||||
from typing import TYPE_CHECKING
|
||||
from bpy.types import PropertyGroup
|
||||
|
||||
import bonsai.tool as tool
|
||||
from bonsai.bim.module.classification.data import (
|
||||
ClassificationsData,
|
||||
ObjectClassificationsData,
|
||||
)
|
||||
from bonsai.bim.prop import Attribute
|
||||
|
||||
|
||||
def get_available_classifications(
|
||||
|
||||
@@ -17,24 +17,29 @@
|
||||
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from __future__ import annotations
|
||||
import bpy
|
||||
import bonsai.bim.helper
|
||||
import bonsai.tool as tool
|
||||
import bonsai.bim.module.classification.prop as classification_prop
|
||||
import ifcopenshell.util.classification
|
||||
|
||||
from bpy.types import Panel, UIList
|
||||
from bonsai.bim.module.classification.data import (
|
||||
ClassificationsData,
|
||||
ObjectClassificationsData,
|
||||
MaterialClassificationsData,
|
||||
CostClassificationsData,
|
||||
ZoneClassificationsData,
|
||||
)
|
||||
from typing import TYPE_CHECKING, Any, Union
|
||||
|
||||
import bpy
|
||||
import ifcopenshell.util.classification
|
||||
from bpy.types import Panel, UIList
|
||||
|
||||
import bonsai.bim.helper
|
||||
import bonsai.bim.module.classification.prop as classification_prop
|
||||
import bonsai.tool as tool
|
||||
from bonsai.bim.module.classification.data import (
|
||||
ClassificationsData,
|
||||
CostClassificationsData,
|
||||
MaterialClassificationsData,
|
||||
ObjectClassificationsData,
|
||||
ZoneClassificationsData,
|
||||
)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from bonsai.bim.module.classification.prop import BIMClassificationProperties, ClassificationReference
|
||||
from bonsai.bim.module.classification.prop import (
|
||||
BIMClassificationProperties,
|
||||
ClassificationReference,
|
||||
)
|
||||
|
||||
|
||||
class BIM_PT_classifications(Panel):
|
||||
|
||||
@@ -17,7 +17,8 @@
|
||||
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import bpy
|
||||
from . import ui, prop, operator
|
||||
|
||||
from . import operator, prop, ui
|
||||
|
||||
classes = (
|
||||
operator.LoadObjectives,
|
||||
|
||||
@@ -17,9 +17,10 @@
|
||||
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import bpy
|
||||
import bonsai.tool as tool
|
||||
from ifcopenshell.util.doc import get_entity_doc
|
||||
|
||||
import bonsai.tool as tool
|
||||
|
||||
|
||||
def refresh():
|
||||
ConstraintsData.is_loaded = False
|
||||
|
||||
@@ -16,12 +16,14 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
import bpy
|
||||
import ifcopenshell.api
|
||||
import ifcopenshell.api.constraint
|
||||
|
||||
import bonsai.bim.helper
|
||||
import bonsai.tool as tool
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
|
||||
def get_active_object(context: bpy.types.Context, obj_name: str) -> bpy.types.Object:
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user