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

This commit is contained in:
Chirag Singh
2026-03-08 23:01:34 +05:30
363 changed files with 4391 additions and 3683 deletions
+2 -2
View File
@@ -104,7 +104,7 @@ endif
endif # def PLATFORM
# Current build commit hash.
OLD:=e8eb5e4
OLD:=1c5b825
.PHONY: bump
bump:
ifndef NEW
@@ -371,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
-1
View File
@@ -34,7 +34,6 @@ IN_PACKAGE = __package__ == "bonsai"
import platform
import re
import shutil
import traceback
import uuid
import webbrowser
-8
View File
@@ -24,21 +24,14 @@ 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
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
@@ -52,7 +45,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:
-1
View File
@@ -28,7 +28,6 @@ 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,
+5 -45
View File
@@ -32,7 +32,6 @@ import ifcopenshell.api.pset
import ifcopenshell.geom
import ifcopenshell.ifcopenshell_wrapper as W
import ifcopenshell.util.element
import ifcopenshell.util.geolocation
import ifcopenshell.util.placement
import ifcopenshell.util.representation
import ifcopenshell.util.shape
@@ -85,7 +84,7 @@ class MaterialCreator:
if element.is_a("IfcTypeProduct"):
self.parse_element_type_material_styles(element)
self.parsed_meshes.add(self.mesh.name)
if not self.ifc_import_settings.load_indexed_maps:
if self.ifc_import_settings.load_indexed_maps:
self.load_texture_maps(shape_has_openings)
self.assign_material_slots_to_faces()
tool.Geometry.record_object_materials(obj)
@@ -117,7 +116,6 @@ class MaterialCreator:
for texture in texture_style.Textures or []:
if coords := getattr(texture, "IsMappedBy", None):
coords = coords[0]
# IfcTextureCoordinateGenerator handled in the style shader graph
if coords.is_a("IfcIndexedTextureMap"):
return coords
# TODO: support IfcTextureMap
@@ -135,6 +133,10 @@ class MaterialCreator:
if shape_has_openings and coords.is_a("IfcIndexedTextureMap"):
continue
tool.Loader.load_indexed_map(coords, self.mesh)
elif tool.Style.get_texture_style(material):
# No explicit coordinate mapping (e.g. IFC2X3 has no IsMappedBy,
# and IFC4 COORD uses generated UVs). Bake XY→UV as fallback.
tool.Loader.load_generated_uv_map(self.mesh)
def assign_material_slots_to_faces(self) -> None:
if not self.mesh["ios_materials"]:
@@ -892,48 +894,6 @@ class IfcImporter:
obj, tool.Loader.apply_blender_offset_to_matrix_world(obj, self.get_element_matrix(element))
)
if element.is_a("IfcAnnotation") and getattr(element, "ObjectType", None) == "IMAGE":
image = None
if obj.data and obj.data.materials and obj.data.materials[0]:
material = obj.data.materials[0]
if material.use_nodes and material.node_tree:
for node in material.node_tree.nodes:
if node.type == "TEX_IMAGE" and node.image:
image = node.image
break
if image:
import bmesh
bm = bmesh.new()
bm.from_mesh(obj.data)
if not bm.loops.layers.uv:
uv_layer = bm.loops.layers.uv.new()
else:
uv_layer = bm.loops.layers.uv.active
if bm.verts:
min_x = min(v.co.x for v in bm.verts)
max_x = max(v.co.x for v in bm.verts)
min_y = min(v.co.y for v in bm.verts)
max_y = max(v.co.y for v in bm.verts)
width = max_x - min_x
height = max_y - min_y
for face in bm.faces:
for loop in face.loops:
vert = loop.vert
u = (vert.co.x - min_x) / width if width > 0 else 0.5
v = (vert.co.y - min_y) / height if height > 0 else 0.5
u = max(0.0, min(1.0, u))
v = max(0.0, min(1.0, v))
loop[uv_layer].uv = (u, v)
bm.to_mesh(obj.data)
bm.free()
obj.data.update()
return obj
def load_existing_meshes(self) -> None:
@@ -19,7 +19,6 @@
import blf
import bpy
import gpu
import ifcopenshell
import ifcopenshell.util.element
from bpy.types import SpaceView3D
from bpy_extras import view3d_utils
@@ -27,7 +26,6 @@ from gpu_extras.batch import batch_for_shader
from mathutils import Vector
import bonsai.tool as tool
from bonsai.bim.module.geometry.decorator import ItemDecorator
def transparent_color(color, alpha=0.1):
@@ -19,8 +19,6 @@
from typing import TYPE_CHECKING
import bpy
import ifcopenshell
import ifcopenshell.api
import ifcopenshell.api.group
import ifcopenshell.api.pset
import ifcopenshell.api.root
@@ -23,12 +23,7 @@ import ifcopenshell.util.element
from bpy.props import (
BoolProperty,
CollectionProperty,
EnumProperty,
FloatProperty,
FloatVectorProperty,
IntProperty,
PointerProperty,
StringProperty,
)
from bpy.types import PropertyGroup
@@ -37,8 +32,6 @@ 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:
@@ -21,7 +21,6 @@ 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
class BIM_PT_aggregate(Panel):
@@ -18,24 +18,14 @@
# pyright: reportUnnecessaryTypeIgnoreComment=error
import calendar
import json
import os
import time
from datetime import datetime
import bpy
import ifcopenshell.api.alignment
import ifcopenshell.api.spatial
import ifcopenshell.geom
import ifcopenshell.util.selector
import ifcopenshell.util.sequence
import isodate
from bpy_extras.io_utils import ImportHelper
from dateutil import parser, relativedelta
import bonsai.bim.module.sequence.helper as helper
import bonsai.core.sequence as core
import bonsai.tool as tool
@@ -23,16 +23,12 @@ 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 Attribute, StrProperty
from bonsai.bim.prop import Attribute
class BIMAttributeProperties(PropertyGroup):
@@ -19,9 +19,7 @@
import os
from typing import Union
import bcf
import bcf.bcfxml
import bcf.v2.bcfxml
import bpy
import bonsai.tool as tool
+2 -7
View File
@@ -16,22 +16,18 @@
# You should have received a copy of the GNU General Public License
# 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 math import atan, degrees, radians, 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
import bcf.v3.model
@@ -43,11 +39,10 @@ import ifcopenshell.util.geolocation
import ifcopenshell.util.unit
import numpy as np
from bpy_extras.io_utils import ExportHelper, ImportHelper
from mathutils import Euler, Matrix, Vector, geometry
from mathutils import Matrix, Vector
from xsdata.models.datatype import XmlDateTime
import bonsai.bim.module.bcf.bcfstore as bcfstore
import bonsai.bim.module.bcf.prop as bcf_prop
import bonsai.tool as tool
-2
View File
@@ -24,8 +24,6 @@ from bpy.props import (
BoolProperty,
CollectionProperty,
EnumProperty,
FloatProperty,
FloatVectorProperty,
IntProperty,
PointerProperty,
StringProperty,
-1
View File
@@ -18,7 +18,6 @@
from __future__ import annotations
import os
from typing import TYPE_CHECKING
import bpy
@@ -20,7 +20,6 @@ import bmesh
import gpu
from bpy.types import SpaceView3D
from gpu_extras.batch import batch_for_shader
from mathutils import Vector
import bonsai.tool as tool
@@ -29,18 +29,15 @@ import ifcopenshell.api.root
import ifcopenshell.geom
import ifcopenshell.util.element
import ifcopenshell.util.placement
import ifcopenshell.util.representation
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
import bonsai.tool as tool
from bonsai.bim.ifc import IfcStore
@@ -21,13 +21,7 @@ from typing import TYPE_CHECKING, Union
import bpy
from bpy.props import (
BoolProperty,
CollectionProperty,
EnumProperty,
FloatProperty,
FloatVectorProperty,
IntProperty,
PointerProperty,
StringProperty,
)
from bpy.types import PropertyGroup
+1 -2
View File
@@ -16,8 +16,7 @@
# You should have received a copy of the GNU General Public License
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
import bpy
from bpy.types import Panel, UIList
from bpy.types import Panel
import bonsai.tool as tool
from bonsai.bim.module.boundary.data import SpaceBoundariesData
+2 -6
View File
@@ -63,8 +63,7 @@ class BrickschemaData:
if namespace == "https://brickschema.org/schema/Brick":
return []
results = []
query = BrickStore.graph.query(
"""
query = BrickStore.graph.query("""
PREFIX brick: <https://brickschema.org/schema/Brick#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
@@ -81,10 +80,7 @@ class BrickschemaData:
}
}
GROUP BY ?object
""".replace(
"{uri}", uri
)
)
""".replace("{uri}", uri))
for row in query:
predicate_uri = row.get("predicate")
predicate_name = predicate_uri.toPython().split("#")[-1]
@@ -19,7 +19,6 @@
import os
import bpy
import ifcopenshell.api
from bpy_extras.io_utils import ExportHelper, ImportHelper
import bonsai.bim.handler
+1 -4
View File
@@ -23,10 +23,7 @@ from bpy.props import (
BoolProperty,
CollectionProperty,
EnumProperty,
FloatProperty,
FloatVectorProperty,
IntProperty,
PointerProperty,
StringProperty,
)
from bpy.types import PropertyGroup
@@ -34,7 +31,7 @@ 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.bim.prop import StrProperty
from bonsai.tool.brick import BrickStore
@@ -16,13 +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/>.
import bpy
import ifcopenshell
import ifcopenshell.util.classification
import ifcopenshell.util.date
import bonsai.tool as tool
from bonsai.bim.ifc import IfcStore
def refresh():
@@ -19,7 +19,6 @@ import textwrap
from typing import Any
import bpy
import bsdd
import ifcopenshell.api.pset
import ifcopenshell.util.element
+1 -4
View File
@@ -23,10 +23,7 @@ from bpy.props import (
BoolProperty,
CollectionProperty,
EnumProperty,
FloatProperty,
FloatVectorProperty,
IntProperty,
PointerProperty,
StringProperty,
)
from bpy.types import PropertyGroup
@@ -34,7 +31,7 @@ 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 bonsai.bim.prop import Attribute
def get_active_dictionary(self: "BIMBSDDProperties", context: object) -> tool.Blender.BLENDER_ENUM_ITEMS:
+1 -3
View File
@@ -17,13 +17,11 @@
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
import math
from math import cos, pi, radians, sin, sqrt
from typing import Union
from math import pi, sqrt
import bmesh
import bpy
import bpy_extras
import ifcopenshell.util.unit
import mathutils
from mathutils import Matrix, Vector
-2
View File
@@ -22,8 +22,6 @@ 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)
@@ -20,12 +20,10 @@ import os
from functools import partial
import bpy
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 bonsai.bim.module.model.data import RailingData, RoofData
def load_custom_icons():
@@ -18,9 +18,6 @@
import json
import bpy
import ifcopenshell.util.element
import bonsai.tool as tool
@@ -17,7 +17,6 @@
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
import blf
import bmesh
import gpu
from bpy.types import SpaceView3D
from bpy_extras.view3d_utils import location_3d_to_region_2d
@@ -18,16 +18,13 @@
import json
import logging
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
+1 -2
View File
@@ -26,7 +26,6 @@ from bpy.props import (
FloatProperty,
FloatVectorProperty,
IntProperty,
PointerProperty,
StringProperty,
)
from bpy.types import PropertyGroup
@@ -34,7 +33,7 @@ from ifcopenshell.geom.main import CLASH_TYPE_ITEMS, ClashType
from mathutils import Vector
import bonsai.tool as tool
from bonsai.bim.prop import Attribute, BIMFilterGroup, StrProperty
from bonsai.bim.prop import BIMFilterGroup, StrProperty
class ClashSource(PropertyGroup):
@@ -18,7 +18,6 @@
import bpy
import ifcopenshell
import ifcopenshell.api
import ifcopenshell.api.classification
import ifcopenshell.api.pset
import ifcopenshell.util.classification
@@ -23,10 +23,7 @@ from bpy.props import (
BoolProperty,
CollectionProperty,
EnumProperty,
FloatProperty,
FloatVectorProperty,
IntProperty,
PointerProperty,
StringProperty,
)
from bpy.types import PropertyGroup
@@ -25,7 +25,6 @@ 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,
@@ -19,7 +19,6 @@
from typing import TYPE_CHECKING
import bpy
import ifcopenshell.api
import ifcopenshell.api.constraint
import bonsai.bim.helper
@@ -20,19 +20,13 @@ from typing import TYPE_CHECKING, Literal
import bpy
from bpy.props import (
BoolProperty,
CollectionProperty,
EnumProperty,
FloatProperty,
FloatVectorProperty,
IntProperty,
PointerProperty,
StringProperty,
)
from bpy.types import PropertyGroup
from ifcopenshell.util.doc import get_entity_doc
import bonsai.tool as tool
from bonsai.bim.module.constraint.data import ConstraintsData
from bonsai.bim.prop import Attribute
@@ -18,7 +18,6 @@
from typing import Any
import bpy
import ifcopenshell
import bonsai.tool as tool
+1 -7
View File
@@ -20,19 +20,13 @@ from typing import TYPE_CHECKING
import bpy
from bpy.props import (
BoolProperty,
CollectionProperty,
EnumProperty,
FloatProperty,
FloatVectorProperty,
IntProperty,
PointerProperty,
StringProperty,
)
from bpy.types import PropertyGroup
from bonsai.bim.module.context.data import ContextData
from bonsai.bim.prop import Attribute, StrProperty
from bonsai.bim.prop import Attribute
class BIMContextProperties(PropertyGroup):
@@ -18,13 +18,11 @@
from typing import Any, Union
import bpy
import ifcopenshell
import ifcopenshell.util.cost
import ifcopenshell.util.date
import ifcopenshell.util.element
import ifcopenshell.util.unit
from ifcopenshell.util.doc import get_entity_doc, get_predefined_type_doc
import bonsai.tool as tool
@@ -987,10 +987,10 @@ class ExportCostSchedulesToPDF(bpy.types.Operator, ExportHelper):
@classmethod
def poll(cls, context):
try:
import typst
import typst # noqa: F401
return True
except:
except ModuleNotFoundError:
cls.poll_message_set(
"Typst not available.\nIt can be installed from Quality and\nControl -> Debug and using 'typst' with Pip Install.\n(Run Blender as Administrator)"
)
@@ -19,16 +19,13 @@
from typing import TYPE_CHECKING, Literal, Union
import bpy
import ifcopenshell.api
import ifcopenshell.api.cost
from bpy.props import (
BoolProperty,
CollectionProperty,
EnumProperty,
FloatProperty,
FloatVectorProperty,
IntProperty,
PointerProperty,
StringProperty,
)
from bpy.types import PropertyGroup
@@ -21,7 +21,6 @@ import os
from functools import partial
import bpy
import ifcopenshell
from bpy.types import WorkSpaceTool
import bonsai.tool as tool
@@ -20,7 +20,6 @@ import json
from math import atan2, degrees
import bpy
import ifcopenshell
import ifcopenshell.util.element
import bonsai.tool as tool
@@ -19,14 +19,10 @@
from __future__ import annotations
import json
import logging
import os
import tempfile
from collections import Counter
from typing import TYPE_CHECKING
import bpy
import ifccsv
import ifcopenshell
import ifcopenshell.util.selector
from bpy_extras.io_utils import ExportHelper, ImportHelper
+1 -5
View File
@@ -23,15 +23,11 @@ from bpy.props import (
BoolProperty,
CollectionProperty,
EnumProperty,
FloatProperty,
FloatVectorProperty,
IntProperty,
PointerProperty,
StringProperty,
)
from bpy.types import PropertyGroup
from bonsai.bim.prop import BIMFilterGroup, StrProperty
from bonsai.bim.prop import BIMFilterGroup
class CsvAttribute(PropertyGroup):
@@ -29,7 +29,6 @@ from typing import TYPE_CHECKING, Any, Literal, Union, assert_never, get_args
import bpy
import ifcopenshell
import ifcopenshell.api
import ifcopenshell.api.pset
import ifcopenshell.geom
import ifcopenshell.ifcopenshell_wrapper as W
@@ -20,13 +20,9 @@ from typing import TYPE_CHECKING, Literal, get_args
import bpy
from bpy.props import (
BoolProperty,
CollectionProperty,
EnumProperty,
FloatProperty,
FloatVectorProperty,
IntProperty,
PointerProperty,
StringProperty,
)
from bpy.types import PropertyGroup
@@ -32,18 +32,10 @@
from typing import TYPE_CHECKING
import bpy
# Properties have many different data types. We won't use all of them in this
# demo module, but this is a list for your reference.
from bpy.props import (
BoolProperty,
CollectionProperty,
EnumProperty,
FloatProperty,
FloatVectorProperty,
IntProperty,
PointerProperty,
StringProperty,
)
from bpy.types import PropertyGroup
+1 -5
View File
@@ -23,16 +23,12 @@ from bpy.props import (
BoolProperty,
CollectionProperty,
EnumProperty,
FloatProperty,
FloatVectorProperty,
IntProperty,
PointerProperty,
StringProperty,
)
from bpy.types import PropertyGroup
from bonsai.bim.module.diff.data import DiffData
from bonsai.bim.prop import BIMFilterGroup, StrProperty
from bonsai.bim.prop import BIMFilterGroup
def update_diff_json_file(self: "DiffProperties", context: bpy.types.Context) -> None:
@@ -19,8 +19,6 @@
import os
import bpy
import ifcopenshell
import ifcopenshell.util.schema
from natsort import natsorted
import bonsai.tool as tool
@@ -20,10 +20,9 @@ import json
import bpy
import bonsai.bim.handler
import bonsai.core.document as core
import bonsai.tool as tool
from bonsai.bim.module.document.data import DocumentData, ObjectDocumentData
from bonsai.bim.module.document.data import ObjectDocumentData
class LoadProjectDocuments(bpy.types.Operator):
@@ -5,17 +5,14 @@ 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.document.data import DocumentData, refresh
from bonsai.bim.prop import Attribute, StrProperty
from bonsai.bim.prop import Attribute
def update_document_name(self: "Document", context: bpy.types.Context) -> None:
@@ -16,7 +16,6 @@
# 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 bpy.types import Panel, UIList
import bonsai.tool as tool
@@ -18,15 +18,12 @@
from __future__ import annotations
import math
import os
from pathlib import Path
from typing import Optional
import bmesh
import bpy
import ifcopenshell.util.element
from mathutils import Matrix, Vector
from mathutils import Vector
import bonsai.tool as tool
@@ -23,8 +23,6 @@ from typing import Any, Union
import bpy
import ifcopenshell.util.element
import ifcopenshell.util.representation
import ifcopenshell.util.selector
import ifcopenshell.util.unit
from natsort import natsorted
@@ -23,7 +23,7 @@ from functools import cache
from math import acos, atan, cos, degrees, pi, radians, sin
from pathlib import Path
from timeit import default_timer as timer
from typing import Optional, Union
from typing import Optional
import blf
import bmesh
@@ -34,7 +34,6 @@ import ifcopenshell.util.element
import ifcopenshell.util.representation
import ifcopenshell.util.unit
import numpy as np
import shapely
from bpy.types import SpaceView3D
from bpy_extras.view3d_utils import location_3d_to_region_2d
from gpu_extras.batch import batch_for_shader
@@ -17,10 +17,8 @@
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
import math
from typing import Union
import bpy
import ifcopenshell
import ifcopenshell.util.element
import ifcopenshell.util.unit
import mathutils.geometry
+104 -189
View File
@@ -18,9 +18,9 @@
import hashlib
import json
import logging
import multiprocessing
import os
import re
import shutil
import subprocess
import time
@@ -41,7 +41,6 @@ from typing import (
import bmesh
import bpy
import ifcopenshell
import ifcopenshell.api
import ifcopenshell.api.document
import ifcopenshell.api.pset
import ifcopenshell.api.style
@@ -50,19 +49,18 @@ import ifcopenshell.ifcopenshell_wrapper
import ifcopenshell.util.element
import ifcopenshell.util.representation
import ifcopenshell.util.selector
import ifcopenshell.util.shape_builder
import ifcopenshell.util.unit
import numpy as np
import shapely
import shapely.ops
from bpy_extras.image_utils import load_image
from bpy_extras.io_utils import ImportHelper
from lxml import etree
from mathutils import Color, Matrix, Vector
from mathutils import Color, Vector
import bonsai.bim.export_ifc
import bonsai.bim.handler
import bonsai.bim.helper
import bonsai.bim.module.drawing.annotation as annotation
import bonsai.bim.import_ifc
import bonsai.bim.module.drawing.sheeter as sheeter
import bonsai.bim.module.drawing.svgwriter as svgwriter
import bonsai.core.drawing as core
@@ -138,7 +136,7 @@ class AddAnnotationType(bpy.types.Operator, tool.Ifc.Operator):
element.ApplicableOccurrence = f"IfcAnnotation/{object_type}"
if props.create_representation_for_type and object_type == "IMAGE":
bpy.ops.bim.add_reference_image("INVOKE_DEFAULT", use_existing_object_by_name=obj.name)
bpy.ops.bim.add_reference_image("INVOKE_DEFAULT", existing_object_by_name=obj.name)
class EnableAddAnnotationType(bpy.types.Operator):
@@ -928,7 +926,7 @@ class CreateDrawing(bpy.types.Operator):
props = tool.Project.get_project_props()
for link in props.get_loaded_links_for_drawings():
files[link.name] = self.get_linked_file(link)
files[link.filepath] = self.get_linked_file(link)
target_view = ifcopenshell.util.element.get_psets(self.camera_element)["EPset_Drawing"]["TargetView"]
self.setup_serialiser(target_view)
@@ -1374,7 +1372,7 @@ class CreateDrawing(bpy.types.Operator):
return True
def get_linked_file(self, link: "Link") -> ifcopenshell.file:
link_path = link.name
link_path = link.filepath
ifc_file = IfcStore.session_files.get(link_path, None)
if ifc_file is not None:
return ifc_file
@@ -1759,7 +1757,7 @@ class AddAnnotation(bpy.types.Operator, tool.Ifc.Operator):
enable_editing=True,
)
if props.object_type == "IMAGE":
bpy.ops.bim.add_reference_image("INVOKE_DEFAULT", use_existing_object_by_name=obj.name)
bpy.ops.bim.add_reference_image("INVOKE_DEFAULT", existing_object_by_name=obj.name)
class AddSheet(bpy.types.Operator, tool.Ifc.Operator):
@@ -2896,12 +2894,16 @@ class AddSchedule(bpy.types.Operator, tool.Ifc.Operator, ImportHelper):
bl_options = {"REGISTER", "UNDO"}
bl_description = "Add an .ods, .xls or .xlsx file as a schedule"
files: bpy.props.CollectionProperty(name="Files", type=bpy.types.OperatorFileListElement)
directory: bpy.props.StringProperty(subtype="DIR_PATH")
filter_glob: bpy.props.StringProperty(default="*.ods;*.xls;*.xlsx", options={"HIDDEN"})
use_relative_path: bpy.props.BoolProperty(name="Use Relative Path", default=True)
def _execute(self, context):
filepath = tool.Ifc.get_uri(self.filepath, use_relative_path=self.use_relative_path)
core.add_document(tool.Ifc, tool.Drawing, "SCHEDULE", uri=filepath)
for filepath in tool.Blender.get_selected_files(
self.directory, self.files, use_relative_path=self.use_relative_path
):
core.add_document(tool.Ifc, tool.Drawing, "SCHEDULE", uri=filepath)
class RemoveSchedule(bpy.types.Operator, tool.Ifc.Operator):
@@ -3090,23 +3092,16 @@ class AddReference(bpy.types.Operator, tool.Ifc.Operator, ImportHelper):
bl_description = "Import a .svg file to the project as a reference"
bl_options = {"REGISTER", "UNDO"}
files: bpy.props.CollectionProperty(name="Files", type=bpy.types.OperatorFileListElement)
directory: bpy.props.StringProperty(subtype="DIR_PATH")
filter_glob: bpy.props.StringProperty(default="*.svg", options={"HIDDEN"})
use_relative_path: bpy.props.BoolProperty(name="Use Relative Path", default=True)
filename_ext = ".svg"
files: bpy.props.CollectionProperty(type=bpy.types.OperatorFileListElement)
directory: bpy.props.StringProperty(subtype="DIR_PATH")
def _execute(self, context):
# Handle both single and multiple file selection
if self.files:
for file_elem in self.files:
filepath = os.path.join(self.directory, file_elem.name)
uri = tool.Ifc.get_uri(filepath, use_relative_path=self.use_relative_path)
core.add_document(tool.Ifc, tool.Drawing, "REFERENCE", uri=uri)
else:
# Fallback for single file (backward compatibility)
filepath = tool.Ifc.get_uri(self.filepath, use_relative_path=self.use_relative_path)
for filepath in tool.Blender.get_selected_files(
self.directory, self.files, use_relative_path=self.use_relative_path
):
core.add_document(tool.Ifc, tool.Drawing, "REFERENCE", uri=filepath)
@@ -3165,6 +3160,7 @@ class EditTextPopup(bpy.types.Operator):
bpy.ops.bim.disable_editing_text()
def execute(self, context):
# TODO: check for possible subtle undo bug here
# can't use invoke() because this operator
# will be run indirectly by hotkey
# so we use execute() and track whether it's the first run of the operator
@@ -3804,83 +3800,51 @@ class AddReferenceImage(bpy.types.Operator, tool.Ifc.Operator, ImportHelper):
use_relative_path: bpy.props.BoolProperty(name="Use Relative Path", default=True)
filter_image: bpy.props.BoolProperty(default=True, options={"HIDDEN", "SKIP_SAVE"})
filter_folder: bpy.props.BoolProperty(default=True, options={"HIDDEN", "SKIP_SAVE"})
override_existing_image: bpy.props.BoolProperty(
name="Override Existing Image",
default=True,
description=(
"Override image if it was previously loaded to Blender. If disabled, will always create a new image"
),
)
use_existing_object_by_name: bpy.props.StringProperty(
name="Use Existing Object By Name",
description="Existing object name to add a style with reference image to. If not provided will create a new object.",
options={"SKIP_SAVE"},
)
x_length: bpy.props.FloatProperty(
name="X Length",
description="Width of the reference image in project units",
description="Width of the reference image",
default=1.0,
min=0.001,
soft_min=0.01,
precision=3,
unit="LENGTH",
)
y_length: bpy.props.FloatProperty(
name="Y Length",
description="Height of the reference image in project units",
description="Height of the reference image",
default=1.0,
min=0.001,
soft_min=0.01,
precision=3,
unit="LENGTH",
)
show_texture_solid_mode: bpy.props.BoolProperty(
name="Show Texture in Solid mode (slow)",
description="Show Texture in Solid mode (slow)",
default=False,
)
show_dimensions_dialog: bpy.props.BoolProperty(default=False, options={"HIDDEN", "SKIP_SAVE"})
def draw(self, context):
layout = self.layout
if getattr(self, "show_dimensions_dialog", False):
if tool.Ifc.get():
length_unit = ifcopenshell.util.unit.get_project_unit(tool.Ifc.get(), "LENGTHUNIT")
if length_unit:
unit_name = ifcopenshell.util.unit.get_full_unit_name(length_unit).lower()
else:
unit_name = "project units"
layout.label(text=f"Set Reference Image Dimensions (in {unit_name}):")
else:
layout.label(text="Set Reference Image Dimensions (in project units):")
layout.separator()
layout.prop(self, "x_length")
layout.prop(self, "y_length")
else:
if Path(tool.Ifc.get_path()).is_file():
layout.prop(self, "use_relative_path")
else:
self.use_relative_path = False
layout.label(text="Save the .ifc file first ")
layout.label(text="to use relative paths.")
layout.prop(self, "override_existing_image")
layout.prop(self, "use_existing_object_by_name")
@classmethod
def poll(cls, context):
if not tool.Ifc.get():
cls.poll_message_set("No IFC project is loaded.")
return False
return True
def invoke(self, context, event):
if not getattr(self, "show_dimensions_dialog", False):
context.window_manager.fileselect_add(self)
return {"RUNNING_MODAL"}
else:
return context.window_manager.invoke_props_dialog(self)
self._last_filepath = ""
return super().invoke(context, event)
def check(self, context):
if not hasattr(self, "_last_filepath"):
self._last_filepath = ""
if self.filepath and self.filepath != self._last_filepath:
self._last_filepath = self.filepath
def execute(self, context):
if not getattr(self, "show_dimensions_dialog", False):
abs_path = Path(self.filepath).absolute().resolve()
if self.override_existing_image:
params = {"check_existing": True, "force_reload": True}
else:
params = {"check_existing": False}
try:
image = load_image(abs_path.name, str(abs_path.parent), **params)
if abs_path.exists() and abs_path.is_file():
image = load_image(abs_path.name, str(abs_path.parent), check_existing=False)
image_width_px = image.size[0]
image_height_px = image.size[1]
aspect_ratio = image_width_px / image_height_px
@@ -3893,17 +3857,23 @@ class AddReferenceImage(bpy.types.Operator, tool.Ifc.Operator, ImportHelper):
self.y_length = 1.0
bpy.data.images.remove(image)
return True
except Exception as e:
self.report({"ERROR"}, f"Failed to load image: {str(e)}")
return {"CANCELLED"}
return False
self.show_dimensions_dialog = True
return context.window_manager.invoke_props_dialog(self)
return self._execute(context)
def draw(self, context):
layout = self.layout
if Path(tool.Ifc.get_path()).is_file():
layout.prop(self, "use_relative_path")
else:
self.use_relative_path = False
layout.prop(self, "show_texture_solid_mode")
layout.prop(self, "x_length")
layout.prop(self, "y_length")
def _execute(self, context):
project_props = tool.Project.get_project_props()
project_props.load_indexed_maps = self.show_texture_solid_mode
space = tool.Blender.get_view3d_space()
if space.shading.color_type != "TEXTURE":
space.shading.color_type = "TEXTURE"
@@ -3916,121 +3886,66 @@ class AddReferenceImage(bpy.types.Operator, tool.Ifc.Operator, ImportHelper):
image_filepath = Path(tool.Ifc.get_uri(self.filepath, use_relative_path=self.use_relative_path))
ifc_file = tool.Ifc.get()
if self.override_existing_image:
params = {"check_existing": True, "force_reload": True}
else:
params = {"check_existing": False}
params = {"check_existing": False}
image = load_image(abs_path.name, str(abs_path.parent), **params)
def bm_add_image_plane(mesh):
bm = tool.Blender.get_bmesh_for_mesh(mesh, clean=True)
mesh = bpy.data.meshes.new(image_filepath.stem)
obj = bpy.data.objects.new(image_filepath.stem, mesh)
element = tool.Drawing.run_root_assign_class(
obj=obj, ifc_class="IfcAnnotation", predefined_type="IMAGE", should_add_representation=False
)
unit_scale = ifcopenshell.util.unit.calculate_unit_scale(ifc_file)
plane_scale = Vector((self.x_length * unit_scale / 2.0, self.y_length * unit_scale / 2.0, 1.0))
matrix = Matrix.LocRotScale(None, None, plane_scale)
bmesh.ops.create_grid(bm, x_segments=1, y_segments=1, size=1, matrix=matrix, calc_uvs=False)
builder = ifcopenshell.util.shape_builder.ShapeBuilder(ifc_file)
unit_scale = ifcopenshell.util.unit.calculate_unit_scale(ifc_file)
hx = self.x_length * 0.5 / unit_scale
hy = self.y_length * 0.5 / unit_scale
verts = [(-hx, -hy, 0.0), (hx, -hy, 0.0), (hx, hy, 0.0), (-hx, hy, 0.0)]
item = builder.mesh(verts, [[0, 1, 2, 3]])
if not bm.loops.layers.uv:
uv_layer = bm.loops.layers.uv.new()
else:
uv_layer = bm.loops.layers.uv.active
ifc_context = ifcopenshell.util.representation.get_context(ifc_file, "Model", "Body", "MODEL_VIEW")
representation = builder.get_representation(ifc_context, [item])
ifcopenshell.api.geometry.assign_representation(ifc_file, element, representation)
min_x = min(v.co.x for v in bm.verts)
max_x = max(v.co.x for v in bm.verts)
min_y = min(v.co.y for v in bm.verts)
max_y = max(v.co.y for v in bm.verts)
width = max_x - min_x
height = max_y - min_y
for face in bm.faces:
for loop in face.loops:
vert = loop.vert
u = (vert.co.x - min_x) / width if width > 0 else 0.5
v = (vert.co.y - min_y) / height if height > 0 else 0.5
u = max(0.0, min(1.0, u))
v = max(0.0, min(1.0, v))
loop[uv_layer].uv = (u, v)
tool.Blender.apply_bmesh(mesh, bm)
if self.use_existing_object_by_name:
obj = bpy.data.objects[self.use_existing_object_by_name]
bm_add_image_plane(obj.data)
bpy.ops.bim.update_representation(obj=obj.name, ifc_representation_class="")
else:
temp_mesh = bpy.data.meshes.new("temp_mesh")
bm_add_image_plane(temp_mesh)
obj = bpy.data.objects.new(image_filepath.stem, temp_mesh)
tool.Drawing.run_root_assign_class(
obj=obj,
ifc_class="IfcAnnotation",
predefined_type="IMAGE",
should_add_representation=True,
context=ifcopenshell.util.representation.get_context(ifc_file, "Model", "Body", "MODEL_VIEW"),
ifc_representation_class=None,
)
tool.Blender.remove_data_block(temp_mesh)
element = tool.Ifc.get_entity(obj)
if element and isinstance(obj.data, bpy.types.Mesh):
representation = ifcopenshell.util.representation.get_representation(element, "Model", "Body", "MODEL_VIEW")
if representation and representation.Items:
item_id = representation.Items[0].id()
num_faces = len(obj.data.polygons)
obj.data["ios_item_ids"] = [item_id] * num_faces
tool.Blender.Attribute.fill_attribute(obj.data, "ios_item_ids", "FACE", "INT", [item_id] * num_faces)
for item in representation.Items:
if item.is_a("IfcPolygonalFaceSet") and item.Coordinates:
new_coords = []
for vertex in obj.data.vertices:
co = obj.matrix_world @ vertex.co
new_coords.append([co.x, co.y, co.z])
item.Coordinates.CoordList = new_coords
tool.Blender.set_active_object(obj)
material = bpy.data.materials.new(name=image_filepath.stem)
obj.data.materials.append(None) # new slot
obj.material_slots[0].material = material
bpy.ops.bim.add_style()
style = tool.Ifc.get_entity(material)
assert style
tool.Style.assign_style_to_object(style, obj)
style = ifcopenshell.api.style.add_style(tool.Ifc.get(), name=image_filepath.stem)
ifcopenshell.api.style.assign_representation_styles(
ifc_file, shape_representation=representation, styles=[style]
)
# TODO: IfcSurfaceStyleRendering is unnecessary here, added it only because
# we don't support IfcSurfaceStyleWithTextures without Rendering yet
shading_attributes = {
"SurfaceColour": {
"Red": 1.0,
"Green": 1.0,
"Blue": 1.0,
},
"SurfaceColour": {"Red": 1.0, "Green": 1.0, "Blue": 1.0},
"Transparency": 0.0,
"ReflectanceMethod": "NOTDEFINED",
}
ifcopenshell.api.style.add_surface_style(
tool.Ifc.get(),
style=style,
ifc_class="IfcSurfaceStyleRendering",
attributes=shading_attributes,
tool.Ifc.get(), style=style, ifc_class="IfcSurfaceStyleRendering", attributes=shading_attributes
)
texture = ifc_file.create_entity("IfcImageTexture", Mode="DIFFUSE", URLReference=image_filepath.as_posix())
textures = [texture]
ifc_file.create_entity("IfcTextureCoordinateGenerator", Maps=textures, Mode="COORD") # UV map
ifcopenshell.api.style.add_surface_style(
ifc_file,
style=style,
ifc_class="IfcSurfaceStyleWithTextures",
attributes={"Textures": textures},
)
tool.Style.reload_material_from_ifc(material)
tool.Geometry.record_object_materials(obj)
return {"FINISHED"}
if tool.Ifc.get_schema() == "IFC2X3":
texture = ifc_file.create_entity(
"IfcImageTexture",
RepeatS=True,
RepeatT=True,
TextureType="TEXTURE",
UrlReference=image_filepath.as_posix(),
)
else:
texture = ifc_file.create_entity("IfcImageTexture", Mode="DIFFUSE", URLReference=image_filepath.as_posix())
ifc_file.create_entity("IfcTextureCoordinateGenerator", Maps=[texture], Mode="COORD")
textures = [texture]
ifcopenshell.api.style.add_surface_style(
ifc_file, style=style, ifc_class="IfcSurfaceStyleWithTextures", attributes={"Textures": textures}
)
logger = logging.getLogger("ImportIFC")
ifc_import_settings = bonsai.bim.import_ifc.IfcImportSettings.factory(bpy.context, None, logger)
ifc_importer = bonsai.bim.import_ifc.IfcImporter(ifc_import_settings)
ifc_importer.file = tool.Ifc.get()
ifc_importer.create_style(style)
bonsai.core.geometry.switch_representation(tool.Ifc, tool.Geometry, obj=obj, representation=representation)
class ConvertSVGToDXF(bpy.types.Operator):
+2 -8
View File
@@ -18,14 +18,11 @@
import enum
import json
import os
from collections.abc import Callable
from pathlib import Path
from typing import TYPE_CHECKING, Any, Literal, Union, get_args
from typing import TYPE_CHECKING, Any, Literal, Union
import bpy
import ifcopenshell
import ifcopenshell.api
import ifcopenshell.api.pset
import ifcopenshell.util.element
from bpy.props import (
@@ -34,7 +31,6 @@ from bpy.props import (
CollectionProperty,
EnumProperty,
FloatProperty,
FloatVectorProperty,
IntProperty,
PointerProperty,
StringProperty,
@@ -42,19 +38,17 @@ from bpy.props import (
from bpy.types import PropertyGroup
from mathutils import Matrix
import bonsai.bim.module.drawing.annotation as annotation
import bonsai.bim.module.drawing.decoration as decoration
import bonsai.core.drawing as core
import bonsai.tool as tool
from bonsai.bim.module.drawing.data import (
AnnotationData,
DecoratorData,
DrawingsData,
ElementValuesData,
SheetsData,
)
from bonsai.bim.module.drawing.data import refresh as refresh_drawing_data
from bonsai.bim.prop import Attribute, BIMFilterGroup, StrProperty
from bonsai.bim.prop import Attribute, BIMFilterGroup
diagram_scales_enum = []
@@ -22,7 +22,6 @@ import string
from pathlib import Path
from textwrap import wrap
import bpy
import openpyxl
import openpyxl.cell # Unnecessary, bug in typeshed.
import openpyxl.utils # Unnecessary, bug in typeshed.
@@ -33,7 +32,6 @@ from odf.table import Table, TableCell, TableColumn, TableRow
from odf.text import P
import bonsai.tool as tool
from bonsai.bim.ifc import IfcStore
from bonsai.bim.module.drawing.svgwriter import SvgWriter
DEBUG = False
@@ -335,12 +335,9 @@ class BaseLinesShader(BaseShader):
TYPE = "LINES"
DEF_GLSL = (
BaseShader.DEF_GLSL
+ """
DEF_GLSL = BaseShader.DEF_GLSL + """
#define GAP_SIZE {gap_size}
"""
)
GEOM_GLSL = """
layout(lines) in;
@@ -401,13 +398,10 @@ class DotsGizmoShader(GizmoShader):
TYPE = "POINTS"
DEF_GLSL = (
BaseShader.DEF_GLSL
+ """
DEF_GLSL = BaseShader.DEF_GLSL + """
#define CIRCLE_SEGMENTS 12
#define CIRCLE_RADIUS 8
"""
)
GEOM_GLSL = """
layout(points) in;
@@ -26,7 +26,6 @@ import xml.etree.ElementTree as ET
from pathlib import Path
from xml.dom import minidom
import bpy
import ifcopenshell.util.geolocation
import pystache
from mathutils import Vector
@@ -18,7 +18,6 @@
import math
import os
import re
import shutil
import xml.etree.ElementTree as ET
from collections.abc import Callable, Sequence
@@ -30,10 +29,8 @@ import bmesh
import bpy
import ifcopenshell
import ifcopenshell.util.element
import ifcopenshell.util.representation
import ifcopenshell.util.selector
import ifcopenshell.util.unit
import mathutils
import svgwrite
import svgwrite.container
import svgwrite.text
@@ -1026,7 +1023,8 @@ class SvgWriter:
for text_literal in text_literals:
text = tool.Drawing.replace_text_literal_variables(text_literal.Literal, product or element)
if newline_at:
text = helper.add_newline_between_words(text, newline_at)
text_segments = parse_markdown_it(text)
if len(text_segments) == 1 and text_segments[0]["url"] is None and not text_segments[0].get("break", False):
+1 -2
View File
@@ -30,7 +30,6 @@ from bonsai.bim.module.drawing.data import (
DocumentsData,
DrawingsData,
ElementFiltersData,
ElementValuesData,
ProductAssignmentsData,
SheetsData,
)
@@ -89,7 +88,7 @@ class BIM_PT_camera(Panel):
for link in links:
row = panel.row(align=True)
split = row.split(factor=0.9)
split.label(text=link.name, icon="FILE")
split.label(text=link.filepath, icon="FILE")
split.prop(link, "include_in_drawings", text="")
else:
panel.label(text="No IFC projects linked and loaded.")
-2
View File
@@ -16,8 +16,6 @@
# You should have received a copy of the GNU General Public License
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
import importlib
import os
import ifcfm
@@ -16,10 +16,7 @@
# You should have received a copy of the GNU General Public License
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
import json
import logging
import os
import tempfile
import bpy
import ifcfm
-4
View File
@@ -23,11 +23,7 @@ from bpy.props import (
BoolProperty,
CollectionProperty,
EnumProperty,
FloatProperty,
FloatVectorProperty,
IntProperty,
PointerProperty,
StringProperty,
)
from bpy.types import PropertyGroup
@@ -16,8 +16,6 @@
# You should have received a copy of the GNU General Public License
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
import math
import bpy
import ifcopenshell.util.element
from bpy.app.handlers import persistent
@@ -19,7 +19,6 @@
from collections.abc import Sequence
import blf
import bmesh
import bpy
import gpu
import ifcopenshell
@@ -16,22 +16,17 @@
# You should have received a copy of the GNU General Public License
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
from math import pi, pow
from math import pi
from typing import Any, Optional, TypeVar, Union
import bmesh
import bpy
import ifcopenshell
import ifcopenshell.util.shape
import ifcopenshell.util.unit
import mathutils
import numpy as np
import shapely
from ifcopenshell.util.shape_builder import ShapeBuilder
from mathutils import Matrix, Vector, geometry
import bonsai.tool as tool
T = TypeVar("T")
@@ -16,7 +16,6 @@
# You should have received a copy of the GNU General Public License
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
import re
from collections.abc import Sequence
from time import time
from typing import (
@@ -32,11 +31,9 @@ from typing import (
import bmesh
import bpy
import ifcopenshell
import ifcopenshell.api
import ifcopenshell.api.boundary
import ifcopenshell.api.drawing
import ifcopenshell.api.geometry
import ifcopenshell.api.grid
import ifcopenshell.api.group
import ifcopenshell.api.layer
import ifcopenshell.api.material
@@ -61,10 +58,8 @@ import bonsai.core.geometry as core
import bonsai.core.nest
import bonsai.core.root
import bonsai.core.spatial
import bonsai.core.style
import bonsai.tool as tool
from bonsai.bim.ifc import IfcStore
from bonsai.bim.module.model.data import AuthoringData
from bonsai.bim.module.model.decorator import ProfileDecorator
if TYPE_CHECKING:
@@ -902,6 +897,7 @@ class OverrideDelete(bpy.types.Operator):
if not is_valid_data_block:
continue
element = tool.Ifc.get_entity(obj)
if element:
if tool.Geometry.is_locked(element):
@@ -912,6 +908,9 @@ class OverrideDelete(bpy.types.Operator):
if ifcopenshell.util.element.get_pset(element, "BBIM_Array"):
self.report({"INFO"}, "Elements that are part of an array cannot be deleted.")
continue
if element.is_a("IfcDocumentReference"):
self.report({"INFO"}, "Linked models cannot be deleted.")
continue
if element.is_a("IfcGridAxis"):
# Deleting the last W axis is OK
if ((grid := element.PartOfU) and len(grid[0].UAxes) == 1) or (
@@ -1208,6 +1207,11 @@ class OverrideDuplicateMove(bpy.types.Operator):
operator.report({"ERROR"}, f"Drawing '{obj.name}' not duplicated.")
continue
if element.is_a("IfcDocumentReference"):
objects_to_remove.add(obj)
operator.report({"ERROR"}, f"Linked model '{obj.name}' not duplicated.")
continue
if tool.Geometry.is_locked(element):
objects_to_remove.add(obj)
operator.report({"ERROR"}, lock_error_message(obj.name))
@@ -24,8 +24,6 @@ from bpy.props import (
BoolProperty,
CollectionProperty,
EnumProperty,
FloatProperty,
FloatVectorProperty,
IntProperty,
PointerProperty,
StringProperty,
@@ -34,7 +32,6 @@ from bpy.types import PropertyGroup
import bonsai.tool as tool
from bonsai.bim.module.geometry.data import RepresentationsData, ViewportData
from bonsai.bim.prop import Attribute, ObjProperty, StrProperty
def get_contexts(self: "BIMObjectGeometryProperties", context: bpy.types.Context) -> list[tuple[str, str, str]]:
@@ -17,7 +17,6 @@
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
import bpy
import ifcopenshell.util.element
import ifcopenshell.util.geolocation
import ifcopenshell.util.schema
@@ -19,10 +19,7 @@
from math import radians
import blf
import bmesh
import bpy
import gpu
import ifcopenshell
import ifcopenshell.util.geolocation
from bpy.types import SpaceView3D
from bpy_extras.view3d_utils import location_3d_to_region_2d
@@ -21,7 +21,6 @@ from bpy_extras.io_utils import ImportHelper
import bonsai.core.georeference as core
import bonsai.tool as tool
from bonsai.bim.module.georeference.decorator import GeoreferenceDecorator
class AddGeoreferencing(bpy.types.Operator, tool.Ifc.Operator):
@@ -51,7 +50,7 @@ class RemoveGeoreferencing(bpy.types.Operator, tool.Ifc.Operator):
bl_description = "Remove the georeferencing"
def _execute(self, context):
core.remove_georeferencing(tool.Ifc)
core.remove_georeferencing(tool.Ifc, tool.Georeference)
class EditGeoreferencing(bpy.types.Operator, tool.Ifc.Operator):
@@ -23,11 +23,7 @@ import ifcopenshell.util.geolocation
from bpy.props import (
BoolProperty,
CollectionProperty,
EnumProperty,
FloatProperty,
FloatVectorProperty,
IntProperty,
PointerProperty,
StringProperty,
)
from bpy.types import PropertyGroup
@@ -224,16 +220,12 @@ class BIMGeoreferenceProperties(PropertyGroup):
x_axis_ordinate: StringProperty(name="X Axis Ordinate", update=update_grid_north_vector)
x_axis_is_null: BoolProperty(name="X Axis Is Null")
# These are only for reference to capture data about a host model from a linked model
# If you relink a model from a new host origin, we can autodetect it in theory with this
host_model_origin: StringProperty(name="Host Model Origin")
host_model_origin_si: StringProperty(name="Host Model Origin SI")
host_model_project_north: StringProperty(name="Host Model Angle to Grid North")
# This is the ENH in project units and SI units of the Blender session's 0,0,0.
# These are only for reference, using tool.Georeference.set_model_origin on
# project load, project create, and when linking for the first time from an
# empty Blender session.
model_is_georeferenced: BoolProperty(name="Model Is Georeferenced")
model_crs: StringProperty(name="Model CRS")
model_origin: StringProperty(name="Model Origin")
model_origin_si: StringProperty(name="Model Origin SI")
model_project_north: StringProperty(name="Model Angle to Grid North")
@@ -275,10 +267,6 @@ class BIMGeoreferenceProperties(PropertyGroup):
x_axis_ordinate: str
x_axis_is_null: bool
host_model_origin: str
host_model_origin_si: str
host_model_project_north: str
model_origin: str
model_origin_si: str
model_project_north: str
@@ -17,9 +17,6 @@
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
import bpy
import ifcopenshell
import ifcopenshell.util.cost
import ifcopenshell.util.element
import bonsai.tool as tool
@@ -16,10 +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/>.
from typing import TYPE_CHECKING, Literal, get_args
from typing import TYPE_CHECKING, get_args
import bpy
import ifcopenshell.api
import ifcopenshell.api.group
import ifcopenshell.util.element
+1 -5
View File
@@ -22,18 +22,14 @@ import bpy
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.pset.data import refresh as refresh_pset
from bonsai.bim.prop import Attribute, StrProperty
from bonsai.bim.prop import Attribute
def update_active_group_index(self, context):
@@ -1,8 +1,6 @@
import os
import shutil
import bpy
# import tool
import bonsai.tool as tool
@@ -19,7 +19,6 @@
from typing import Any
import bpy
import ifcopenshell
import bonsai.tool as tool
@@ -19,7 +19,6 @@
from typing import TYPE_CHECKING
import bpy
import ifcopenshell.api
import ifcopenshell.api.layer
import ifcopenshell.util.element
+1 -4
View File
@@ -23,16 +23,13 @@ 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 Attribute, StrProperty
from bonsai.bim.prop import Attribute
def update_layer_property(self: "Layer", context: bpy.types.Context, *, property: str) -> None:
@@ -17,7 +17,6 @@
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
import bpy
import ifcopenshell.api
import bonsai.core.library as core
import bonsai.tool as tool
+1 -5
View File
@@ -20,20 +20,16 @@ from typing import TYPE_CHECKING, Literal
import bpy
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.library.data import LibrariesData
from bonsai.bim.prop import Attribute, StrProperty
from bonsai.bim.prop import Attribute
def update_active_reference_index(self, context):
+1 -1
View File
@@ -28,7 +28,7 @@ import bonsai.tool as tool
from bonsai.bim.module.library.data import LibrariesData, LibraryReferencesData
if TYPE_CHECKING:
from bonsai.bim.module.library.prop import BIMLibraryProperties, LibraryReference
from bonsai.bim.module.library.prop import LibraryReference
class BIM_PT_libraries(Panel):
@@ -16,10 +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/>.
import importlib
import importlib.util
import stat
import traceback
from pathlib import Path
import bpy
@@ -16,9 +16,7 @@
# You should have received a copy of the GNU General Public License
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
import bpy
import ifcopenshell.util.geolocation
from mathutils import Vector
import bonsai.tool as tool
@@ -16,10 +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 math import degrees, radians
import blf
import bmesh
import bpy
import gpu
from bpy.types import SpaceView3D
@@ -16,14 +16,12 @@
# You should have received a copy of the GNU General Public License
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
import os
from typing import Any, Union
import bpy
import ifcopenshell
import ifcopenshell.util.doc
import ifcopenshell.util.element
import ifcopenshell.util.schema
from natsort import natsorted
import bonsai.tool as tool
@@ -20,7 +20,6 @@ import json
from typing import TYPE_CHECKING, Any, Literal, Union
import bpy
import ifcopenshell.api
import ifcopenshell.api.material
import ifcopenshell.api.profile
import ifcopenshell.api.style
@@ -19,25 +19,21 @@
from typing import TYPE_CHECKING
import bpy
import ifcopenshell
from bpy.props import (
BoolProperty,
CollectionProperty,
EnumProperty,
FloatProperty,
FloatVectorProperty,
IntProperty,
PointerProperty,
StringProperty,
)
from bpy.types import PropertyGroup
from ifcopenshell.util.doc import get_entity_doc
import bonsai.tool as tool
from bonsai.bim.module.classification.data import MaterialClassificationsData
from bonsai.bim.module.material.data import MaterialsData, ObjectMaterialData
from bonsai.bim.module.profile.data import ProfileData
from bonsai.bim.prop import Attribute, StrProperty
from bonsai.bim.prop import Attribute
def get_profile_classes(self, context):
@@ -22,7 +22,6 @@ from typing import TYPE_CHECKING, Any
import bpy
import ifcopenshell.util.element
import ifcopenshell.util.unit
from bpy.types import Panel, UIList
import bonsai.bim.helper
@@ -19,12 +19,11 @@
from typing import TYPE_CHECKING, Literal, assert_never, get_args
import bpy
import ifcopenshell
import ifcopenshell.util.geolocation
import ifcopenshell.util.placement
import ifcopenshell.util.unit
import numpy as np
from mathutils import Euler, Matrix, Vector
from mathutils import Matrix
import bonsai.core.geometry as core_geometry
import bonsai.core.misc as core
@@ -16,21 +16,12 @@
# You should have received a copy of the GNU General Public License
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
import bpy
from bpy.props import (
BoolProperty,
CollectionProperty,
EnumProperty,
FloatProperty,
FloatVectorProperty,
IntProperty,
PointerProperty,
StringProperty,
)
from bpy.types import PropertyGroup
from bonsai.bim.prop import Attribute, StrProperty
class BIMMiscProperties(PropertyGroup):
total_storeys: IntProperty(
+1 -3
View File
@@ -19,12 +19,10 @@
import json
import bpy
import ifcopenshell
import ifcopenshell.api
import ifcopenshell.api.pset
import ifcopenshell.util.element
import ifcopenshell.util.unit
from mathutils import Matrix, Vector
from mathutils import Matrix
import bonsai.tool as tool
@@ -18,8 +18,6 @@
import bpy
import ifcopenshell
import ifcopenshell.util.element
import bonsai.core.covering as core
import bonsai.tool as tool
+4 -4
View File
@@ -25,7 +25,7 @@ import bpy
import ifcopenshell
import ifcopenshell.util.element
import ifcopenshell.util.schema
from ifcopenshell.util.doc import get_entity_doc, get_predefined_type_doc
from ifcopenshell.util.doc import get_entity_doc
from natsort import natsorted
import bonsai.tool as tool
@@ -424,12 +424,12 @@ class SverchokData:
return tool.Model.get_modeling_bbim_pset_data(bpy.context.active_object, "BBIM_Sverchok")
@classmethod
def has_sverchok(cls):
def has_sverchok(cls) -> bool:
try:
import sverchok
import sverchok # noqa: F401
return True
except:
except ModuleNotFoundError:
return False
@@ -19,9 +19,8 @@
from __future__ import annotations
import math
from itertools import chain
from math import cos, radians, sin, tan
from typing import Any, Literal, Union
from typing import Any, Literal
import blf
import bmesh
@@ -466,13 +465,14 @@ class PolylineDecorator:
self.addon_prefs = tool.Blender.get_addon_preferences()
self.font_id = 0
font_size = tool.Blender.scale_font_size(12)
font_size = tool.Blender.scale_font_size()
offset = tool.Blender.scale_font_size() * 1.5
line_height = tool.Blender.scale_font_size() * 1.25
blf.size(self.font_id, font_size)
blf.enable(self.font_id, blf.SHADOW)
blf.shadow(self.font_id, 6, 0, 0, 0, 1)
color = self.addon_prefs.decorations_colour
color_highlight = self.addon_prefs.decorator_color_special
offset = 20
new_line = 0
for i, (key, field_name) in enumerate(texts.items()):
formatted_value = None
@@ -480,7 +480,7 @@ class PolylineDecorator:
# Controls which options are displayed in the UI
if key not in self.input_ui.input_options:
continue
new_line += 20
new_line += line_height
if self.tool_state and key != self.tool_state.input_type:
formatted_value = self.input_ui.get_formatted_value(key)
else:
@@ -515,7 +515,7 @@ class PolylineDecorator:
self.addon_prefs = tool.Blender.get_addon_preferences()
self.font_id = 1
self.shader = gpu.shader.from_builtin("UNIFORM_COLOR")
font_size = tool.Blender.scale_font_size(12)
font_size = tool.Blender.scale_font_size()
blf.size(self.font_id, font_size)
blf.enable(self.font_id, blf.SHADOW)
blf.shadow(self.font_id, 6, 0, 0, 0, 1)
@@ -1076,7 +1076,7 @@ class ProductDecorator:
data["verts"] = []
# Verts
polyline_vertices = []
polyline_vertices: list[Vector] = []
polyline_props = tool.Model.get_polyline_props()
polyline_data = polyline_props.insertion_polyline
polyline_points = polyline_data[0].polyline_points if polyline_data else []
@@ -1196,7 +1196,7 @@ class ProductDecorator:
data = {}
data["verts"] = []
# Verts
polyline_vertices = []
polyline_vertices: list[Vector] = []
polyline_props = tool.Model.get_polyline_props()
polyline_data = polyline_props.insertion_polyline
polyline_points = polyline_data[0].polyline_points if polyline_data else []
@@ -1936,7 +1936,7 @@ class BoundingBoxDecorator:
addon_prefs = tool.Blender.get_addon_preferences()
font_id = 0
font_size = tool.Blender.scale_font_size(12)
font_size = tool.Blender.scale_font_size()
blf.size(font_id, font_size)
blf.enable(font_id, blf.SHADOW)
blf.shadow(font_id, 6, 0, 0, 0, 1)

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