mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-14 19:34:34 +00:00
typing
This commit is contained in:
@@ -29,6 +29,7 @@ import numpy.typing as npt
|
||||
import multiprocessing
|
||||
import ifcopenshell
|
||||
import ifcopenshell.geom
|
||||
import ifcopenshell.ifcopenshell_wrapper as W
|
||||
import ifcopenshell.util.unit
|
||||
import ifcopenshell.util.element
|
||||
import ifcopenshell.util.geolocation
|
||||
@@ -1032,9 +1033,9 @@ class IfcImporter:
|
||||
def create_curve(
|
||||
self,
|
||||
element: ifcopenshell.entity_instance,
|
||||
shape: Union[ifcopenshell.geom.ShapeElementType, ifcopenshell.geom.ShapeType],
|
||||
shape: Union[W.Triangulation, W.TriangulationElement],
|
||||
) -> bpy.types.Curve:
|
||||
if isinstance(shape, ifcopenshell.geom.ShapeElementType):
|
||||
if isinstance(shape, W.TriangulationElement):
|
||||
geometry = shape.geometry
|
||||
else:
|
||||
geometry = shape
|
||||
|
||||
@@ -41,7 +41,7 @@ class SearchBSDDClassifications(bpy.types.Operator):
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def execute(self, context):
|
||||
total = core.search_bsdd_class(tool.Bsdd, context.scene.BIMBSDDProperties.keyword)
|
||||
total = core.search_bsdd_class(tool.Bsdd, tool.Bsdd.get_bsdd_props().keyword)
|
||||
self.report({"INFO"}, f"{total} bSDD classes found.")
|
||||
return {"FINISHED"}
|
||||
|
||||
@@ -71,7 +71,7 @@ class SearchBSDDProperties(bpy.types.Operator):
|
||||
|
||||
def execute(self, context):
|
||||
props = tool.Bsdd.get_bsdd_props()
|
||||
core.search_bsdd_properties(tool.Bsdd, context.scene.BIMBSDDProperties.keyword, self.obj, self.obj_type)
|
||||
core.search_bsdd_properties(tool.Bsdd, tool.Bsdd.get_bsdd_props().keyword, self.obj, self.obj_type)
|
||||
self.report({"INFO"}, f"{len(props.properties)} bSDD properties found.")
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ from bpy.props import (
|
||||
FloatVectorProperty,
|
||||
CollectionProperty,
|
||||
)
|
||||
from typing import Union
|
||||
from typing import Union, TYPE_CHECKING, Literal
|
||||
|
||||
|
||||
def get_active_dictionary(self, context):
|
||||
@@ -54,27 +54,41 @@ def update_active_class_index(self: "BIMBSDDProperties", context: bpy.types.Cont
|
||||
|
||||
|
||||
class BSDDDictionary(PropertyGroup):
|
||||
name: StringProperty(name="Name")
|
||||
uri: StringProperty(name="URI")
|
||||
default_language_code: StringProperty(name="Language")
|
||||
organization_name_owner: StringProperty(name="Organization")
|
||||
status: StringProperty(name="Status")
|
||||
version: StringProperty(name="Version")
|
||||
is_active: BoolProperty(
|
||||
name="Is Active", description="Enable to search with this dictionary", default=False, update=update_is_active
|
||||
name="Is Active",
|
||||
description="Enable to search with this dictionary",
|
||||
default=False,
|
||||
update=update_is_active,
|
||||
)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
uri: str
|
||||
default_language_code: str
|
||||
organization_name_owner: str
|
||||
status: str
|
||||
version: str
|
||||
is_active: bool
|
||||
|
||||
|
||||
class BSDDClassification(PropertyGroup):
|
||||
name: StringProperty(name="Name")
|
||||
reference_code: StringProperty(name="Reference Code")
|
||||
uri: StringProperty(name="URI")
|
||||
dictionary_name: StringProperty(name="Dictionary Name")
|
||||
dictionary_namespace_uri: StringProperty(name="Dictionary Namespace URI")
|
||||
|
||||
if TYPE_CHECKING:
|
||||
reference_code: str
|
||||
uri: str
|
||||
dictionary_name: str
|
||||
dictionary_namespace_uri: str
|
||||
|
||||
|
||||
class BSDDProperty(PropertyGroup):
|
||||
name: StringProperty(name="Name")
|
||||
code: StringProperty(name="Code")
|
||||
uri: StringProperty(name="URI")
|
||||
pset: StringProperty(name="Pset")
|
||||
@@ -82,11 +96,19 @@ class BSDDProperty(PropertyGroup):
|
||||
name="Is Selected", description="Select to add or edit this property", default=False, update=update_is_selected
|
||||
)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
code: str
|
||||
uri: str
|
||||
pset: str
|
||||
is_selected: bool
|
||||
|
||||
|
||||
class BSDDPset(PropertyGroup):
|
||||
name: StringProperty(name="Name")
|
||||
properties: CollectionProperty(name="Properties", type=Attribute)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
properties: bpy.types.bpy_prop_collection_idprop[Attribute]
|
||||
|
||||
|
||||
class BIMBSDDProperties(PropertyGroup):
|
||||
active_dictionary: StringProperty(name="Active Dictionary")
|
||||
@@ -131,6 +153,28 @@ class BIMBSDDProperties(PropertyGroup):
|
||||
)
|
||||
classification_psets: CollectionProperty(name="Classification Psets", type=BSDDPset)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
active_dictionary: str
|
||||
active_dictionary: str
|
||||
active_uri: str
|
||||
dictionaries: bpy.types.bpy_prop_collection_idprop[BSDDDictionary]
|
||||
active_dictionary_index: int
|
||||
classifications: bpy.types.bpy_prop_collection_idprop[BSDDClassification]
|
||||
active_classification_index: int
|
||||
property_filter_mode: Literal["CLASS", "KEYWORD"]
|
||||
classes: bpy.types.bpy_prop_collection_idprop[BSDDClassification]
|
||||
active_class_index: int
|
||||
properties: bpy.types.bpy_prop_collection_idprop[BSDDProperty]
|
||||
active_property_index: int
|
||||
selected_properties: bpy.types.bpy_prop_collection_idprop[Attribute]
|
||||
keyword: str
|
||||
should_filter_ifc_class: bool
|
||||
use_only_ifc_properties: bool
|
||||
load_preview_dictionaries: bool
|
||||
load_inactive_dictionaries: bool
|
||||
load_test_dictionaries: bool
|
||||
classification_psets: bpy.types.bpy_prop_collection_idprop[BSDDPset]
|
||||
|
||||
@property
|
||||
def active_class(self) -> Union[BSDDClassification, None]:
|
||||
return tool.Blender.get_active_uilist_element(self.classes, self.active_class_index)
|
||||
|
||||
@@ -16,9 +16,15 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from __future__ import annotations
|
||||
import bpy
|
||||
import bonsai.tool as tool
|
||||
from bonsai.bim.module.bsdd.data import BSDDData
|
||||
from bpy.types import Panel, UIList
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from bonsai.bim.module.bsdd.prop import BIMBSDDProperties, BSDDDictionary, BSDDClassification, BSDDProperty
|
||||
|
||||
|
||||
class BIM_PT_bsdd(Panel):
|
||||
@@ -33,7 +39,8 @@ class BIM_PT_bsdd(Panel):
|
||||
def draw(self, context):
|
||||
if not BSDDData.is_loaded:
|
||||
BSDDData.load()
|
||||
props = context.scene.BIMBSDDProperties
|
||||
props = tool.Bsdd.get_bsdd_props()
|
||||
assert self.layout
|
||||
layout = self.layout
|
||||
if len(props.dictionaries):
|
||||
row = self.layout.row()
|
||||
@@ -70,9 +77,17 @@ class BIM_PT_bsdd(Panel):
|
||||
|
||||
|
||||
class BIM_UL_bsdd_dictionaries(UIList):
|
||||
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
|
||||
def draw_item(
|
||||
self,
|
||||
context,
|
||||
layout: bpy.types.UILayout,
|
||||
data: BIMBSDDProperties,
|
||||
item: BSDDDictionary,
|
||||
icon,
|
||||
active_data,
|
||||
active_propname,
|
||||
) -> None:
|
||||
if item:
|
||||
props = context.scene.BIMBSDDProperties
|
||||
row = layout.row(align=True)
|
||||
if item.status != "Active":
|
||||
row.label(
|
||||
@@ -86,7 +101,16 @@ class BIM_UL_bsdd_dictionaries(UIList):
|
||||
|
||||
|
||||
class BIM_UL_bsdd_classifications(UIList):
|
||||
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
|
||||
def draw_item(
|
||||
self,
|
||||
context,
|
||||
layout: bpy.types.UILayout,
|
||||
data: BIMBSDDProperties,
|
||||
item: BSDDClassification,
|
||||
icon,
|
||||
active_data,
|
||||
active_propname,
|
||||
) -> None:
|
||||
if item:
|
||||
row = layout.row(align=True)
|
||||
row.label(text=item.reference_code)
|
||||
@@ -95,7 +119,16 @@ class BIM_UL_bsdd_classifications(UIList):
|
||||
|
||||
|
||||
class BIM_UL_bsdd_classes(UIList):
|
||||
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
|
||||
def draw_item(
|
||||
self,
|
||||
context,
|
||||
layout: bpy.types.UILayout,
|
||||
data: BIMBSDDProperties,
|
||||
item: BSDDClassification,
|
||||
icon,
|
||||
active_data,
|
||||
active_propname,
|
||||
) -> None:
|
||||
if item:
|
||||
row = layout.row(align=True)
|
||||
row.label(text=item.name)
|
||||
@@ -103,7 +136,16 @@ class BIM_UL_bsdd_classes(UIList):
|
||||
|
||||
|
||||
class BIM_UL_bsdd_properties(UIList):
|
||||
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
|
||||
def draw_item(
|
||||
self,
|
||||
context,
|
||||
layout: bpy.types.UILayout,
|
||||
data: BIMBSDDProperties,
|
||||
item: BSDDProperty,
|
||||
icon,
|
||||
active_data,
|
||||
active_propname,
|
||||
) -> None:
|
||||
if item:
|
||||
row = layout.row(align=True)
|
||||
name = item.name
|
||||
|
||||
@@ -83,7 +83,7 @@ class ReferencesData:
|
||||
def active_classification_library(cls):
|
||||
if not IfcStore.classification_file or not IfcStore.classification_file.by_type("IfcClassification"):
|
||||
return False
|
||||
props = bpy.context.scene.BIMClassificationProperties
|
||||
props = tool.Classification.get_classification_props()
|
||||
name = IfcStore.classification_file.by_id(int(props.available_classifications)).Name
|
||||
if name in [e.Name for e in tool.Ifc.get().by_type("IfcClassification")]:
|
||||
return name
|
||||
|
||||
@@ -47,7 +47,7 @@ class AddClassification(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def _execute(self, context):
|
||||
props = context.scene.BIMClassificationProperties
|
||||
props = tool.Classification.get_classification_props()
|
||||
ifcopenshell.api.classification.add_classification(
|
||||
tool.Ifc.get(),
|
||||
classification=IfcStore.classification_file.by_id(int(props.available_classifications)),
|
||||
@@ -60,7 +60,7 @@ class AddManualClassification(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def _execute(self, context):
|
||||
props = context.scene.BIMClassificationProperties
|
||||
props = tool.Classification.get_classification_props()
|
||||
attributes = bonsai.bim.helper.export_attributes(props.classification_attributes)
|
||||
classification = ifcopenshell.api.classification.add_classification(tool.Ifc.get(), classification="Unnamed")
|
||||
ifcopenshell.api.classification.edit_classification(
|
||||
@@ -84,7 +84,7 @@ class AddManualClassificationReference(bpy.types.Operator, tool.Ifc.Operator):
|
||||
objects = [context.active_object.name]
|
||||
else:
|
||||
objects = [self.obj]
|
||||
props = context.scene.BIMClassificationReferenceProperties
|
||||
props = tool.Classification.get_classification_reference_props()
|
||||
attributes = bonsai.bim.helper.export_attributes(props.reference_attributes)
|
||||
products = [
|
||||
tool.Ifc.get().by_id(ifc_definition_id)
|
||||
@@ -110,7 +110,7 @@ class AddClassificationFromBSDD(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def _execute(self, context):
|
||||
cprops = context.scene.BIMClassificationProperties
|
||||
cprops = tool.Classification.get_classification_props()
|
||||
bprops = tool.Bsdd.get_bsdd_props()
|
||||
if cprops.classification_source == "BSDD":
|
||||
dictionaries = [d.uri for d in bprops.dictionaries if d.is_active]
|
||||
@@ -142,7 +142,7 @@ class EnableAddingManualClassification(bpy.types.Operator):
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def execute(self, context):
|
||||
props = context.scene.BIMClassificationProperties
|
||||
props = tool.Classification.get_classification_props()
|
||||
props.is_adding = True
|
||||
props.active_classification_id = 0
|
||||
props.classification_attributes.clear()
|
||||
@@ -156,7 +156,7 @@ class DisableAddingManualClassification(bpy.types.Operator):
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def execute(self, context):
|
||||
props = context.scene.BIMClassificationProperties
|
||||
props = tool.Classification.get_classification_props()
|
||||
props.is_adding = False
|
||||
return {"FINISHED"}
|
||||
|
||||
@@ -167,7 +167,7 @@ class EnableAddingManualClassificationReference(bpy.types.Operator):
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def execute(self, context):
|
||||
props = context.scene.BIMClassificationReferenceProperties
|
||||
props = tool.Classification.get_classification_reference_props()
|
||||
props.is_adding = True
|
||||
props.reference_attributes.clear()
|
||||
bonsai.bim.helper.import_attributes2("IfcClassificationReference", props.reference_attributes)
|
||||
@@ -180,7 +180,7 @@ class DisableAddingManualClassificationReference(bpy.types.Operator):
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def execute(self, context):
|
||||
props = context.scene.BIMClassificationReferenceProperties
|
||||
props = tool.Classification.get_classification_reference_props()
|
||||
props.is_adding = False
|
||||
return {"FINISHED"}
|
||||
|
||||
@@ -203,7 +203,7 @@ class EnableEditingClassification(bpy.types.Operator):
|
||||
new.string_value = "" if new.is_null else json.dumps(data[name])
|
||||
return True
|
||||
|
||||
props = context.scene.BIMClassificationProperties
|
||||
props = tool.Classification.get_classification_props()
|
||||
props.classification_attributes.clear()
|
||||
bonsai.bim.helper.import_attributes2(
|
||||
tool.Ifc.get().by_id(self.classification), props.classification_attributes, callback
|
||||
@@ -218,7 +218,8 @@ class DisableEditingClassification(bpy.types.Operator):
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def execute(self, context):
|
||||
context.scene.BIMClassificationProperties.active_classification_id = 0
|
||||
props = tool.Classification.get_classification_props()
|
||||
props.active_classification_id = 0
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
@@ -246,7 +247,7 @@ class EditClassification(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def _execute(self, context):
|
||||
props = context.scene.BIMClassificationProperties
|
||||
props = tool.Classification.get_classification_props()
|
||||
|
||||
def callback(attributes, prop):
|
||||
if prop.name == "ReferenceTokens":
|
||||
@@ -271,7 +272,7 @@ class EnableEditingClassificationReference(bpy.types.Operator):
|
||||
obj: bpy.props.StringProperty()
|
||||
|
||||
def execute(self, context):
|
||||
props = context.scene.BIMClassificationReferenceProperties
|
||||
props = tool.Classification.get_classification_reference_props()
|
||||
props.reference_attributes.clear()
|
||||
bonsai.bim.helper.import_attributes2(tool.Ifc.get().by_id(self.reference), props.reference_attributes)
|
||||
props.active_reference_id = self.reference
|
||||
@@ -285,7 +286,7 @@ class DisableEditingClassificationReference(bpy.types.Operator):
|
||||
obj: bpy.props.StringProperty()
|
||||
|
||||
def execute(self, context):
|
||||
context.scene.BIMClassificationReferenceProperties.active_reference_id = 0
|
||||
tool.Classification.get_classification_reference_props().active_reference_id = 0
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
@@ -337,7 +338,7 @@ class EditClassificationReference(bpy.types.Operator, tool.Ifc.Operator):
|
||||
obj: bpy.props.StringProperty()
|
||||
|
||||
def _execute(self, context):
|
||||
props = context.scene.BIMClassificationReferenceProperties
|
||||
props = tool.Classification.get_classification_reference_props()
|
||||
attributes = bonsai.bim.helper.export_attributes(props.reference_attributes)
|
||||
ifc_file = tool.Ifc.get()
|
||||
ifcopenshell.api.classification.edit_reference(
|
||||
@@ -364,7 +365,7 @@ class AddClassificationReference(bpy.types.Operator, tool.Ifc.Operator):
|
||||
objects = [context.active_object.name]
|
||||
else:
|
||||
objects = [self.obj]
|
||||
props = context.scene.BIMClassificationProperties
|
||||
props = tool.Classification.get_classification_props()
|
||||
classification = None
|
||||
classification_name = IfcStore.classification_file.by_id(int(props.available_classifications)).Name
|
||||
for element in tool.Ifc.get().by_type("IfcClassification"):
|
||||
@@ -405,8 +406,7 @@ class AddClassificationReferenceFromBSDD(bpy.types.Operator, tool.Ifc.Operator):
|
||||
objects = [context.active_object.name]
|
||||
else:
|
||||
objects = [self.obj]
|
||||
props = context.scene.BIMClassificationProperties
|
||||
bprops = context.scene.BIMBSDDProperties
|
||||
bprops = tool.Bsdd.get_bsdd_props()
|
||||
use_only_ifc_properties: bool = bprops.use_only_ifc_properties
|
||||
|
||||
bsdd_classification = bprops.classifications[bprops.active_classification_index]
|
||||
@@ -487,7 +487,7 @@ class ChangeClassificationLevel(bpy.types.Operator):
|
||||
parent_id: bpy.props.IntProperty()
|
||||
|
||||
def execute(self, context):
|
||||
props = context.scene.BIMClassificationProperties
|
||||
props = tool.Classification.get_classification_props()
|
||||
props.available_library_references.clear()
|
||||
for reference in IfcStore.classification_file.by_id(self.parent_id).HasReferences:
|
||||
new = props.available_library_references.add()
|
||||
@@ -509,6 +509,6 @@ class DisableEditingClassificationReferences(bpy.types.Operator):
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def execute(self, context):
|
||||
props = context.scene.BIMClassificationProperties
|
||||
props = tool.Classification.get_classification_props()
|
||||
props.available_library_references.clear()
|
||||
return {"FINISHED"}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import bpy
|
||||
import bonsai.tool as tool
|
||||
from bonsai.bim.prop import Attribute
|
||||
from bonsai.bim.module.classification.data import ClassificationsData, ClassificationReferencesData
|
||||
from bpy.types import PropertyGroup
|
||||
@@ -30,9 +31,12 @@ from bpy.props import (
|
||||
FloatVectorProperty,
|
||||
CollectionProperty,
|
||||
)
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
|
||||
def get_available_classifications(self, context):
|
||||
def get_available_classifications(
|
||||
self: "BIMClassificationProperties", context: bpy.types.Context
|
||||
) -> tool.Blender.BLENDER_ENUM_ITEMS:
|
||||
if not ClassificationsData.is_loaded:
|
||||
ClassificationsData.load()
|
||||
return ClassificationsData.data["available_classifications"]
|
||||
@@ -44,19 +48,26 @@ def get_classifications(self, context):
|
||||
return ClassificationReferencesData.data["classifications"]
|
||||
|
||||
|
||||
def get_classification_source(self, context):
|
||||
def get_classification_source(
|
||||
self: "BIMClassificationProperties", context: bpy.types.Context
|
||||
) -> tool.Blender.BLENDER_ENUM_ITEMS:
|
||||
if not ClassificationsData.is_loaded:
|
||||
ClassificationsData.load()
|
||||
return ClassificationsData.data["classification_source"]
|
||||
|
||||
|
||||
class ClassificationReference(PropertyGroup):
|
||||
name: StringProperty(name="Name")
|
||||
identification: StringProperty(name="Identification")
|
||||
ifc_definition_id: IntProperty(name="IFC Definition ID")
|
||||
has_references: BoolProperty(name="Has References")
|
||||
referenced_source: IntProperty(name="IFC Definition ID")
|
||||
|
||||
if TYPE_CHECKING:
|
||||
identification: str
|
||||
ifc_definition_id: int
|
||||
has_references: bool
|
||||
referenced_source: int
|
||||
|
||||
|
||||
class BIMClassificationProperties(PropertyGroup):
|
||||
is_adding: BoolProperty(name="Is Adding", default=False)
|
||||
@@ -68,9 +79,25 @@ class BIMClassificationProperties(PropertyGroup):
|
||||
active_library_referenced_source: IntProperty(name="Active Library Referenced Source")
|
||||
active_library_reference_index: IntProperty(name="Active Library Reference Index")
|
||||
|
||||
if TYPE_CHECKING:
|
||||
is_adding: bool
|
||||
classification_source: str
|
||||
available_classifications: str
|
||||
classification_attributes: bpy.types.bpy_prop_collection_idprop[Attribute]
|
||||
active_classification_id: int
|
||||
available_library_references: bpy.types.bpy_prop_collection_idprop[ClassificationReference]
|
||||
active_library_referenced_source: int
|
||||
active_library_reference_index: int
|
||||
|
||||
|
||||
class BIMClassificationReferenceProperties(PropertyGroup):
|
||||
is_adding: BoolProperty(name="Is Adding", default=False)
|
||||
classifications: EnumProperty(items=get_classifications, name="Classifications")
|
||||
reference_attributes: CollectionProperty(name="Reference Attributes", type=Attribute)
|
||||
active_reference_id: IntProperty(name="Active Reference Id")
|
||||
|
||||
if TYPE_CHECKING:
|
||||
is_adding: bool
|
||||
classifications: str
|
||||
reference_attributes: bpy.types.bpy_prop_collection_idprop
|
||||
active_reference_id: int
|
||||
|
||||
@@ -16,6 +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/>.
|
||||
|
||||
from __future__ import annotations
|
||||
import bpy
|
||||
import bonsai.bim.helper
|
||||
import bonsai.tool as tool
|
||||
@@ -27,6 +28,10 @@ from bonsai.bim.module.classification.data import (
|
||||
MaterialClassificationsData,
|
||||
CostClassificationsData,
|
||||
)
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from bonsai.bim.module.classification.prop import BIMClassificationProperties, ClassificationReference
|
||||
|
||||
|
||||
class BIM_PT_classifications(Panel):
|
||||
@@ -46,7 +51,8 @@ class BIM_PT_classifications(Panel):
|
||||
if not ClassificationsData.is_loaded:
|
||||
ClassificationsData.load()
|
||||
|
||||
self.props = context.scene.BIMClassificationProperties
|
||||
self.props = tool.Classification.get_classification_props()
|
||||
assert self.layout
|
||||
|
||||
row = self.layout.row(align=True)
|
||||
row.label(text="Source", icon="OUTLINER")
|
||||
@@ -110,9 +116,9 @@ class ReferenceUI:
|
||||
|
||||
def draw_ui(self, context):
|
||||
obj = context.active_object
|
||||
self.sprops = context.scene.BIMClassificationProperties
|
||||
self.bprops = context.scene.BIMBSDDProperties
|
||||
self.props = context.scene.BIMClassificationReferenceProperties
|
||||
self.sprops = tool.Classification.get_classification_props()
|
||||
self.bprops = tool.Bsdd.get_bsdd_props()
|
||||
self.props = tool.Classification.get_classification_reference_props()
|
||||
self.file = tool.Ifc.get()
|
||||
|
||||
self.draw_add_ui(context)
|
||||
@@ -315,7 +321,16 @@ class BIM_PT_cost_classifications(Panel, ReferenceUI):
|
||||
|
||||
|
||||
class BIM_UL_classifications(UIList):
|
||||
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
|
||||
def draw_item(
|
||||
self,
|
||||
context,
|
||||
layout: bpy.types.UILayout,
|
||||
data: BIMClassificationProperties,
|
||||
item: ClassificationReference,
|
||||
icon,
|
||||
active_data,
|
||||
active_propname,
|
||||
):
|
||||
if item:
|
||||
if item.has_references:
|
||||
op = layout.operator("bim.change_classification_level", text="", icon="DISCLOSURE_TRI_RIGHT")
|
||||
|
||||
@@ -255,7 +255,7 @@ class BIM_PT_object_psets(Panel):
|
||||
ObjectPsetsData.load()
|
||||
|
||||
props = context.active_object.PsetProperties
|
||||
self.bprops = context.scene.BIMBSDDProperties
|
||||
self.bprops = tool.Bsdd.get_bsdd_props()
|
||||
row = self.layout.row(align=True)
|
||||
prop_with_search(row, props, "pset_name", text="")
|
||||
if props.pset_name != "BBIM_BSDD" and not props.pset_name.startswith(tool.Bsdd.identifier_url):
|
||||
|
||||
@@ -26,20 +26,20 @@ if TYPE_CHECKING:
|
||||
import bonsai.tool as tool
|
||||
|
||||
|
||||
def import_bsdd_classes(bsdd: tool.Bsdd, obj, obj_type) -> int:
|
||||
def import_bsdd_classes(bsdd: type[tool.Bsdd], obj, obj_type) -> int:
|
||||
return bsdd.import_classes(obj, obj_type)
|
||||
|
||||
|
||||
def search_bsdd_properties(bsdd: tool.Bsdd, keyword: str, obj, obj_type) -> int:
|
||||
def search_bsdd_properties(bsdd: type[tool.Bsdd], keyword: str, obj, obj_type) -> int:
|
||||
return bsdd.import_properties(obj, obj_type, keyword)
|
||||
|
||||
|
||||
def load_bsdd(bsdd: tool.Bsdd) -> None:
|
||||
def load_bsdd(bsdd: type[tool.Bsdd]) -> None:
|
||||
bsdd.clear_dictionaries()
|
||||
bsdd.create_dictionaries(bsdd.get_dictionaries())
|
||||
|
||||
|
||||
def search_bsdd_class(bsdd: tool.Bsdd, keyword: str) -> int:
|
||||
def search_bsdd_class(bsdd: type[tool.Bsdd], keyword: str) -> int:
|
||||
bsdd.clear_classes()
|
||||
related_entities = bsdd.get_related_ifc_entities()
|
||||
return bsdd.search_class(keyword, related_entities)
|
||||
|
||||
@@ -32,7 +32,11 @@ if TYPE_CHECKING:
|
||||
|
||||
|
||||
def unjoin_walls(
|
||||
ifc: tool.Ifc, blender: tool.Blender, geometry: tool.Geometry, joiner: DumbWallJoiner, model: tool.Model
|
||||
ifc: type[tool.Ifc],
|
||||
blender: type[tool.Blender],
|
||||
geometry: type[tool.Geometry],
|
||||
joiner: DumbWallJoiner,
|
||||
model: type[tool.Model],
|
||||
) -> None:
|
||||
"""Unjoin selected walls."""
|
||||
for obj in blender.get_selected_objects():
|
||||
@@ -45,11 +49,11 @@ def unjoin_walls(
|
||||
|
||||
|
||||
def extend_walls(
|
||||
ifc: tool.Ifc,
|
||||
blender: tool.Blender,
|
||||
geometry: tool.Geometry,
|
||||
ifc: type[tool.Ifc],
|
||||
blender: type[tool.Blender],
|
||||
geometry: type[tool.Geometry],
|
||||
joiner: DumbWallJoiner,
|
||||
model: tool.Model,
|
||||
model: type[tool.Model],
|
||||
target: Vector,
|
||||
connection: Optional[str] = None,
|
||||
) -> None:
|
||||
@@ -62,11 +66,11 @@ def extend_walls(
|
||||
|
||||
|
||||
def join_walls_LV(
|
||||
ifc: tool.Ifc,
|
||||
blender: tool.Blender,
|
||||
geometry: tool.Geometry,
|
||||
ifc: type[tool.Ifc],
|
||||
blender: type[tool.Blender],
|
||||
geometry: type[tool.Geometry],
|
||||
joiner: DumbWallJoiner,
|
||||
model: tool.Model,
|
||||
model: type[tool.Model],
|
||||
join_type: Literal["L", "V"] = "L",
|
||||
) -> None:
|
||||
selected_objs = [
|
||||
@@ -86,7 +90,7 @@ def join_walls_LV(
|
||||
joiner.connect(another_selected_object, active_obj)
|
||||
|
||||
|
||||
def offset_walls(ifc: tool.Ifc, blender: tool.Blender, model: tool.Model, offset_type: OffsetType):
|
||||
def offset_walls(ifc: type[tool.Ifc], blender: type[tool.Blender], model: type[tool.Model], offset_type: OffsetType):
|
||||
objs = [
|
||||
obj
|
||||
for obj in blender.get_selected_objects()
|
||||
@@ -98,7 +102,11 @@ def offset_walls(ifc: tool.Ifc, blender: tool.Blender, model: tool.Model, offset
|
||||
|
||||
|
||||
def align_walls(
|
||||
ifc: tool.Ifc, blender: tool.Blender, model: tool.Model, aligner: DumbWallAligner, align_type: AlignType
|
||||
ifc: type[tool.Ifc],
|
||||
blender: type[tool.Blender],
|
||||
model: type[tool.Model],
|
||||
aligner: DumbWallAligner,
|
||||
align_type: AlignType,
|
||||
):
|
||||
reference_obj = blender.get_active_object(is_selected=True)
|
||||
if not (e := ifc.get_entity(reference_obj) or not model.get_usage_type(e) == "LAYER2"):
|
||||
@@ -122,7 +130,9 @@ def align_walls(
|
||||
aligner.align_last_layer(obj)
|
||||
|
||||
|
||||
def align_objects(blender: tool.Blender, model: tool.Model, align_type: Literal["CENTER", "POSITIVE", "NEGATIVE"]):
|
||||
def align_objects(
|
||||
blender: type[tool.Blender], model: type[tool.Model], align_type: Literal["CENTER", "POSITIVE", "NEGATIVE"]
|
||||
):
|
||||
reference_obj = blender.get_active_object(is_selected=True)
|
||||
objs = [o for o in blender.get_selected_objects() if o != reference_obj]
|
||||
if not reference_obj or not objs:
|
||||
@@ -131,9 +141,9 @@ def align_objects(blender: tool.Blender, model: tool.Model, align_type: Literal[
|
||||
|
||||
|
||||
def extend_wall_to_slab(
|
||||
ifc: tool.Ifc,
|
||||
geometry: tool.Geometry,
|
||||
model: tool.Model,
|
||||
ifc: type[tool.Ifc],
|
||||
geometry: type[tool.Geometry],
|
||||
model: type[tool.Model],
|
||||
slab_obj: bpy.types.Object,
|
||||
wall_objs: list[bpy.types.Object],
|
||||
) -> None:
|
||||
@@ -150,7 +160,11 @@ def extend_wall_to_slab(
|
||||
|
||||
|
||||
def join_walls_TZ(
|
||||
ifc: tool.Ifc, blender: tool.Blender, geometry: tool.Geometry, joiner: DumbWallJoiner, model: tool.Model
|
||||
ifc: type[tool.Ifc],
|
||||
blender: type[tool.Blender],
|
||||
geometry: type[tool.Geometry],
|
||||
joiner: DumbWallJoiner,
|
||||
model: type[tool.Model],
|
||||
) -> None:
|
||||
selected_objs = [
|
||||
o
|
||||
|
||||
@@ -1,3 +1,22 @@
|
||||
# Bonsai - OpenBIM Blender Add-on
|
||||
# Copyright (C) 2021 Dion Moult <dion@thinkmoult.com>
|
||||
#
|
||||
# This file is part of Bonsai.
|
||||
#
|
||||
# Bonsai is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Bonsai is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from __future__ import annotations
|
||||
import bonsai.core.tool
|
||||
import bonsai.tool as tool
|
||||
import bpy
|
||||
@@ -8,6 +27,9 @@ import ifcopenshell.util.element
|
||||
import ifcopenshell.util.classification
|
||||
from typing import Any, Union, Optional, TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from bonsai.bim.module.bsdd.prop import BIMBSDDProperties
|
||||
|
||||
|
||||
class Bsdd(bonsai.core.tool.Bsdd):
|
||||
identifier_url = "https://identifier.buildingsmart.org"
|
||||
@@ -16,28 +38,29 @@ class Bsdd(bonsai.core.tool.Bsdd):
|
||||
bsdd_properties: dict[str, dict] = {}
|
||||
|
||||
@classmethod
|
||||
def get_bsdd_props(cls):
|
||||
return bpy.context.scene.BIMBSDDProperties
|
||||
def get_bsdd_props(cls) -> BIMBSDDProperties:
|
||||
assert (scene := bpy.context.scene)
|
||||
return scene.BIMBSDDProperties # pyright: ignore[reportAttributeAccessIssue]
|
||||
|
||||
@classmethod
|
||||
def clear_class_psets(cls) -> None:
|
||||
bpy.context.scene.BIMBSDDProperties.classification_psets.clear()
|
||||
cls.get_bsdd_props().classification_psets.clear()
|
||||
|
||||
@classmethod
|
||||
def clear_classes(cls) -> None:
|
||||
bpy.context.scene.BIMBSDDProperties.classifications.clear()
|
||||
cls.get_bsdd_props().classifications.clear()
|
||||
|
||||
@classmethod
|
||||
def clear_properties(cls) -> None:
|
||||
bpy.context.scene.BIMBSDDProperties.properties.clear()
|
||||
cls.get_bsdd_props().properties.clear()
|
||||
|
||||
@classmethod
|
||||
def clear_dictionaries(cls) -> None:
|
||||
bpy.context.scene.BIMBSDDProperties.dictionaries.clear()
|
||||
cls.get_bsdd_props().dictionaries.clear()
|
||||
|
||||
@classmethod
|
||||
def create_class_psets(cls, pset_dict: dict[str, dict[str, Any]]) -> None:
|
||||
props = bpy.context.scene.BIMBSDDProperties
|
||||
props = cls.get_bsdd_props()
|
||||
data_type_map = {
|
||||
"String": "string",
|
||||
"Real": "float",
|
||||
@@ -60,7 +83,7 @@ class Bsdd(bonsai.core.tool.Bsdd):
|
||||
|
||||
@classmethod
|
||||
def create_dictionaries(cls, dictionaries: list[bsdd.DictionaryContractV1]) -> None:
|
||||
props = bpy.context.scene.BIMBSDDProperties
|
||||
props = cls.get_bsdd_props()
|
||||
for dictionary in sorted(dictionaries, key=lambda d: d["name"]):
|
||||
new = props.dictionaries.add()
|
||||
new.name = dictionary["name"]
|
||||
@@ -72,7 +95,7 @@ class Bsdd(bonsai.core.tool.Bsdd):
|
||||
|
||||
@classmethod
|
||||
def get_active_class_data(cls) -> Union[bsdd.ClassContractV1, dict]:
|
||||
prop = bpy.context.scene.BIMBSDDProperties
|
||||
prop = cls.get_bsdd_props()
|
||||
bsdd_classification = prop.classifications[prop.active_classification_index]
|
||||
if not bsdd_classification:
|
||||
return {}
|
||||
@@ -80,18 +103,18 @@ class Bsdd(bonsai.core.tool.Bsdd):
|
||||
|
||||
@classmethod
|
||||
def get_active_dictionary_uri(cls) -> str:
|
||||
return bpy.context.scene.BIMBSDDProperties.active_uri
|
||||
return cls.get_bsdd_props().active_uri
|
||||
|
||||
@classmethod
|
||||
def get_dictionary(cls, uri: str) -> bsdd.DictionaryContractV1:
|
||||
props = bpy.context.scene.BIMBSDDProperties
|
||||
props = cls.get_bsdd_props()
|
||||
response = cls.client.get_dictionary(dictionary_uri=uri, include_test_dictionaries=props.load_test_dictionaries)
|
||||
if dicts := response.get("dictionaries"):
|
||||
return dicts[0]
|
||||
|
||||
@classmethod
|
||||
def get_dictionaries(cls) -> list[bsdd.DictionaryContractV1]:
|
||||
props = bpy.context.scene.BIMBSDDProperties
|
||||
props = cls.get_bsdd_props()
|
||||
response = cls.client.get_dictionary(include_test_dictionaries=props.load_test_dictionaries)
|
||||
dicts = response.get("dictionaries") or []
|
||||
statuses = ["Active"]
|
||||
@@ -165,7 +188,7 @@ class Bsdd(bonsai.core.tool.Bsdd):
|
||||
limit: int = 100,
|
||||
should_paginate: bool = True,
|
||||
):
|
||||
cprops = bpy.context.scene.BIMClassificationProperties
|
||||
cprops = tool.Classification.get_classification_props()
|
||||
bprops = cls.get_bsdd_props()
|
||||
dictionary_uris = (
|
||||
[d.uri for d in bprops.dictionaries if d.is_active]
|
||||
@@ -202,13 +225,13 @@ class Bsdd(bonsai.core.tool.Bsdd):
|
||||
|
||||
@classmethod
|
||||
def set_active_bsdd(cls, name: str, uri: str) -> None:
|
||||
props = bpy.context.scene.BIMBSDDProperties
|
||||
props = cls.get_bsdd_props()
|
||||
props.active_dictionary = name
|
||||
props.active_uri = uri
|
||||
|
||||
@classmethod
|
||||
def should_filter_ifc_class(cls) -> bool:
|
||||
return bpy.context.scene.BIMBSDDProperties.should_filter_ifc_class
|
||||
return cls.get_bsdd_props().should_filter_ifc_class
|
||||
|
||||
@classmethod
|
||||
def get_bsdd_class(cls, uri: str) -> dict:
|
||||
|
||||
@@ -22,10 +22,23 @@ import ifcopenshell.api
|
||||
import ifcopenshell.util.classification
|
||||
import bonsai.core.tool
|
||||
import bonsai.tool as tool
|
||||
from typing import Union, assert_never
|
||||
from typing import Union, assert_never, TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from bonsai.bim.module.classification.prop import BIMClassificationReferenceProperties, BIMClassificationProperties
|
||||
|
||||
|
||||
class Classification(bonsai.core.tool.Classification):
|
||||
@classmethod
|
||||
def get_classification_props(cls) -> BIMClassificationProperties:
|
||||
assert (scene := bpy.context.scene)
|
||||
return scene.BIMClassificationProperties # pyright: ignore[reportAttributeAccessIssue]
|
||||
|
||||
@classmethod
|
||||
def get_classification_reference_props(cls) -> BIMClassificationReferenceProperties:
|
||||
assert (scene := bpy.context.scene)
|
||||
return scene.BIMClassificationReferenceProperties # pyright: ignore[reportAttributeAccessIssue]
|
||||
|
||||
@classmethod
|
||||
def get_location(cls, classification: ifcopenshell.entity_instance) -> Union[str, None]:
|
||||
schema = classification.file.schema
|
||||
|
||||
@@ -46,8 +46,8 @@ class TestAddClassificationReferenceFromBSDD(NewFile):
|
||||
bpy.ops.bim.load_bsdd_domains()
|
||||
uri = "https://identifier.buildingsmart.org/uri/molio/cciconstruction/1.0"
|
||||
bpy.ops.bim.set_active_bsdd_domain(name="CCI Construction", uri=uri)
|
||||
props = context.scene.BIMBSDDProperties
|
||||
bpy.context.scene.BIMClassificationProperties.classification_source = "BSDD"
|
||||
props = tool.Bsdd.get_bsdd_props()
|
||||
tool.Classification.get_classification_props().classification_source = "BSDD"
|
||||
props.should_filter_ifc_class = True
|
||||
props.keyword = "Room"
|
||||
bpy.ops.bim.search_bsdd_classifications()
|
||||
@@ -70,8 +70,8 @@ class TestAddClassificationReferenceFromBSDD(NewFile):
|
||||
bpy.ops.bim.load_bsdd_domains()
|
||||
uri = "https://identifier.buildingsmart.org/uri/molio/cciconstruction/1.0"
|
||||
bpy.ops.bim.set_active_bsdd_domain(name="CCI Construction", uri=uri)
|
||||
props = context.scene.BIMBSDDProperties
|
||||
bpy.context.scene.BIMClassificationProperties.classification_source = "BSDD"
|
||||
props = tool.Bsdd.get_bsdd_props()
|
||||
tool.Classification.get_classification_props().classification_source = "BSDD"
|
||||
props.should_filter_ifc_class = True
|
||||
props.keyword = "Room"
|
||||
bpy.ops.bim.search_bsdd_classifications()
|
||||
@@ -103,12 +103,12 @@ class TestAddClassificationReferenceFromBSDD(NewFile):
|
||||
element = tool.Ifc.get_entity(obj)
|
||||
assert element
|
||||
|
||||
props = context.scene.BIMBSDDProperties
|
||||
props = tool.Bsdd.get_bsdd_props()
|
||||
props.load_preview_domains = True
|
||||
bpy.ops.bim.load_bsdd_domains()
|
||||
uri = "https://identifier.buildingsmart.org/uri/ifcairport/ifcairport/0.9"
|
||||
bpy.ops.bim.set_active_bsdd_domain(name="IFC Airport", uri=uri)
|
||||
bpy.context.scene.BIMClassificationProperties.classification_source = "BSDD"
|
||||
tool.Classification.get_classification_props().classification_source = "BSDD"
|
||||
props.should_filter_ifc_class = False # Important due to class mismatch.
|
||||
props.keyword = "check-in conveyor"
|
||||
bpy.ops.bim.search_bsdd_classifications()
|
||||
|
||||
@@ -540,7 +540,7 @@ class TestSetupActiveBsddClassification(NewFile):
|
||||
filepath = "test/files/temp/test.ifc"
|
||||
ifc_file.write(filepath)
|
||||
bpy.ops.bim.load_project(filepath=filepath)
|
||||
props = bpy.context.scene.BIMBSDDProperties
|
||||
props = tool.Bsdd.get_bsdd_props()
|
||||
assert props.active_domain == name
|
||||
assert props.active_uri == base_uri
|
||||
|
||||
|
||||
@@ -351,19 +351,18 @@ def log_internal_cpp_errors(f: ifcopenshell.file, filename: str, logger: Logger)
|
||||
logger.error(m)
|
||||
|
||||
|
||||
entity_attribute_map: dict[tuple[str, str], tuple[entity_type, tuple[attribute]]] = {}
|
||||
entity_attribute_map: dict[tuple[str, str], tuple[entity_type, tuple[attribute, ...]]] = {}
|
||||
|
||||
|
||||
def get_entity_attributes(schema: schema_definition, entity: str) -> tuple[entity_type, tuple[attribute]]:
|
||||
def get_entity_attributes(schema: schema_definition, entity: str) -> tuple[entity_type, tuple[attribute, ...]]:
|
||||
cache_key = schema.name(), entity
|
||||
from_cache = entity_attribute_map.get(cache_key)
|
||||
if from_cache:
|
||||
return from_cache
|
||||
|
||||
entity_attrs = (
|
||||
ent := schema.declaration_by_name(entity),
|
||||
ent.all_attributes(),
|
||||
)
|
||||
ent = schema.declaration_by_name(entity).as_entity()
|
||||
assert ent
|
||||
entity_attrs = (ent, ent.all_attributes())
|
||||
|
||||
entity_attribute_map[cache_key] = entity_attrs
|
||||
return entity_attrs
|
||||
|
||||
@@ -17,12 +17,14 @@
|
||||
# along with IfcPatch. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import ifcopenshell
|
||||
import ifcopenshell.guid
|
||||
import ifcopenshell.util.element
|
||||
import ifcpatch
|
||||
import logging
|
||||
from typing import Union
|
||||
|
||||
|
||||
class Patcher:
|
||||
def __init__(self, file, logger):
|
||||
class Patcher(ifcpatch.BasePatcher):
|
||||
def __init__(self, file: ifcopenshell.file, logger: Union[logging.Logger, None] = None):
|
||||
"""Merge identical styles together
|
||||
|
||||
Some software may create an obscene number of styles instead of reusing
|
||||
@@ -35,8 +37,7 @@ class Patcher:
|
||||
|
||||
ifcpatch.execute({"file": model, "recipe": "MergeStyles", "arguments": []})
|
||||
"""
|
||||
self.file = file
|
||||
self.logger = logger
|
||||
super().__init__(file, logger)
|
||||
|
||||
def patch(self):
|
||||
for ifc_class in ("IfcColourRgb", "IfcSurfaceStyleShading", "IfcPresentationStyle"):
|
||||
|
||||
Reference in New Issue
Block a user