diff --git a/.github/workflows/ci-black-formatting.yml b/.github/workflows/ci-black-formatting.yml
new file mode 100644
index 0000000000..fb293e36c8
--- /dev/null
+++ b/.github/workflows/ci-black-formatting.yml
@@ -0,0 +1,12 @@
+name: ci-black-formatting
+
+on:
+ push:
+ pull_request:
+
+jobs:
+ lint-formatting:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - uses: psf/black@stable
diff --git a/.github/workflows/ci-ifcconvert.yml b/.github/workflows/ci-ifcconvert.yml
new file mode 100644
index 0000000000..d47dad04ba
--- /dev/null
+++ b/.github/workflows/ci-ifcconvert.yml
@@ -0,0 +1,65 @@
+name: ci-ifcconvert
+
+on:
+ workflow_dispatch:
+
+jobs:
+ activate:
+ runs-on: ubuntu-latest
+ if: |
+ github.repository == 'IfcOpenShell/IfcOpenShell'
+ steps:
+ - name: Set env
+ run: echo ok go
+
+ build:
+ needs: activate
+ name: ${{ matrix.config.name }}-${{ matrix.pyver }}
+ runs-on: ubuntu-latest
+ strategy:
+ fail-fast: false
+ matrix:
+ config:
+ - {
+ name: "Windows 64bit",
+ short_name: win64,
+ }
+ - {
+ name: "Windows 32bit",
+ short_name: win32,
+ }
+ - {
+ name: "Linux 64bit",
+ short_name: linux64
+ }
+ - {
+ name: "MacOS Intel 64bit",
+ short_name: macos64
+ }
+ - {
+ name: "MacOS Silicon 64bit",
+ short_name: macosm164
+ }
+ steps:
+ - uses: actions/checkout@v2
+ - uses: actions/setup-python@v2 # https://github.com/actions/setup-python
+ with:
+ python-version: '3.11' # Version range or exact version of a Python version to use, using SemVer's version range syntax
+ architecture: 'x64' # optional x64 or x86. Defaults to x64 if not specified
+ - run: echo ${{ env.DATE }}
+ - name: Get current version
+ id: version
+ run: echo "version=$(cat VERSION)" >> $GITHUB_OUTPUT
+ - name: Compile
+ run: |
+ cd src/ifcopenshell-python &&
+ make zip-ifcconvert PLATFORM=${{ matrix.config.short_name }}
+ - name: Upload zip file to release
+ uses: svenstaro/upload-release-action@v2
+ with:
+ repo_token: ${{ secrets.GITHUB_TOKEN }}
+ file: src/ifcopenshell-python/dist/ifcconvert-${{ steps.version.outputs.version }}-${{ matrix.config.short_name }}.zip
+ asset_name: ifcconvert-${{ steps.version.outputs.version }}-${{ matrix.config.short_name }}.zip
+ release_name: "ifcconvert-${{steps.version.outputs.version}}"
+ tag: "ifcconvert-${{steps.version.outputs.version}}"
+ overwrite: true
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index d5d8f641b4..2f671da1a8 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -47,6 +47,7 @@ jobs:
run: |
python -m pip install --upgrade pip
pip install xmlschema xsdata numpy lxml pytest isodate lark networkx tabulate python-dateutil shapely
+ pip install mathutils
pip install src/bcf --no-deps
pip install https://github.com/Andrej730/aud/archive/refs/heads/master-reduced-size.zip
@@ -125,4 +126,9 @@ jobs:
python tests.py
cd ../src/ifcopenshell-python
mv ifcopenshell ifcopenshell-local # Force testing on installed module
- make test-safe
+ make test
+ cd ../bcf && make test
+ pip install requests
+ cd ../bsdd && make test
+ cd ../ifcpatch && make test
+ cd ../ifctester && make test
diff --git a/README.md b/README.md
index a7076b7d6d..21ba13c948 100644
--- a/README.md
+++ b/README.md
@@ -46,12 +46,12 @@ Contents
| ifcblender | Historic Blender IFC import add-on | LGPL-3.0-or-later\* |
| ifccityjson | Convert CityJSON to IFC | LGPL-3.0-or-later | [](https://pypi.org/project/ifccityjson/) |
| ifcclash | Clash detection library and CLI app | LGPL-3.0-or-later | [](https://pypi.org/project/ifcclash/) |
-| ifcconvert | CLI app to convert IFC to many other formats | LGPL-3.0-or-later\* | [](https://docs.ifcopenshell.org/ifcconvert/installation.html)
+| ifcconvert | CLI app to convert IFC to many other formats | LGPL-3.0-or-later\* | [](https://docs.ifcopenshell.org/ifcconvert/installation.html) [](https://github.com/IfcOpenShell/IfcOpenShell/releases?q=ifcconvert&expanded=true)
| ifccsv | Library and CLI app to export and import schedules from IFC | LGPL-3.0-or-later | [](https://pypi.org/project/ifccsv/) |
| ifcdiff | Compare changes between IFC models | LGPL-3.0-or-later | [](https://pypi.org/project/ifcdiff/) |
| ifcfm | Extract IFC data for FM handover requirements | LGPL-3.0-or-later | [](https://pypi.org/project/ifcfm/) |
| ifcmax | Historic extension for IFC support in 3DS Max | LGPL-3.0-or-later\* | [](https://docs.ifcopenshell.org/ifcmax.html)
-| ifcopenshell-python | Python library for IFC manipulation | LGPL-3.0-or-later\* | [](https://github.com/IfcOpenShell/IfcOpenShell/releases?q=ifcopenshell-python&expanded=true) [](https://pypi.org/project/ifcopenshell/) [](https://anaconda.org/conda-forge/ifcopenshell) [](https://anaconda.org/ifcopenshell/ifcopenshell) [](https://hub.docker.com/r/aecgeeks/ifcopenshell) [](https://aur.archlinux.org/packages/ifcopenshell) [](https://aur.archlinux.org/packages/ifcopenshell-git) |
+| ifcopenshell-python | Python library for IFC manipulation | LGPL-3.0-or-later\* | [](https://docs.ifcopenshell.org/ifcopenshell-python/installation.html) [](https://github.com/IfcOpenShell/IfcOpenShell/releases?q=ifcopenshell-python&expanded=true) [](https://pypi.org/project/ifcopenshell/) [](https://anaconda.org/conda-forge/ifcopenshell) [](https://anaconda.org/ifcopenshell/ifcopenshell) [](https://hub.docker.com/r/aecgeeks/ifcopenshell) [](https://aur.archlinux.org/packages/ifcopenshell) [](https://aur.archlinux.org/packages/ifcopenshell-git) |
| ifcpatch | Utility to run pre-packaged scripts to manipulate IFCs | LGPL-3.0-or-later | [](https://pypi.org/project/ifcpatch/) |
| ifcsverchok | Blender Add-on for visual node programming with IFC | GPL-3.0-or-later | [](https://github.com/IfcOpenShell/IfcOpenShell/releases?q=ifcsverchok&expanded=true)
| ifctester | Library, CLI and webapp for IDS model auditing | LGPL-3.0-or-later | [](https://pypi.org/project/ifctester/) |
diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt
index 382e7396b4..60294c2256 100644
--- a/cmake/CMakeLists.txt
+++ b/cmake/CMakeLists.txt
@@ -221,10 +221,11 @@ endif()
if(GLTF_SUPPORT OR CITYJSON_SUPPORT)
UNIFY_ENVVARS_AND_CACHE(JSON_INCLUDE_DIR)
- find_file(json_hpp "json.hpp" ${JSON_INCLUDE_DIR}/nlohmann)
+ find_path(json_header_path "json.hpp" ${JSON_INCLUDE_DIR} PATH_SUFFIXES "nlohmann")
+ set(JSON_INCLUDE_DIR ${json_header_path})
- if(json_hpp)
- message(STATUS "JSON for Modern C++ header file found")
+ if(json_header_path)
+ message(STATUS "JSON for Modern C++ header file found in ${JSON_INCLUDE_DIR}")
else()
message(FATAL_ERROR "Unable to find JSON for Modern C++ header file, aborting")
endif()
diff --git a/pyproject.toml b/pyproject.toml
index 518164504f..8e329ff191 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,5 +1,34 @@
[tool.black]
line-length = 120
+include = '''
+ src/(
+ bcf
+ |bcfserver
+ |blenderbim
+ |bsdd
+ |foundationserver
+ |ifc2ca
+ |ifc4d
+ |ifc5d
+ |ifcbimtester
+ |ifcblender
+ |ifccityjson
+ |ifcclash
+ |ifccsv
+ |ifcdiff
+ |ifcfm
+ |ifcpatch
+ |ifctester
+ |ifcopenshell-python
+ |ifcsverchok
+ |opencdeserver
+ )/.*.py$
+'''
+extend-exclude = '''
+ src/ifcopenshell-python/ifcopenshell/express/*
+ |src/ifcopenshell-python/ifcopenshell/mvd/*
+ |src/ifc2ca/templates/*
+'''
[tool.pyright]
reportInvalidTypeForm = false
diff --git a/src/bcf/Makefile b/src/bcf/Makefile
index daf7696155..ef03ba0d43 100644
--- a/src/bcf/Makefile
+++ b/src/bcf/Makefile
@@ -33,6 +33,10 @@ models:
cd src && xsdata generate -p bcf.v2.model --unnest-classes --kw-only --slots -ds Google bcf/v2/xsd
cd src && xsdata generate -p bcf.v3.model --unnest-classes --kw-only --slots -ds Google bcf/v3/xsd
+.PHONY: test
+test:
+ pytest -p no:pytest-blender tests
+
# .PHONY
# api:
# openapi-python-client generate --url https://api.swaggerhub.com/apis/buildingSMART/BCF/3.0
diff --git a/src/bcf/bcf/bcfxml.py b/src/bcf/bcf/bcfxml.py
index d54e7a1482..9aeb726c51 100644
--- a/src/bcf/bcf/bcfxml.py
+++ b/src/bcf/bcf/bcfxml.py
@@ -18,6 +18,7 @@ GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with BCF. If not, see .
"""
+
import zipfile
from pathlib import Path
from typing import Optional, Union
diff --git a/src/bcf/bcf/geometry.py b/src/bcf/bcf/geometry.py
index 92759f9b99..c32ae7619a 100644
--- a/src/bcf/bcf/geometry.py
+++ b/src/bcf/bcf/geometry.py
@@ -5,8 +5,8 @@ from numpy.typing import NDArray
def camera_vectors_from_element_placement(
- elem_placement: NDArray[np.float_],
-) -> tuple[NDArray[np.float_], NDArray[np.float_], NDArray[np.float_]]:
+ elem_placement: NDArray[np.float64],
+) -> tuple[NDArray[np.float64], NDArray[np.float64], NDArray[np.float64]]:
"""
Calculate the vectors of a camera pointing to an element.
@@ -21,8 +21,8 @@ def camera_vectors_from_element_placement(
def camera_vectors_from_target_position(
- target_position: NDArray[np.float_], offset: Optional[NDArray[np.float_]] = None
-) -> tuple[NDArray[np.float_], NDArray[np.float_], NDArray[np.float_]]:
+ target_position: NDArray[np.float64], offset: Optional[NDArray[np.float64]] = None
+) -> tuple[NDArray[np.float64], NDArray[np.float64], NDArray[np.float64]]:
"""
Calculate the vectors of a camera pointing to a target point.
@@ -50,7 +50,7 @@ def camera_vectors_from_target_position(
# return camera_position, -mat[:3, 2], mat[:3, 1]
-def unit_vector(v: NDArray[np.float_]) -> NDArray[np.float_]:
+def unit_vector(v: NDArray[np.float64]) -> NDArray[np.float64]:
"""
Return the unit vector of a vector.
diff --git a/src/bcf/bcf/inmemory_zipfile.py b/src/bcf/bcf/inmemory_zipfile.py
index c78e9f9a74..2a4d4117ce 100644
--- a/src/bcf/bcf/inmemory_zipfile.py
+++ b/src/bcf/bcf/inmemory_zipfile.py
@@ -5,6 +5,7 @@ Copyright (c) 2017-2020 Anthon van der Neut, Ruamel bvba
original idea from https://stackoverflow.com/a/19722365/1307905
"""
+
import zipfile
from io import BytesIO
from os import PathLike
@@ -13,8 +14,7 @@ from typing import Any, Optional, Protocol
class ZipFileInterface(Protocol):
- def writestr(self, filename_in_zip: str | zipfile.ZipInfo, file_contents: bytes | str) -> None:
- ...
+ def writestr(self, filename_in_zip: str | zipfile.ZipInfo, file_contents: bytes | str) -> None: ...
class InMemoryZipFile:
diff --git a/src/bcf/bcf/v2/bcfxml.py b/src/bcf/bcf/v2/bcfxml.py
index de71f65937..fe1d482d61 100644
--- a/src/bcf/bcf/v2/bcfxml.py
+++ b/src/bcf/bcf/v2/bcfxml.py
@@ -1,4 +1,5 @@
"""BCF XML V2 handler."""
+
import uuid
import warnings
import zipfile
diff --git a/src/bcf/bcf/v2/model/markup.py b/src/bcf/bcf/v2/model/markup.py
index 88ddd3e3a4..0b8fd987aa 100644
--- a/src/bcf/bcf/v2/model/markup.py
+++ b/src/bcf/bcf/v2/model/markup.py
@@ -34,7 +34,7 @@ class BimSnippet:
metadata={
"name": "isExternal",
"type": "Attribute",
- }
+ },
)
@@ -64,7 +64,7 @@ class HeaderFile:
"name": "Filename",
"type": "Element",
"namespace": "",
- }
+ },
)
date: Optional[XmlDateTime] = field(
default=None,
@@ -72,7 +72,7 @@ class HeaderFile:
"name": "Date",
"type": "Element",
"namespace": "",
- }
+ },
)
reference: Optional[str] = field(
default=None,
@@ -80,7 +80,7 @@ class HeaderFile:
"name": "Reference",
"type": "Element",
"namespace": "",
- }
+ },
)
ifc_project: Optional[str] = field(
default=None,
@@ -89,7 +89,7 @@ class HeaderFile:
"type": "Attribute",
"length": 22,
"pattern": r"[0-9,A-Z,a-z,_$]*",
- }
+ },
)
ifc_spatial_structure_element: Optional[str] = field(
default=None,
@@ -98,14 +98,14 @@ class HeaderFile:
"type": "Attribute",
"length": 22,
"pattern": r"[0-9,A-Z,a-z,_$]*",
- }
+ },
)
is_external: bool = field(
default=True,
metadata={
"name": "isExternal",
"type": "Attribute",
- }
+ },
)
@@ -120,7 +120,7 @@ class TopicDocumentReference:
"name": "ReferencedDocument",
"type": "Element",
"namespace": "",
- }
+ },
)
description: Optional[str] = field(
default=None,
@@ -128,7 +128,7 @@ class TopicDocumentReference:
"name": "Description",
"type": "Element",
"namespace": "",
- }
+ },
)
guid: Optional[str] = field(
default=None,
@@ -136,14 +136,14 @@ class TopicDocumentReference:
"name": "Guid",
"type": "Attribute",
"pattern": r"[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}",
- }
+ },
)
is_external: bool = field(
default=False,
metadata={
"name": "isExternal",
"type": "Attribute",
- }
+ },
)
@@ -170,7 +170,7 @@ class ViewPoint:
"name": "Viewpoint",
"type": "Element",
"namespace": "",
- }
+ },
)
snapshot: Optional[str] = field(
default=None,
@@ -178,7 +178,7 @@ class ViewPoint:
"name": "Snapshot",
"type": "Element",
"namespace": "",
- }
+ },
)
index: Optional[int] = field(
default=None,
@@ -186,7 +186,7 @@ class ViewPoint:
"name": "Index",
"type": "Element",
"namespace": "",
- }
+ },
)
guid: str = field(
metadata={
@@ -230,7 +230,7 @@ class Comment:
"name": "Viewpoint",
"type": "Element",
"namespace": "",
- }
+ },
)
modified_date: Optional[XmlDateTime] = field(
default=None,
@@ -238,7 +238,7 @@ class Comment:
"name": "ModifiedDate",
"type": "Element",
"namespace": "",
- }
+ },
)
modified_author: Optional[str] = field(
default=None,
@@ -246,7 +246,7 @@ class Comment:
"name": "ModifiedAuthor",
"type": "Element",
"namespace": "",
- }
+ },
)
guid: str = field(
metadata={
@@ -267,7 +267,7 @@ class Header:
"type": "Element",
"namespace": "",
"min_occurs": 1,
- }
+ },
)
@@ -279,7 +279,7 @@ class Topic:
"name": "ReferenceLink",
"type": "Element",
"namespace": "",
- }
+ },
)
title: str = field(
metadata={
@@ -295,7 +295,7 @@ class Topic:
"name": "Priority",
"type": "Element",
"namespace": "",
- }
+ },
)
index: Optional[int] = field(
default=None,
@@ -303,7 +303,7 @@ class Topic:
"name": "Index",
"type": "Element",
"namespace": "",
- }
+ },
)
labels: List[str] = field(
default_factory=list,
@@ -311,7 +311,7 @@ class Topic:
"name": "Labels",
"type": "Element",
"namespace": "",
- }
+ },
)
creation_date: XmlDateTime = field(
metadata={
@@ -335,7 +335,7 @@ class Topic:
"name": "ModifiedDate",
"type": "Element",
"namespace": "",
- }
+ },
)
modified_author: Optional[str] = field(
default=None,
@@ -343,7 +343,7 @@ class Topic:
"name": "ModifiedAuthor",
"type": "Element",
"namespace": "",
- }
+ },
)
due_date: Optional[XmlDateTime] = field(
default=None,
@@ -351,7 +351,7 @@ class Topic:
"name": "DueDate",
"type": "Element",
"namespace": "",
- }
+ },
)
assigned_to: Optional[str] = field(
default=None,
@@ -359,7 +359,7 @@ class Topic:
"name": "AssignedTo",
"type": "Element",
"namespace": "",
- }
+ },
)
stage: Optional[str] = field(
default=None,
@@ -367,7 +367,7 @@ class Topic:
"name": "Stage",
"type": "Element",
"namespace": "",
- }
+ },
)
description: Optional[str] = field(
default=None,
@@ -375,7 +375,7 @@ class Topic:
"name": "Description",
"type": "Element",
"namespace": "",
- }
+ },
)
bim_snippet: Optional[BimSnippet] = field(
default=None,
@@ -383,7 +383,7 @@ class Topic:
"name": "BimSnippet",
"type": "Element",
"namespace": "",
- }
+ },
)
document_reference: List[TopicDocumentReference] = field(
default_factory=list,
@@ -391,7 +391,7 @@ class Topic:
"name": "DocumentReference",
"type": "Element",
"namespace": "",
- }
+ },
)
related_topic: List[TopicRelatedTopic] = field(
default_factory=list,
@@ -399,7 +399,7 @@ class Topic:
"name": "RelatedTopic",
"type": "Element",
"namespace": "",
- }
+ },
)
guid: str = field(
metadata={
@@ -414,14 +414,14 @@ class Topic:
metadata={
"name": "TopicType",
"type": "Attribute",
- }
+ },
)
topic_status: Optional[str] = field(
default=None,
metadata={
"name": "TopicStatus",
"type": "Attribute",
- }
+ },
)
@@ -433,7 +433,7 @@ class Markup:
"name": "Header",
"type": "Element",
"namespace": "",
- }
+ },
)
topic: Topic = field(
metadata={
@@ -449,7 +449,7 @@ class Markup:
"name": "Comment",
"type": "Element",
"namespace": "",
- }
+ },
)
viewpoints: List[ViewPoint] = field(
default_factory=list,
@@ -457,5 +457,5 @@ class Markup:
"name": "Viewpoints",
"type": "Element",
"namespace": "",
- }
+ },
)
diff --git a/src/bcf/bcf/v2/model/project.py b/src/bcf/bcf/v2/model/project.py
index fea44c6f50..e86fb9b009 100644
--- a/src/bcf/bcf/v2/model/project.py
+++ b/src/bcf/bcf/v2/model/project.py
@@ -10,7 +10,7 @@ class Project:
"name": "Name",
"type": "Element",
"namespace": "",
- }
+ },
)
project_id: str = field(
metadata={
@@ -29,7 +29,7 @@ class ProjectExtension:
"name": "Project",
"type": "Element",
"namespace": "",
- }
+ },
)
extension_schema: str = field(
metadata={
diff --git a/src/bcf/bcf/v2/model/version.py b/src/bcf/bcf/v2/model/version.py
index 777572c6ae..9f55ad5bf9 100644
--- a/src/bcf/bcf/v2/model/version.py
+++ b/src/bcf/bcf/v2/model/version.py
@@ -10,12 +10,12 @@ class Version:
"name": "DetailedVersion",
"type": "Element",
"namespace": "",
- }
+ },
)
version_id: Optional[str] = field(
default=None,
metadata={
"name": "VersionId",
"type": "Attribute",
- }
+ },
)
diff --git a/src/bcf/bcf/v2/model/visinfo.py b/src/bcf/bcf/v2/model/visinfo.py
index f9976e1c78..e1f13d3a37 100644
--- a/src/bcf/bcf/v2/model/visinfo.py
+++ b/src/bcf/bcf/v2/model/visinfo.py
@@ -15,14 +15,14 @@ class Component:
metadata={
"name": "OriginatingSystem",
"type": "Element",
- }
+ },
)
authoring_tool_id: Optional[str] = field(
default=None,
metadata={
"name": "AuthoringToolId",
"type": "Element",
- }
+ },
)
ifc_guid: Optional[str] = field(
default=None,
@@ -31,7 +31,7 @@ class Component:
"type": "Attribute",
"length": 22,
"pattern": r"[0-9,A-Z,a-z,_$]*",
- }
+ },
)
@@ -92,21 +92,21 @@ class ViewSetupHints:
metadata={
"name": "SpacesVisible",
"type": "Attribute",
- }
+ },
)
space_boundaries_visible: Optional[bool] = field(
default=None,
metadata={
"name": "SpaceBoundariesVisible",
"type": "Attribute",
- }
+ },
)
openings_visible: Optional[bool] = field(
default=None,
metadata={
"name": "OpeningsVisible",
"type": "Attribute",
- }
+ },
)
@@ -139,7 +139,7 @@ class ComponentColoringColor:
"name": "Component",
"type": "Element",
"min_occurs": 1,
- }
+ },
)
color: Optional[str] = field(
default=None,
@@ -147,7 +147,7 @@ class ComponentColoringColor:
"name": "Color",
"type": "Attribute",
"pattern": r"[0-9,a-f,A-F]{6}([0-9,a-f,A-F]{2})?",
- }
+ },
)
@@ -159,7 +159,7 @@ class ComponentSelection:
"name": "Component",
"type": "Element",
"min_occurs": 1,
- }
+ },
)
@@ -174,7 +174,7 @@ class ComponentVisibilityExceptions:
"name": "Component",
"type": "Element",
"min_occurs": 1,
- }
+ },
)
@@ -205,6 +205,7 @@ class OrthogonalCamera:
camera_up_vector:
view_to_world_scale: view's visible size in meters
"""
+
camera_view_point: Point = field(
metadata={
"name": "CameraViewPoint",
@@ -247,6 +248,7 @@ class PerspectiveCamera:
release and viewers should be expect values outside this
range in current implementations.
"""
+
camera_view_point: Point = field(
metadata={
"name": "CameraViewPoint",
@@ -336,7 +338,7 @@ class ComponentColoring:
"name": "Color",
"type": "Element",
"min_occurs": 1,
- }
+ },
)
@@ -347,14 +349,14 @@ class ComponentVisibility:
metadata={
"name": "Exceptions",
"type": "Element",
- }
+ },
)
default_visibility: Optional[bool] = field(
default=None,
metadata={
"name": "DefaultVisibility",
"type": "Attribute",
- }
+ },
)
@@ -368,7 +370,7 @@ class VisualizationInfoClippingPlanes:
metadata={
"name": "ClippingPlane",
"type": "Element",
- }
+ },
)
@@ -383,7 +385,7 @@ class VisualizationInfoLines:
"name": "Line",
"type": "Element",
"min_occurs": 1,
- }
+ },
)
@@ -394,14 +396,14 @@ class Components:
metadata={
"name": "ViewSetupHints",
"type": "Element",
- }
+ },
)
selection: Optional[ComponentSelection] = field(
default=None,
metadata={
"name": "Selection",
"type": "Element",
- }
+ },
)
visibility: ComponentVisibility = field(
metadata={
@@ -415,7 +417,7 @@ class Components:
metadata={
"name": "Coloring",
"type": "Element",
- }
+ },
)
@@ -424,47 +426,48 @@ class VisualizationInfo:
"""
VisualizationInfo documentation.
"""
+
components: Optional[Components] = field(
default=None,
metadata={
"name": "Components",
"type": "Element",
- }
+ },
)
orthogonal_camera: Optional[OrthogonalCamera] = field(
default=None,
metadata={
"name": "OrthogonalCamera",
"type": "Element",
- }
+ },
)
perspective_camera: Optional[PerspectiveCamera] = field(
default=None,
metadata={
"name": "PerspectiveCamera",
"type": "Element",
- }
+ },
)
lines: Optional[VisualizationInfoLines] = field(
default=None,
metadata={
"name": "Lines",
"type": "Element",
- }
+ },
)
clipping_planes: Optional[VisualizationInfoClippingPlanes] = field(
default=None,
metadata={
"name": "ClippingPlanes",
"type": "Element",
- }
+ },
)
bitmap: List[VisualizationInfoBitmap] = field(
default_factory=list,
metadata={
"name": "Bitmap",
"type": "Element",
- }
+ },
)
guid: str = field(
metadata={
diff --git a/src/bcf/bcf/v2/topic.py b/src/bcf/bcf/v2/topic.py
index c1188c9a06..82f09c54a4 100644
--- a/src/bcf/bcf/v2/topic.py
+++ b/src/bcf/bcf/v2/topic.py
@@ -1,4 +1,5 @@
"""BCF XML V2 Topic handler."""
+
import datetime
import tempfile
import uuid
@@ -277,7 +278,7 @@ class TopicHandler:
self.add_visinfo_handler(new_viewpoint)
return new_viewpoint
- def add_viewpoint_from_point_and_guids(self, position: NDArray[np.float_], *guids: str) -> None:
+ def add_viewpoint_from_point_and_guids(self, position: NDArray[np.float64], *guids: str) -> None:
"""Add a viewpoint pointing at an XYZ point in space
Args:
diff --git a/src/bcf/bcf/v2/visinfo.py b/src/bcf/bcf/v2/visinfo.py
index 7ac1a750d8..08694b8111 100644
--- a/src/bcf/bcf/v2/visinfo.py
+++ b/src/bcf/bcf/v2/visinfo.py
@@ -176,7 +176,7 @@ class VisualizationInfoHandler:
@classmethod
def create_from_point_and_guids(
cls,
- position: NDArray[np.float_],
+ position: NDArray[np.float64],
*guids: str,
xml_handler: Optional[AbstractXmlParserSerializer] = None,
) -> "VisualizationInfoHandler":
@@ -224,7 +224,7 @@ def build_viewpoint(element: entity_instance) -> mdl.VisualizationInfo:
)
-def build_viewpoint_from_position_and_guids(position: NDArray[np.float_], *guids: str) -> mdl.VisualizationInfo:
+def build_viewpoint_from_position_and_guids(position: NDArray[np.float64], *guids: str) -> mdl.VisualizationInfo:
"""
Return a BCF viewpoint of an IFC element.
@@ -261,7 +261,7 @@ def build_components(*guids: str) -> mdl.Components:
)
-def build_camera(elem_placement: NDArray[np.float_]) -> mdl.PerspectiveCamera:
+def build_camera(elem_placement: NDArray[np.float64]) -> mdl.PerspectiveCamera:
"""
Return a BCF camera for an IFC element placement matrix.
@@ -275,7 +275,7 @@ def build_camera(elem_placement: NDArray[np.float_]) -> mdl.PerspectiveCamera:
def build_camera_from_vectors(
- camera_position: NDArray[np.float_], camera_dir: NDArray[np.float_], camera_up: NDArray[np.float_]
+ camera_position: NDArray[np.float64], camera_dir: NDArray[np.float64], camera_up: NDArray[np.float64]
) -> mdl.PerspectiveCamera:
"""
Return a BCF camera for an IFC element placement matrix.
diff --git a/src/bcf/bcf/v3/bcfxml.py b/src/bcf/bcf/v3/bcfxml.py
index 481a7557fa..3318264670 100644
--- a/src/bcf/bcf/v3/bcfxml.py
+++ b/src/bcf/bcf/v3/bcfxml.py
@@ -1,4 +1,5 @@
"""BCF XML V3 handlers."""
+
import uuid
import warnings
import zipfile
diff --git a/src/bcf/bcf/v3/document.py b/src/bcf/bcf/v3/document.py
index 56a15da42d..afc6be50b9 100644
--- a/src/bcf/bcf/v3/document.py
+++ b/src/bcf/bcf/v3/document.py
@@ -1,4 +1,5 @@
"""BCF XML V3 Documents handler."""
+
import zipfile
from typing import Any, Optional
diff --git a/src/bcf/bcf/v3/model/documents.py b/src/bcf/bcf/v3/model/documents.py
index c9a1b43c9c..1b18758d0e 100644
--- a/src/bcf/bcf/v3/model/documents.py
+++ b/src/bcf/bcf/v3/model/documents.py
@@ -22,7 +22,7 @@ class Document:
"namespace": "",
"min_length": 1,
"white_space": "collapse",
- }
+ },
)
guid: str = field(
metadata={
@@ -45,7 +45,7 @@ class DocumentInfoDocuments:
"name": "Document",
"type": "Element",
"namespace": "",
- }
+ },
)
@@ -57,5 +57,5 @@ class DocumentInfo:
"name": "Documents",
"type": "Element",
"namespace": "",
- }
+ },
)
diff --git a/src/bcf/bcf/v3/model/extensions.py b/src/bcf/bcf/v3/model/extensions.py
index cb0af500f6..c9c47495ce 100644
--- a/src/bcf/bcf/v3/model/extensions.py
+++ b/src/bcf/bcf/v3/model/extensions.py
@@ -15,7 +15,7 @@ class ExtensionsPriorities:
"namespace": "",
"min_length": 1,
"white_space": "collapse",
- }
+ },
)
@@ -32,7 +32,7 @@ class ExtensionsSnippetTypes:
"namespace": "",
"min_length": 1,
"white_space": "collapse",
- }
+ },
)
@@ -49,7 +49,7 @@ class ExtensionsStages:
"namespace": "",
"min_length": 1,
"white_space": "collapse",
- }
+ },
)
@@ -66,7 +66,7 @@ class ExtensionsTopicLabels:
"namespace": "",
"min_length": 1,
"white_space": "collapse",
- }
+ },
)
@@ -83,7 +83,7 @@ class ExtensionsTopicStatuses:
"namespace": "",
"min_length": 1,
"white_space": "collapse",
- }
+ },
)
@@ -100,7 +100,7 @@ class ExtensionsTopicTypes:
"namespace": "",
"min_length": 1,
"white_space": "collapse",
- }
+ },
)
@@ -117,7 +117,7 @@ class ExtensionsUsers:
"namespace": "",
"min_length": 1,
"white_space": "collapse",
- }
+ },
)
@@ -129,7 +129,7 @@ class Extensions:
"name": "TopicTypes",
"type": "Element",
"namespace": "",
- }
+ },
)
topic_statuses: Optional[ExtensionsTopicStatuses] = field(
default=None,
@@ -137,7 +137,7 @@ class Extensions:
"name": "TopicStatuses",
"type": "Element",
"namespace": "",
- }
+ },
)
priorities: Optional[ExtensionsPriorities] = field(
default=None,
@@ -145,7 +145,7 @@ class Extensions:
"name": "Priorities",
"type": "Element",
"namespace": "",
- }
+ },
)
topic_labels: Optional[ExtensionsTopicLabels] = field(
default=None,
@@ -153,7 +153,7 @@ class Extensions:
"name": "TopicLabels",
"type": "Element",
"namespace": "",
- }
+ },
)
users: Optional[ExtensionsUsers] = field(
default=None,
@@ -161,7 +161,7 @@ class Extensions:
"name": "Users",
"type": "Element",
"namespace": "",
- }
+ },
)
snippet_types: Optional[ExtensionsSnippetTypes] = field(
default=None,
@@ -169,7 +169,7 @@ class Extensions:
"name": "SnippetTypes",
"type": "Element",
"namespace": "",
- }
+ },
)
stages: Optional[ExtensionsStages] = field(
default=None,
@@ -177,5 +177,5 @@ class Extensions:
"name": "Stages",
"type": "Element",
"namespace": "",
- }
+ },
)
diff --git a/src/bcf/bcf/v3/model/markup.py b/src/bcf/bcf/v3/model/markup.py
index f212b9fc7e..4121b04abe 100644
--- a/src/bcf/bcf/v3/model/markup.py
+++ b/src/bcf/bcf/v3/model/markup.py
@@ -40,7 +40,7 @@ class BimSnippet:
metadata={
"name": "IsExternal",
"type": "Attribute",
- }
+ },
)
@@ -68,7 +68,7 @@ class DocumentReference:
"type": "Element",
"namespace": "",
"pattern": r"[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}",
- }
+ },
)
url: Optional[str] = field(
default=None,
@@ -78,7 +78,7 @@ class DocumentReference:
"namespace": "",
"min_length": 1,
"white_space": "collapse",
- }
+ },
)
description: Optional[str] = field(
default=None,
@@ -88,7 +88,7 @@ class DocumentReference:
"namespace": "",
"min_length": 1,
"white_space": "collapse",
- }
+ },
)
guid: str = field(
metadata={
@@ -110,7 +110,7 @@ class File:
"namespace": "",
"min_length": 1,
"white_space": "collapse",
- }
+ },
)
date: Optional[XmlDateTime] = field(
default=None,
@@ -118,7 +118,7 @@ class File:
"name": "Date",
"type": "Element",
"namespace": "",
- }
+ },
)
reference: Optional[str] = field(
default=None,
@@ -128,7 +128,7 @@ class File:
"namespace": "",
"min_length": 1,
"white_space": "collapse",
- }
+ },
)
ifc_project: Optional[str] = field(
default=None,
@@ -137,7 +137,7 @@ class File:
"type": "Attribute",
"length": 22,
"pattern": r"[0-9A-Za-z_$]*",
- }
+ },
)
ifc_spatial_structure_element: Optional[str] = field(
default=None,
@@ -146,14 +146,14 @@ class File:
"type": "Attribute",
"length": 22,
"pattern": r"[0-9A-Za-z_$]*",
- }
+ },
)
is_external: bool = field(
default=True,
metadata={
"name": "IsExternal",
"type": "Attribute",
- }
+ },
)
@@ -170,7 +170,7 @@ class TopicLabels:
"namespace": "",
"min_length": 1,
"white_space": "collapse",
- }
+ },
)
@@ -187,7 +187,7 @@ class TopicReferenceLinks:
"namespace": "",
"min_length": 1,
"white_space": "collapse",
- }
+ },
)
@@ -216,7 +216,7 @@ class ViewPoint:
"namespace": "",
"min_length": 1,
"white_space": "collapse",
- }
+ },
)
snapshot: Optional[str] = field(
default=None,
@@ -226,7 +226,7 @@ class ViewPoint:
"namespace": "",
"min_length": 1,
"white_space": "collapse",
- }
+ },
)
index: Optional[int] = field(
default=None,
@@ -234,7 +234,7 @@ class ViewPoint:
"name": "Index",
"type": "Element",
"namespace": "",
- }
+ },
)
guid: str = field(
metadata={
@@ -274,7 +274,7 @@ class Comment:
"namespace": "",
"min_length": 1,
"white_space": "collapse",
- }
+ },
)
viewpoint: Optional[CommentViewpoint] = field(
default=None,
@@ -282,7 +282,7 @@ class Comment:
"name": "Viewpoint",
"type": "Element",
"namespace": "",
- }
+ },
)
modified_date: Optional[XmlDateTime] = field(
default=None,
@@ -290,7 +290,7 @@ class Comment:
"name": "ModifiedDate",
"type": "Element",
"namespace": "",
- }
+ },
)
modified_author: Optional[str] = field(
default=None,
@@ -300,7 +300,7 @@ class Comment:
"namespace": "",
"min_length": 1,
"white_space": "collapse",
- }
+ },
)
guid: str = field(
metadata={
@@ -323,7 +323,7 @@ class HeaderFiles:
"name": "File",
"type": "Element",
"namespace": "",
- }
+ },
)
@@ -338,7 +338,7 @@ class TopicDocumentReferences:
"name": "DocumentReference",
"type": "Element",
"namespace": "",
- }
+ },
)
@@ -353,7 +353,7 @@ class TopicRelatedTopics:
"name": "RelatedTopic",
"type": "Element",
"namespace": "",
- }
+ },
)
@@ -368,7 +368,7 @@ class TopicViewpoints:
"name": "ViewPoint",
"type": "Element",
"namespace": "",
- }
+ },
)
@@ -380,7 +380,7 @@ class Header:
"name": "Files",
"type": "Element",
"namespace": "",
- }
+ },
)
@@ -395,7 +395,7 @@ class TopicComments:
"name": "Comment",
"type": "Element",
"namespace": "",
- }
+ },
)
@@ -407,7 +407,7 @@ class Topic:
"name": "ReferenceLinks",
"type": "Element",
"namespace": "",
- }
+ },
)
title: str = field(
metadata={
@@ -427,7 +427,7 @@ class Topic:
"namespace": "",
"min_length": 1,
"white_space": "collapse",
- }
+ },
)
index: Optional[int] = field(
default=None,
@@ -435,7 +435,7 @@ class Topic:
"name": "Index",
"type": "Element",
"namespace": "",
- }
+ },
)
labels: Optional[TopicLabels] = field(
default=None,
@@ -443,7 +443,7 @@ class Topic:
"name": "Labels",
"type": "Element",
"namespace": "",
- }
+ },
)
creation_date: XmlDateTime = field(
metadata={
@@ -469,7 +469,7 @@ class Topic:
"name": "ModifiedDate",
"type": "Element",
"namespace": "",
- }
+ },
)
modified_author: Optional[str] = field(
default=None,
@@ -479,7 +479,7 @@ class Topic:
"namespace": "",
"min_length": 1,
"white_space": "collapse",
- }
+ },
)
due_date: Optional[XmlDateTime] = field(
default=None,
@@ -487,7 +487,7 @@ class Topic:
"name": "DueDate",
"type": "Element",
"namespace": "",
- }
+ },
)
assigned_to: Optional[str] = field(
default=None,
@@ -497,7 +497,7 @@ class Topic:
"namespace": "",
"min_length": 1,
"white_space": "collapse",
- }
+ },
)
stage: Optional[str] = field(
default=None,
@@ -507,7 +507,7 @@ class Topic:
"namespace": "",
"min_length": 1,
"white_space": "collapse",
- }
+ },
)
description: Optional[str] = field(
default=None,
@@ -517,7 +517,7 @@ class Topic:
"namespace": "",
"min_length": 1,
"white_space": "collapse",
- }
+ },
)
bim_snippet: Optional[BimSnippet] = field(
default=None,
@@ -525,7 +525,7 @@ class Topic:
"name": "BimSnippet",
"type": "Element",
"namespace": "",
- }
+ },
)
document_references: Optional[TopicDocumentReferences] = field(
default=None,
@@ -533,7 +533,7 @@ class Topic:
"name": "DocumentReferences",
"type": "Element",
"namespace": "",
- }
+ },
)
related_topics: Optional[TopicRelatedTopics] = field(
default=None,
@@ -541,7 +541,7 @@ class Topic:
"name": "RelatedTopics",
"type": "Element",
"namespace": "",
- }
+ },
)
comments: Optional[TopicComments] = field(
default=None,
@@ -549,7 +549,7 @@ class Topic:
"name": "Comments",
"type": "Element",
"namespace": "",
- }
+ },
)
viewpoints: Optional[TopicViewpoints] = field(
default=None,
@@ -557,7 +557,7 @@ class Topic:
"name": "Viewpoints",
"type": "Element",
"namespace": "",
- }
+ },
)
guid: str = field(
metadata={
@@ -574,7 +574,7 @@ class Topic:
"type": "Attribute",
"min_length": 1,
"white_space": "collapse",
- }
+ },
)
topic_type: str = field(
metadata={
@@ -604,7 +604,7 @@ class Markup:
"name": "Header",
"type": "Element",
"namespace": "",
- }
+ },
)
topic: Topic = field(
metadata={
diff --git a/src/bcf/bcf/v3/model/project.py b/src/bcf/bcf/v3/model/project.py
index b6962213d6..76a6922925 100644
--- a/src/bcf/bcf/v3/model/project.py
+++ b/src/bcf/bcf/v3/model/project.py
@@ -12,7 +12,7 @@ class Project:
"namespace": "",
"min_length": 1,
"white_space": "collapse",
- }
+ },
)
project_id: str = field(
metadata={
diff --git a/src/bcf/bcf/v3/model/visinfo.py b/src/bcf/bcf/v3/model/visinfo.py
index fa541945ea..1a1dcb72c5 100644
--- a/src/bcf/bcf/v3/model/visinfo.py
+++ b/src/bcf/bcf/v3/model/visinfo.py
@@ -17,7 +17,7 @@ class Component:
"type": "Element",
"min_length": 1,
"white_space": "collapse",
- }
+ },
)
authoring_tool_id: Optional[str] = field(
default=None,
@@ -26,7 +26,7 @@ class Component:
"type": "Element",
"min_length": 1,
"white_space": "collapse",
- }
+ },
)
ifc_guid: Optional[str] = field(
default=None,
@@ -35,7 +35,7 @@ class Component:
"type": "Attribute",
"length": 22,
"pattern": r"[0-9A-Za-z_$]*",
- }
+ },
)
@@ -96,21 +96,21 @@ class ViewSetupHints:
metadata={
"name": "SpacesVisible",
"type": "Attribute",
- }
+ },
)
space_boundaries_visible: bool = field(
default=False,
metadata={
"name": "SpaceBoundariesVisible",
"type": "Attribute",
- }
+ },
)
openings_visible: bool = field(
default=False,
metadata={
"name": "OpeningsVisible",
"type": "Attribute",
- }
+ },
)
@@ -191,7 +191,7 @@ class ComponentColoringColorComponents:
"name": "Component",
"type": "Element",
"min_occurs": 1,
- }
+ },
)
@@ -202,7 +202,7 @@ class ComponentSelection:
metadata={
"name": "Component",
"type": "Element",
- }
+ },
)
@@ -216,7 +216,7 @@ class ComponentVisibilityExceptions:
metadata={
"name": "Component",
"type": "Element",
- }
+ },
)
@@ -249,6 +249,7 @@ class OrthogonalCamera:
aspect_ratio: Proportional relationship between the width and
the height of the view (w/h).
"""
+
camera_view_point: Point = field(
metadata={
"name": "CameraViewPoint",
@@ -302,6 +303,7 @@ class PerspectiveCamera:
aspect_ratio: Proportional relationship between the width and
the height of the view (w/h).
"""
+
camera_view_point: Point = field(
metadata={
"name": "CameraViewPoint",
@@ -371,21 +373,21 @@ class ComponentVisibility:
metadata={
"name": "ViewSetupHints",
"type": "Element",
- }
+ },
)
exceptions: Optional[ComponentVisibilityExceptions] = field(
default=None,
metadata={
"name": "Exceptions",
"type": "Element",
- }
+ },
)
default_visibility: bool = field(
default=False,
metadata={
"name": "DefaultVisibility",
"type": "Attribute",
- }
+ },
)
@@ -399,7 +401,7 @@ class VisualizationInfoBitmaps:
metadata={
"name": "Bitmap",
"type": "Element",
- }
+ },
)
@@ -413,7 +415,7 @@ class VisualizationInfoClippingPlanes:
metadata={
"name": "ClippingPlane",
"type": "Element",
- }
+ },
)
@@ -427,7 +429,7 @@ class VisualizationInfoLines:
metadata={
"name": "Line",
"type": "Element",
- }
+ },
)
@@ -438,7 +440,7 @@ class ComponentColoring:
metadata={
"name": "Color",
"type": "Element",
- }
+ },
)
@@ -449,21 +451,21 @@ class Components:
metadata={
"name": "Selection",
"type": "Element",
- }
+ },
)
visibility: Optional[ComponentVisibility] = field(
default=None,
metadata={
"name": "Visibility",
"type": "Element",
- }
+ },
)
coloring: Optional[ComponentColoring] = field(
default=None,
metadata={
"name": "Coloring",
"type": "Element",
- }
+ },
)
@@ -472,47 +474,48 @@ class VisualizationInfo:
"""
VisualizationInfo documentation.
"""
+
components: Optional[Components] = field(
default=None,
metadata={
"name": "Components",
"type": "Element",
- }
+ },
)
orthogonal_camera: Optional[OrthogonalCamera] = field(
default=None,
metadata={
"name": "OrthogonalCamera",
"type": "Element",
- }
+ },
)
perspective_camera: Optional[PerspectiveCamera] = field(
default=None,
metadata={
"name": "PerspectiveCamera",
"type": "Element",
- }
+ },
)
lines: Optional[VisualizationInfoLines] = field(
default=None,
metadata={
"name": "Lines",
"type": "Element",
- }
+ },
)
clipping_planes: Optional[VisualizationInfoClippingPlanes] = field(
default=None,
metadata={
"name": "ClippingPlanes",
"type": "Element",
- }
+ },
)
bitmaps: Optional[VisualizationInfoBitmaps] = field(
default=None,
metadata={
"name": "Bitmaps",
"type": "Element",
- }
+ },
)
guid: str = field(
metadata={
diff --git a/src/bcf/bcf/v3/topic.py b/src/bcf/bcf/v3/topic.py
index 71550505ca..44109a21db 100644
--- a/src/bcf/bcf/v3/topic.py
+++ b/src/bcf/bcf/v3/topic.py
@@ -1,4 +1,5 @@
"""BCF XML V3 Topic handler."""
+
import datetime
import uuid
import zipfile
@@ -174,7 +175,7 @@ class TopicHandler:
new_viewpoint = VisualizationInfoHandler.create_new(element, self._xml_handler)
self.add_visinfo_handler(new_viewpoint)
- def add_viewpoint_from_point_and_guids(self, position: NDArray[np.float_], *guids: str) -> None:
+ def add_viewpoint_from_point_and_guids(self, position: NDArray[np.float64], *guids: str) -> None:
"""
Add a viewpoint tergeting an IFC element to the topic.
diff --git a/src/bcf/bcf/v3/visinfo.py b/src/bcf/bcf/v3/visinfo.py
index 56c1692206..f2666288d9 100644
--- a/src/bcf/bcf/v3/visinfo.py
+++ b/src/bcf/bcf/v3/visinfo.py
@@ -175,7 +175,7 @@ class VisualizationInfoHandler:
@classmethod
def create_from_point_and_guids(
cls,
- position: NDArray[np.float_],
+ position: NDArray[np.float64],
*guids: str,
xml_handler: Optional[AbstractXmlParserSerializer] = None,
) -> "VisualizationInfoHandler":
@@ -218,7 +218,7 @@ def build_viewpoint(element: entity_instance) -> mdl.VisualizationInfo:
)
-def build_viewpoint_from_position_and_guids(position: NDArray[np.float_], *guids: str) -> mdl.VisualizationInfo:
+def build_viewpoint_from_position_and_guids(position: NDArray[np.float64], *guids: str) -> mdl.VisualizationInfo:
"""
Return a BCF viewpoint of an IFC element.
@@ -255,7 +255,7 @@ def build_components(*guids: str) -> mdl.Components:
)
-def build_camera(elem_placement: NDArray[np.float_]) -> mdl.PerspectiveCamera:
+def build_camera(elem_placement: NDArray[np.float64]) -> mdl.PerspectiveCamera:
"""
Return a BCF camera for an IFC element placement matrix.
@@ -269,7 +269,7 @@ def build_camera(elem_placement: NDArray[np.float_]) -> mdl.PerspectiveCamera:
def build_camera_from_vectors(
- camera_position: NDArray[np.float_], camera_dir: NDArray[np.float_], camera_up: NDArray[np.float_]
+ camera_position: NDArray[np.float64], camera_dir: NDArray[np.float64], camera_up: NDArray[np.float64]
) -> mdl.PerspectiveCamera:
"""
Return a BCF camera for an IFC element placement matrix.
diff --git a/src/bcf/bcf/xml_parser.py b/src/bcf/bcf/xml_parser.py
index b3b51367e0..a5dbd3b71c 100644
--- a/src/bcf/bcf/xml_parser.py
+++ b/src/bcf/bcf/xml_parser.py
@@ -1,4 +1,5 @@
"""XML Parser and Serializer factories."""
+
from typing import Optional, Protocol, Type, TypeVar
from xsdata.formats.dataclass.context import XmlContext
diff --git a/src/bcf/tests/v2/test_bcf_xml.py b/src/bcf/tests/v2/test_bcf_xml.py
index 26446ee0c3..fed1428e73 100644
--- a/src/bcf/tests/v2/test_bcf_xml.py
+++ b/src/bcf/tests/v2/test_bcf_xml.py
@@ -1,4 +1,5 @@
"""BCF XML tests."""
+
import uuid
from pathlib import Path
from tempfile import TemporaryDirectory
diff --git a/src/bcf/tests/v3/test_bcf_xml.py b/src/bcf/tests/v3/test_bcf_xml.py
index 133dd66419..50664b98c7 100644
--- a/src/bcf/tests/v3/test_bcf_xml.py
+++ b/src/bcf/tests/v3/test_bcf_xml.py
@@ -1,4 +1,5 @@
"""BCF XML tests."""
+
import uuid
from pathlib import Path
from tempfile import TemporaryDirectory
diff --git a/src/blenderbim/Makefile b/src/blenderbim/Makefile
index f1e4f1a01f..1603e887b5 100644
--- a/src/blenderbim/Makefile
+++ b/src/blenderbim/Makefile
@@ -91,12 +91,11 @@ BLENDER_PLATFORM:=windows-x64
endif
# Current build commit hash.
-OLD:=c18e4ea
+OLD:=d51fa2c
.PHONY: bump
bump:
cd . && $(SED) -b "s/$(OLD)/$(NEW)/" Makefile
cd ../ifcopenshell-python/ && $(SED) -b "s/$(OLD)/$(NEW)/" Makefile
- cd ../ifcopenshell-python/docs/ifcconvert/ && $(SED) -b "s/$(OLD)/$(NEW)/" installation.rst
.PHONY: dist
dist:
@@ -196,19 +195,20 @@ endif
cd build/blenderbim/bim/data/gantt/ && wget https://raw.githubusercontent.com/jsGanttImproved/jsgantt-improved/master/dist/jsgantt.css
# Provides IFCJSON functionality
- cd build && wget https://github.com/IFCJSON-Team/IFC2JSON_python/archive/master.zip
- cd build && unzip master.zip && rm master.zip
+ # TODO: replace with main repo if https://github.com/IFCJSON-Team/IFC2JSON_python/pull/3 is merged.
+ cd build && wget -O ifc2json.zip https://github.com/Moult/IFC2JSON_python/archive/refs/heads/feature-ios-v0.8.0.zip
+ cd build && unzip ifc2json.zip && rm ifc2json.zip
# IFCJSON doesn't have pyproject.toml, so we use python command.
- cd build && . env/$(VENV_ACTIVATE) && cd IFC2JSON_python-master/file_converters && \
+ cd build && . env/$(VENV_ACTIVATE) && cd IFC2JSON_python-*/file_converters && \
$(PYTHON) -c "from setuptools import setup; \
setup( \
name='ifcjson', \
- version='0.0.0', \
+ version='0.0.1', \
author='Jan Brouwer', \
author_email='jan@brewsky.nl', \
packages=['ifcjson'], \
)" bdist_wheel
- cp -r build/IFC2JSON_python-master/file_converters/dist/*.whl build/wheels/
+ cp -r build/IFC2JSON_python-*/file_converters/dist/*.whl build/wheels/
# Brickschema requires pkg_resources which is provided by Blender.
# Provides Brickschema functionality
diff --git a/src/blenderbim/blenderbim/bim/__init__.py b/src/blenderbim/blenderbim/bim/__init__.py
index 51f2c02614..15e7c8c47e 100644
--- a/src/blenderbim/blenderbim/bim/__init__.py
+++ b/src/blenderbim/blenderbim/bim/__init__.py
@@ -98,10 +98,10 @@ classes = [
operator.AddIfcFile,
operator.BIM_OT_add_section_plane,
operator.BIM_OT_delete_object,
- operator.BIM_OT_open_webbrowser,
operator.BIM_OT_remove_section_plane,
operator.BIM_OT_select_object,
operator.BIM_OT_show_description,
+ operator.BIM_OT_multiple_file_selector,
operator.ClippingPlaneCutWithCappings,
operator.CloseError,
operator.EditBlenderCollection,
@@ -121,6 +121,7 @@ classes = [
prop.StrProperty,
operator.BIM_OT_enum_property_search, # /!\ Register AFTER prop.StrProperty
prop.ObjProperty,
+ prop.MultipleFileSelect,
prop.Attribute,
prop.BIMAreaProperties,
prop.BIMTabProperties,
diff --git a/src/blenderbim/blenderbim/bim/data/webui/sioserver.py b/src/blenderbim/blenderbim/bim/data/webui/sioserver.py
index fdbef0b50c..6d81c03665 100644
--- a/src/blenderbim/blenderbim/bim/data/webui/sioserver.py
+++ b/src/blenderbim/blenderbim/bim/data/webui/sioserver.py
@@ -2,7 +2,9 @@ import sys
import os
import webbrowser
-blenderbim_lib_path = os.environ.get("blenderbim_lib_path")
+blenderbim_lib_path = os.environ.get("BLENDERBIM_LIB_PATH")
+blenderbim_version = os.environ.get("BLENDERBIM_VERSION")
+
if blenderbim_lib_path:
sys.path.insert(0, blenderbim_lib_path)
@@ -52,9 +54,16 @@ class WebNamespace(socketio.AsyncNamespace):
"web_operator",
data,
namespace="/blender",
- room=data["blenderId"],
+ room=data.get("blenderId", None),
)
+ async def on_get_svg(self, sid, data):
+ print("hello world!")
+ file_path = data["path"]
+ with open(file_path, "r") as file:
+ svg_data = file.read()
+ await sio.emit("svg_data", svg_data, room=sid, namespace="/web")
+
async def send_cached_messages(self, sid):
# Send cached messages to the connected web client
for blenderId, messages in blender_messages.items():
@@ -98,6 +107,12 @@ class BlenderNamespace(socketio.AsyncNamespace):
blender_messages[sid]["gantt_data"] = data
await sio.emit("gantt_data", {"blenderId": sid, "data": data}, namespace="/web")
+ async def on_drawings_data(self, sid, data):
+ print(f"Drawings directory from Blender client {sid}")
+ print(data)
+ blender_messages[sid]["drwings_data"] = data
+ await sio.emit("drawings_data", {"blenderId": sid, "data": data}, namespace="/web")
+
# Attach namespaces
sio.register_namespace(WebNamespace("/web"))
@@ -108,26 +123,45 @@ sio.register_namespace(BlenderNamespace("/blender"))
async def index(request):
with open("templates/index.html", "r") as f:
template = f.read()
- html_content = pystache.render(template, {"port": sio_port})
+ html_content = pystache.render(template, {"port": sio_port, "version": blenderbim_version})
return web.Response(text=html_content, content_type="text/html")
async def gantt(request):
with open("templates/gantt.html", "r") as f:
template = f.read()
+ html_content = pystache.render(template, {"port": sio_port, "version": blenderbim_version})
+ return web.Response(text=html_content, content_type="text/html")
+
+
+async def drawings(request):
+ with open("templates/drawings.html", "r") as f:
+ template = f.read()
html_content = pystache.render(template, {"port": sio_port})
return web.Response(text=html_content, content_type="text/html")
-async def open_web_browser(app):
- webbrowser.open(f"http://127.0.0.1:{sio_port}/")
+async def on_startup(app):
+ pid_file = "running_pid.json"
+
+ if os.path.exists(pid_file):
+ with open(pid_file, "r") as f:
+ pids = json.load(f)
+ else:
+ pids = {}
+
+ pids[str(os.getpid())] = sio_port
+
+ with open(pid_file, "w") as f:
+ json.dump(pids, f, indent=4)
app.router.add_get("/", index)
+app.router.add_get("/drawings", drawings)
app.router.add_get("/gantt", gantt)
app.router.add_static("/jsgantt/", path="../gantt", name="jsgantt")
app.router.add_static("/static/", path="./static", name="static")
-app.on_startup.append(open_web_browser)
+app.on_startup.append(on_startup)
def main():
diff --git a/src/blenderbim/blenderbim/bim/data/webui/static/css/drawings.css b/src/blenderbim/blenderbim/bim/data/webui/static/css/drawings.css
new file mode 100644
index 0000000000..9dd2437ecf
--- /dev/null
+++ b/src/blenderbim/blenderbim/bim/data/webui/static/css/drawings.css
@@ -0,0 +1,249 @@
+:root {
+ --font-family: Arial, sans-serif;
+ --base-font-size: 16px;
+ --margin-tiny: 0.125rem;
+ --margin-small: 0.625rem;
+ --margin-medium: 1.25rem;
+ --margin-large: 2.5rem;
+ --padding-tiny: 0.125rem;
+ --padding-small: 0.625rem;
+ --padding-medium: 1rem;
+ --font-size-large: 1.2rem;
+ --logo-height: 2.5rem;
+ --nav-height: 2.5rem;
+}
+
+:root.dark {
+ color-scheme: dark;
+ --bg-color: #252525;
+ --text-color: #e0e0e0;
+ --nav-bg-color: #121212;
+ --nav-border-color: #25682a;
+ --nav-link-color: #fff;
+ --nav-link-hover-color: #3fb449;
+ --warning-color: #FFDB8F;
+ --border-color: #464444;
+}
+
+:root.light {
+ color-scheme: light;
+ --bg-color: #ffffff;
+ --text-color: #000000;
+ --nav-bg-color: #f8f8f8;
+ --nav-border-color: #cccccc;
+ --nav-link-color: #000000;
+ --nav-link-hover-color: #38a63d;
+ --warning-color: #FF4500;
+ --border-color: #222;
+}
+
+html {
+ font-size: var(--base-font-size);
+ color: var(--text-color);
+}
+
+body {
+ background-color: var(--bg-color);
+ color: var(--text-color);
+ margin: 0;
+ font-family: var(--font-family);
+}
+
+#container {
+ margin-top: var(--margin-medium);
+ margin-left: var(--margin-small);
+ margin-right: var(--margin-small);
+ margin-bottom: var(--margin-medium);
+ height: calc(100vh - var(--nav-height));
+ box-sizing: border-box;
+ display: flex;
+}
+
+h3 {
+ margin-top: 0;
+}
+
+nav {
+ background-color: var(--nav-bg-color);
+ height: var(--nav-height);
+ padding: var(--padding-medium) 0;
+ display: flex;
+ align-items: center;
+ position: relative;
+ border-bottom: 2px solid var(--nav-border-color);
+}
+
+nav .logo {
+ margin-left: var(--margin-large);
+ height: var(--logo-height);
+}
+
+nav ul {
+ list-style-type: none;
+ margin: 0;
+ margin-left: 0.0625rem;
+ display: flex;
+ flex-grow: 1;
+ justify-content: center;
+}
+
+nav ul li {
+ margin-right: 3.125rem;
+}
+
+nav ul li a {
+ text-decoration: none;
+ color: var(--nav-link-color);
+ font-size: var(--font-size-large);
+}
+
+nav ul li a:hover,
+nav ul li a.active {
+ color: var(--nav-link-hover-color);
+}
+
+.warning {
+ color: var(--warning-color);
+ margin-bottom: var(--margin-small);
+ padding: var(--padding-tiny);
+ display: none;
+}
+
+#toggle-theme {
+ border: none;
+ background: none;
+ cursor: pointer;
+ font-size: var(--font-size-large);
+ margin-right: var(--margin-medium);
+}
+
+#toggle-theme:focus {
+ outline: none;
+}
+
+#client-list {
+ position: absolute;
+ top: calc(0 + var(--nav-height));
+ overflow-y: auto;
+ overflow: hidden;
+ transition: opacity 0.3s ease-out, visibility 0.3s ease-out;
+ border: 1px solid var(--table-border-color);
+ background-color: var(--nav-bg-color);
+ z-index: 1;
+ opacity: 0;
+ visibility: hidden;
+ width: auto;
+}
+
+#client-list.show {
+ opacity: 1;
+ visibility: visible;
+}
+
+#connected-list-div {
+ display: inline-block;
+}
+
+.client {
+ padding: var(--margin-small);
+ border-bottom: 1px solid var(--table-border-color);
+ cursor: pointer;
+}
+
+.client-details {
+ max-height: 0;
+ overflow: hidden;
+ padding-left: var(--padding-small);
+ transition: max-height 0.2s ease-out, padding 0.2s ease-out, opacity 0.1s ease-out;
+ background-color: var(--nav-bg-color);
+ margin-top: var(--margin-tiny);
+ opacity: 0;
+}
+
+.client-details.show {
+ max-height: none;
+ opacity: 1;
+}
+
+.client-detail {
+ border-bottom: 1px solid var(--table-border-color);
+ padding: var(--padding-small);
+}
+
+#show-connected-button {
+ width: auto;
+ background-color: var(--bg-color);
+ border: none;
+ font-size: var(--base-font-size);
+}
+
+#show-connected-button:hover,
+.scroll-button:hover {
+ cursor: pointer;
+}
+
+.scroll-button {
+ font-size: var(--base-font-size);
+ margin-left: var(--margin-tiny);
+ margin-top: var(--margin-small);
+}
+
+
+.left {
+ flex: 1;
+ background-color: var(--bg-color);
+ display: flex;
+ flex-direction: column;
+ padding: 20px;
+}
+
+.right {
+ flex: 4;
+ background-color: var(--bg-color);
+ border: 1px solid var(--border-color);
+}
+
+#svg-container {
+ height: 100%;
+}
+
+.panel {
+ background-color: var(--nav-bg-color);
+ border: 1px solid var(--border-color);
+ padding: 10px;
+ flex-grow: 1;
+ display: flex;
+ flex-direction: column;
+}
+
+.card-header,
+.card-body {
+ background-color: var(--bg-color);
+ border: 1px solid var(--border-color);
+ overflow: auto;
+}
+
+.card {
+ background-color: var(--nav-bg-color);
+ overflow: auto;
+}
+
+li.svg-name {
+ list-style-type: none;
+}
+
+#dropdown-menu:focus {
+ outline: none;
+}
+
+/* remove bootstrap css confilcts */
+*,
+::after,
+::before {
+ box-sizing: unset;
+}
+
+.btn,
+.btn:hover {
+ color: var(--nav-link-hover-color);
+}
\ No newline at end of file
diff --git a/src/blenderbim/blenderbim/bim/data/webui/static/css/gantt.css b/src/blenderbim/blenderbim/bim/data/webui/static/css/gantt.css
index 1256b09080..f19ab94c28 100644
--- a/src/blenderbim/blenderbim/bim/data/webui/static/css/gantt.css
+++ b/src/blenderbim/blenderbim/bim/data/webui/static/css/gantt.css
@@ -1,13 +1,17 @@
:root {
--font-family: Arial, sans-serif;
+ --base-font-size: 16px;
+ --margin-tiny: 0.125rem;
--margin-small: 0.625rem;
--margin-medium: 1.25rem;
--margin-large: 2.5rem;
- --padding-small: 0.125rem;
+ --padding-tiny: 0.125rem;
+ --padding-small: 0.625rem;
--padding-medium: 1rem;
--font-size-small: 1rem;
--font-size-large: 1.2rem;
--logo-height: 2.5rem;
+ --nav-height: 2.5rem;
--folder-collapse-font-size: 0.75rem;
--folder-collapse-font-family: Courier, "Courier New", monospace;
--box-shadow: 0 0 0.7rem #5f5f5f66;
@@ -31,6 +35,7 @@
--group-item-bg-color: #4b4b4b;
--input-bg-color: #3b3b3b;
--input-border-color: #000;
+ --details-border-color: #464444;
}
:root.light {
@@ -42,6 +47,7 @@
--nav-link-color: #000000;
--nav-link-hover-color: #38a63d;
--warning-color: #FF4500;
+ --details-border-color: #222;
}
html {
@@ -53,9 +59,13 @@ body {
color: var(--primary-text-color);
margin: 0;
font-family: var(--font-family);
+ display: flex;
+ flex-direction: column;
+ min-height: 100vh;
}
#container {
+ flex: 1;
margin-top: var(--margin-medium);
margin-left: var(--margin-small);
margin-right: var(--margin-small);
@@ -107,7 +117,7 @@ nav ul li a.active {
.warning {
color: var(--warning-color);
margin-bottom: var(--margin-small);
- padding: var(--padding-small);
+ padding: var(--padding-tiny);
display: none;
}
@@ -141,6 +151,87 @@ nav ul li a.active {
outline: none;
}
+#client-list {
+ position: absolute;
+ top: calc(0 + var(--nav-height));
+ overflow-y: auto;
+ overflow: hidden;
+ transition: opacity 0.3s ease-out, visibility 0.3s ease-out;
+ border: 1px solid var(--table-border-color);
+ background-color: var(--nav-bg-color);
+ z-index: 1;
+ opacity: 0;
+ visibility: hidden;
+ width: auto;
+}
+
+#client-list.show {
+ opacity: 1;
+ visibility: visible;
+}
+
+#connected-list-div {
+ display: inline-block;
+}
+
+.client {
+ padding: var(--margin-small);
+ border-bottom: 1px solid var(--table-border-color);
+ cursor: pointer;
+}
+
+.client-details {
+ max-height: 0;
+ overflow: hidden;
+ padding-left: var(--padding-small);
+ transition: max-height 0.2s ease-out, padding 0.2s ease-out, opacity 0.1s ease-out;
+ background-color: var(--nav-bg-color);
+ margin-top: var(--margin-tiny);
+ opacity: 0;
+}
+
+.client-details.show {
+ max-height: none;
+ opacity: 1;
+}
+
+.client-detail {
+ border-bottom: 1px solid var(--table-border-color);
+ padding: var(--padding-small);
+}
+
+#show-connected-button {
+ width: auto;
+ background-color: var(--bg-color);
+ border: none;
+ font-size: var(--base-font-size);
+}
+
+#show-connected-button:hover,
+.scroll-button:hover {
+ cursor: pointer;
+}
+
+.scroll-button {
+ font-size: var(--base-font-size);
+ margin-left: var(--margin-tiny);
+ margin-top: var(--margin-small);
+}
+
+footer {
+ background-color: var(--nav-bg-color);
+ text-align: right;
+ padding: var(--padding-tiny);
+ border-top: 1px solid var(--nav-border-color);
+}
+
+footer p {
+ margin: 0;
+ color: var(--text-color);
+ margin-right: var(--margin-small);
+ font-size: 0.8rem;
+}
+
.gantt-info {
margin: 0.5rem;
font-size: var(--font-size-small);
diff --git a/src/blenderbim/blenderbim/bim/data/webui/static/css/index.css b/src/blenderbim/blenderbim/bim/data/webui/static/css/index.css
index 7a480b42c8..37386ebea9 100644
--- a/src/blenderbim/blenderbim/bim/data/webui/static/css/index.css
+++ b/src/blenderbim/blenderbim/bim/data/webui/static/css/index.css
@@ -1,12 +1,16 @@
:root {
--font-family: Arial, sans-serif;
+ --base-font-size: 16px;
+ --margin-tiny: 0.125rem;
--margin-small: 0.625rem;
--margin-medium: 1.25rem;
--margin-large: 2.5rem;
- --padding-small: 0.125rem;
+ --padding-tiny: 0.125rem;
+ --padding-small: 0.625rem;
--padding-medium: 1rem;
--font-size-large: 1.2rem;
--logo-height: 2.5rem;
+ --nav-height: 2.5rem;
}
:root.dark {
@@ -18,6 +22,7 @@
--nav-link-color: #fff;
--nav-link-hover-color: #3fb449;
--warning-color: #FFDB8F;
+ --table-border-color: #464444;
}
:root.light {
@@ -29,6 +34,7 @@
--nav-link-color: #000000;
--nav-link-hover-color: #38a63d;
--warning-color: #FF4500;
+ --table-border-color: #222;
}
html {
@@ -40,29 +46,26 @@ body {
color: var(--text-color);
margin: 0;
font-family: var(--font-family);
+ display: flex;
+ flex-direction: column;
+ min-height: 100vh;
}
#container {
+ flex: 1;
margin-top: var(--margin-medium);
margin-left: var(--margin-small);
margin-right: var(--margin-small);
margin-bottom: var(--margin-medium);
}
-.table-container {
- margin-bottom: var(--margin-large);
-}
-
-.csv-table {
- margin-top: var(--margin-small);
-}
-
h3 {
margin-top: 0;
}
nav {
background-color: var(--nav-bg-color);
+ height: var(--nav-height);
padding: var(--padding-medium) 0;
display: flex;
align-items: center;
@@ -102,7 +105,7 @@ nav ul li a.active {
.warning {
color: var(--warning-color);
margin-bottom: var(--margin-small);
- padding: var(--padding-small);
+ padding: var(--padding-tiny);
display: none;
}
@@ -118,6 +121,95 @@ nav ul li a.active {
outline: none;
}
+#client-list {
+ position: absolute;
+ top: calc(0 + var(--nav-height));
+ overflow-y: auto;
+ overflow: hidden;
+ transition: opacity 0.3s ease-out, visibility 0.3s ease-out;
+ border: 1px solid var(--table-border-color);
+ background-color: var(--nav-bg-color);
+ z-index: 1;
+ opacity: 0;
+ visibility: hidden;
+ width: auto;
+}
+
+#client-list.show {
+ opacity: 1;
+ visibility: visible;
+}
+
+#connected-list-div {
+ display: inline-block;
+}
+
+.client {
+ padding: var(--margin-small);
+ border-bottom: 1px solid var(--table-border-color);
+ cursor: pointer;
+}
+
+.client-details {
+ max-height: 0;
+ overflow: hidden;
+ padding-left: var(--padding-small);
+ transition: max-height 0.2s ease-out, padding 0.2s ease-out, opacity 0.1s ease-out;
+ background-color: var(--nav-bg-color);
+ margin-top: var(--margin-tiny);
+ opacity: 0;
+}
+
+.client-details.show {
+ max-height: none;
+ opacity: 1;
+}
+
+.client-detail {
+ border-bottom: 1px solid var(--table-border-color);
+ padding: var(--padding-small);
+}
+
+#show-connected-button {
+ width: auto;
+ background-color: var(--bg-color);
+ border: none;
+ font-size: var(--base-font-size);
+}
+
+#show-connected-button:hover,
+.scroll-button:hover {
+ cursor: pointer;
+}
+
+.scroll-button {
+ font-size: var(--base-font-size);
+ margin-left: var(--margin-tiny);
+ margin-top: var(--margin-small);
+}
+
+footer {
+ background-color: var(--nav-bg-color);
+ text-align: right;
+ padding: var(--padding-tiny);
+ border-top: 1px solid var(--nav-border-color);
+}
+
+footer p {
+ margin: 0;
+ color: var(--text-color);
+ margin-right: var(--margin-small);
+ font-size: 0.8rem;
+}
+
+.table-container {
+ margin-bottom: var(--margin-large);
+}
+
+.csv-table {
+ margin-top: var(--margin-small);
+}
+
/* ------------ Overwriting Tabulator CSS rules ------------ */
:root.light .tabulator-header,
@@ -127,6 +219,6 @@ nav ul li a.active {
}
:root.light .tabulator {
- border-top: 1px solid #222;
- border-bottom: 2px solid #222;
+ border-top: 1px solid var(--table-border-color);
+ border-bottom: 2px solid var(--table-border-color);
}
\ No newline at end of file
diff --git a/src/blenderbim/blenderbim/bim/data/webui/static/js/drawings.js b/src/blenderbim/blenderbim/bim/data/webui/static/js/drawings.js
new file mode 100644
index 0000000000..8a865dcab1
--- /dev/null
+++ b/src/blenderbim/blenderbim/bim/data/webui/static/js/drawings.js
@@ -0,0 +1,263 @@
+// keeps track of blenders connected
+const connectedClients = {};
+const allDrawings = {};
+let socket;
+
+// Document ready function
+$(document).ready(function () {
+ var systemTheme = window.matchMedia("(prefers-color-scheme: light)").matches
+ ? "light"
+ : "dark";
+ var theme = localStorage.getItem("theme") || systemTheme;
+ setTheme(theme);
+
+ $("#dropdown-menu").change(function () {
+ const blenderId = $(this).attr("id");
+ const ifcFile = $(this).val();
+ displayDrawingsNames(blenderId, ifcFile);
+ });
+
+ connectSocket();
+});
+
+// Function to connect to Socket.IO server
+function connectSocket() {
+ const url = "ws://localhost:" + SOCKET_PORT + "/web";
+ socket = io(url);
+ console.log("socket: ", socket);
+
+ // Register socket event handlers
+ socket.on("blender_connect", handleBlenderConnect);
+ socket.on("blender_disconnect", handleBlenderDisconnect);
+ socket.on("connect", handleWebConnect);
+ socket.on("drawings_data", handleDrawingsData);
+ socket.on("svg_data", handleSvgData);
+ // socket.on("default_data", handleDefaultData);
+}
+
+// function used to get drawings data from blenderbim
+function handleWebConnect() {
+ const msg = {
+ sourcePage: "drawings",
+ operator: {
+ type: "getDrawings",
+ },
+ };
+ socket.emit("web_operator", msg);
+}
+
+// Function to handle 'blender_connect' event
+function handleBlenderConnect(blenderId) {
+ console.log("blender_connect: ", blenderId);
+ if (!connectedClients.hasOwnProperty(blenderId)) {
+ connectedClients[blenderId] = {
+ shown: false,
+ ifc_file: "",
+ };
+ }
+}
+
+// Function to handle 'blender_disconnect' event
+function handleBlenderDisconnect(blenderId) {
+ console.log("blender_disconnect: ", blenderId);
+ if (connectedClients.hasOwnProperty(blenderId)) {
+ delete connectedClients[blenderId];
+ // remove(blenderId);
+ }
+
+ $("#blender-count").text(function (i, text) {
+ return parseInt(text, 10) - 1;
+ });
+}
+
+function handleDrawingsData(data) {
+ const blenderId = data["blenderId"];
+
+ console.log(data);
+
+ const filename = data["data"]["ifc_file"];
+ const drawings = data["data"]["drawings_data"]["drawings"];
+ const sheets = data["data"]["drawings_data"]["sheets"];
+
+ allDrawings[filename] = { drawings: drawings, sheets: sheets };
+
+ console.log(connectedClients);
+
+ if (connectedClients.hasOwnProperty(blenderId)) {
+ if (!connectedClients[blenderId].shown) {
+ connectedClients[blenderId] = {
+ shown: true,
+ ifc_file: filename,
+ };
+ addSelectOption(blenderId, filename);
+ } else {
+ // update(blenderId, data, filename);
+ }
+ } else {
+ connectedClients[blenderId] = {
+ shown: true,
+ ifc_file: filename,
+ };
+ addSelectOption(blenderId, filename);
+ }
+}
+
+function handleSvgData(data) {
+ const svgContainer = document.getElementById("svg-container");
+ svgContainer.innerHTML = "";
+ svgContainer.style.backgroundColor = "white";
+
+ const dom = SVG(svgContainer).svg(data);
+ const svgElement = dom.node.children[0];
+
+ // to make the svg not grow outside the svg container
+ svgElement.setAttribute("width", "100%");
+ svgElement.setAttribute("height", "100%");
+ svgElement.style.maxWidth = "100%";
+ svgElement.style.maxHeight = "100%";
+ svgElement.style.width = "100%";
+ svgElement.style.height = "100%";
+ svgElement.style.boxSizing = "border-box"; // Ensure padding and borders are included in the element's total width and height
+
+ const panZoomControls = svgPanZoom(svgElement, {
+ zoomEnabled: true,
+ controlIconsEnabled: true,
+ fit: true,
+ center: true,
+ });
+}
+
+function addSelectOption(blenderId, filename) {
+ const filenameOption = $("")
+ .attr("id", "blender-" + blenderId)
+ .val(filename)
+ .text(filename);
+ $("#dropdown-menu").append(filenameOption);
+}
+
+function displayDrawingsNames(blenderId, ifcFile) {
+ drawings = allDrawings[ifcFile].drawings;
+ sheets = allDrawings[ifcFile].sheets;
+
+ function createSvgNames(text, index, type) {
+ var label = $("
")
+ .text(text)
+ .attr("id", type + "-" + index)
+ .addClass("svg-name")
+ .click(function () {
+ const id = $(this).attr("id").split("-");
+ const index = parseInt(id[1]);
+ const type = id[0];
+ const ifcFile = $("#dropdown-menu").val();
+
+ var path = "";
+
+ if (type === "drawing") {
+ path = allDrawings[ifcFile].drawings[index].path;
+ } else if (type === "sheet") {
+ path = allDrawings[ifcFile].sheets[index].path;
+ }
+
+ const msg = {
+ path: path,
+ };
+ console.log(msg);
+ socket.emit("get_svg", msg);
+ });
+
+ if (type === "drawing") $("#drawings-sub-panel").append(label);
+ else if (type === "sheet") $("#sheets-sub-panel").append(label);
+ }
+
+ $("#drawings-sub-panel").empty();
+ drawings.forEach(function (drawing, index) {
+ createSvgNames(drawing.name, index, "drawing");
+ });
+
+ $("#sheets-sub-panel").empty();
+ sheets.forEach(function (sheet, index) {
+ createSvgNames(sheet.name, index, "sheet");
+ });
+}
+
+function setTheme(theme) {
+ if (theme === "light") {
+ $("html").removeClass("dark").addClass("light");
+ $("#toggle-theme").html('');
+ } else {
+ $("html").removeClass("light").addClass("dark");
+ $("#toggle-theme").html('');
+ }
+ localStorage.setItem("theme", theme);
+}
+
+function toggleTheme() {
+ if ($("html").hasClass("dark")) {
+ setTheme("light");
+ } else {
+ setTheme("dark");
+ }
+}
+
+function toggleClientList() {
+ var clientList = $("#client-list");
+
+ if (clientList.hasClass("show")) {
+ clientList.removeClass("show");
+ return;
+ }
+
+ clientList.empty();
+
+ $.each(connectedClients, function (id, client) {
+ if (!client.shown) return;
+
+ const dropdownIcon = $("")
+ .addClass("fas fa-chevron-down")
+ .css("margin-left", "0.5rem");
+
+ const clientDiv = $("").addClass("client").text(client.ifc_file);
+
+ clientDiv.append(dropdownIcon);
+
+ const clientDetailsDiv = $("
").addClass("client-details");
+
+ if (id) {
+ const clientId = $("
")
+ .addClass("client-detail")
+ .text(`Blender ID: ${id}`);
+ clientDetailsDiv.append(clientId);
+ }
+
+ if (client.headers && client.headers.length) {
+ const clientHeaders = $("
")
+ .addClass("client-detail")
+ .text(`Table Headers: ${client.headers.join(", ")}`);
+
+ const scrollButton = $("