mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-11 18:16:40 +00:00
WIP port classification module with new features. See #1222.
* Adaptive UI based on IFC version * You can now load new classification libraries on the fly * You can mix classification libraries with project references
This commit is contained in:
@@ -13,6 +13,7 @@ if bpy is not None:
|
||||
"aggregate": None,
|
||||
"attribute": None,
|
||||
"bcf": None,
|
||||
"classification": None,
|
||||
"cobie": None,
|
||||
"context": None,
|
||||
"covetool": None,
|
||||
@@ -87,12 +88,6 @@ if bpy is not None:
|
||||
operator.SelectGlobalId,
|
||||
operator.SelectAttribute,
|
||||
operator.SelectPset,
|
||||
operator.LoadClassification,
|
||||
operator.AddClassification,
|
||||
operator.RemoveClassification,
|
||||
operator.AssignClassification,
|
||||
operator.UnassignClassification,
|
||||
operator.RemoveClassificationReference,
|
||||
operator.FetchLibraryInformation,
|
||||
operator.FetchExternalMaterial,
|
||||
operator.FetchObjectPassport,
|
||||
@@ -119,7 +114,6 @@ if bpy is not None:
|
||||
operator.SelectSmartGroup,
|
||||
operator.LoadSmartGroupsForActiveClashSet,
|
||||
operator.OpenUpstream,
|
||||
operator.BIM_OT_ChangeClassificationLevel,
|
||||
operator.AddPropertySetTemplate,
|
||||
operator.RemovePropertySetTemplate,
|
||||
operator.EditPropertySetTemplate,
|
||||
@@ -181,9 +175,6 @@ if bpy is not None:
|
||||
prop.StrProperty,
|
||||
prop.Attribute,
|
||||
prop.Variable,
|
||||
prop.Classification,
|
||||
prop.ClassificationReference,
|
||||
prop.ClassificationView,
|
||||
prop.PropertySetTemplate,
|
||||
prop.PropertyTemplate,
|
||||
prop.DocumentInformation,
|
||||
@@ -217,7 +208,6 @@ if bpy is not None:
|
||||
ui.BIM_PT_schedules,
|
||||
ui.BIM_PT_sheets,
|
||||
ui.BIM_PT_psets,
|
||||
ui.BIM_PT_classifications,
|
||||
ui.BIM_PT_document_information,
|
||||
ui.BIM_PT_constraints,
|
||||
ui.BIM_PT_search,
|
||||
@@ -227,7 +217,6 @@ if bpy is not None:
|
||||
ui.BIM_PT_patch,
|
||||
ui.BIM_PT_mvd,
|
||||
ui.BIM_PT_presentation_layer_data,
|
||||
ui.BIM_PT_classification_references,
|
||||
ui.BIM_PT_documents,
|
||||
ui.BIM_PT_constraint_relations,
|
||||
ui.BIM_PT_object_structural,
|
||||
@@ -246,7 +235,6 @@ if bpy is not None:
|
||||
ui.BIM_UL_document_information,
|
||||
ui.BIM_UL_document_references,
|
||||
ui.BIM_UL_topics,
|
||||
ui.BIM_UL_classifications,
|
||||
ui.BIM_ADDON_preferences,
|
||||
]
|
||||
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
import bpy
|
||||
from . import ui, prop, operator
|
||||
|
||||
classes = (
|
||||
operator.LoadClassificationLibrary,
|
||||
operator.AddClassification,
|
||||
operator.RemoveClassification,
|
||||
operator.EnableEditingClassification,
|
||||
operator.DisableEditingClassification,
|
||||
operator.EditClassification,
|
||||
operator.RemoveClassificationReference,
|
||||
operator.EnableEditingClassificationReference,
|
||||
operator.DisableEditingClassificationReference,
|
||||
operator.EditClassificationReference,
|
||||
operator.AddClassificationReference,
|
||||
operator.ChangeClassificationLevel,
|
||||
prop.ClassificationReference,
|
||||
prop.BIMClassificationProperties,
|
||||
prop.BIMClassificationReferenceProperties,
|
||||
ui.BIM_PT_classifications,
|
||||
ui.BIM_PT_classification_references,
|
||||
ui.BIM_UL_classifications,
|
||||
)
|
||||
|
||||
|
||||
def register():
|
||||
bpy.types.Scene.BIMClassificationProperties = bpy.props.PointerProperty(type=prop.BIMClassificationProperties)
|
||||
bpy.types.Object.BIMClassificationReferenceProperties = bpy.props.PointerProperty(
|
||||
type=prop.BIMClassificationReferenceProperties
|
||||
)
|
||||
|
||||
|
||||
def unregister():
|
||||
del bpy.types.Scene.BIMClassificationProperties
|
||||
del bpy.types.Object.BIMClassificationReferenceProperties
|
||||
@@ -0,0 +1,26 @@
|
||||
import ifcopenshell
|
||||
import ifcopenshell.util.schema
|
||||
|
||||
class Usecase:
|
||||
def __init__(self, file, settings=None):
|
||||
self.file = file
|
||||
self.settings = {
|
||||
"classification": None,
|
||||
}
|
||||
for key, value in settings.items():
|
||||
self.settings[key] = value
|
||||
|
||||
def execute(self):
|
||||
migrator = ifcopenshell.util.schema.Migrator()
|
||||
result = migrator.migrate(self.settings["classification"], self.file)
|
||||
self.file.create_entity("IfcRelAssociatesClassification", **{
|
||||
"GlobalId": ifcopenshell.guid.new(),
|
||||
"RelatedObjects": [self.file.by_type("IfcProject")[0]],
|
||||
"RelatingClassification": result
|
||||
})
|
||||
return # See bug #1272
|
||||
try:
|
||||
result = self.file.add(self.settings["classification"])
|
||||
except:
|
||||
migrator = ifcopenshell.util.schema.Migrator()
|
||||
result = migrator.migrate(self.settings["classification"], self.file)
|
||||
@@ -0,0 +1,53 @@
|
||||
import ifcopenshell
|
||||
import ifcopenshell.util.schema
|
||||
|
||||
class Usecase:
|
||||
def __init__(self, file, settings=None):
|
||||
self.file = file
|
||||
self.settings = {
|
||||
"product": None,
|
||||
"reference": None,
|
||||
"classification": None,
|
||||
}
|
||||
for key, value in settings.items():
|
||||
self.settings[key] = value
|
||||
|
||||
def execute(self):
|
||||
relating_classification = None
|
||||
for reference in self.file.by_type("IfcClassificationReference"):
|
||||
if self.file.schema == "IFC2X3":
|
||||
if reference.ItemReference == self.settings["reference"].ItemReference:
|
||||
relating_classification = reference
|
||||
break
|
||||
else:
|
||||
if reference.Identification == self.settings["reference"].Identification:
|
||||
relating_classification = reference
|
||||
break
|
||||
|
||||
if relating_classification:
|
||||
association = self.get_association(relating_classification)
|
||||
related_objects = set(association.RelatedObjects)
|
||||
related_objects.add(self.settings["product"])
|
||||
association.RelatedObjects = list(related_objects)
|
||||
return
|
||||
|
||||
migrator = ifcopenshell.util.schema.Migrator()
|
||||
# This removal patch is to support a lightweight classification
|
||||
old_referenced_source = self.settings["reference"].ReferencedSource
|
||||
self.settings["reference"].ReferencedSource = None
|
||||
relating_classification = migrator.migrate(self.settings["reference"], self.file)
|
||||
relating_classification.ReferencedSource = self.settings["classification"]
|
||||
self.settings["reference"].ReferencedSource = old_referenced_source
|
||||
self.file.create_entity("IfcRelAssociatesClassification", **{
|
||||
"GlobalId": ifcopenshell.guid.new(),
|
||||
"RelatedObjects": [self.settings["product"]],
|
||||
"RelatingClassification": relating_classification
|
||||
})
|
||||
|
||||
def get_association(self, reference):
|
||||
if self.file.schema == "IFC2X3":
|
||||
for association in self.file.by_type("IfcRelAssociatesClassification"):
|
||||
if relating_classification == reference:
|
||||
return association
|
||||
elif reference.ClassificationRefForObjects:
|
||||
return reference.ClassificationRefForObjects[0]
|
||||
@@ -0,0 +1,71 @@
|
||||
import ifcopenshell
|
||||
from blenderbim.bim.ifc import IfcStore
|
||||
from datetime import datetime
|
||||
|
||||
|
||||
class Data:
|
||||
is_loaded = False
|
||||
products = {}
|
||||
classifications = {}
|
||||
references = {}
|
||||
library_file = None
|
||||
library_classifications = {}
|
||||
library_references = {}
|
||||
|
||||
@classmethod
|
||||
def load(cls, product_id=None):
|
||||
cls._file = IfcStore.get_file()
|
||||
if not cls._file:
|
||||
return
|
||||
if product_id:
|
||||
return cls.load_product_classifications(product_id)
|
||||
cls.load_classifications()
|
||||
cls.load_references()
|
||||
cls.is_loaded = True
|
||||
|
||||
@classmethod
|
||||
def load_product_classifications(cls, product_id):
|
||||
product = cls._file.by_id(product_id)
|
||||
cls.products[product_id] = []
|
||||
if not product.HasAssociations:
|
||||
return
|
||||
for association in product.HasAssociations:
|
||||
if association.is_a("IfcRelAssociatesClassification"):
|
||||
cls.products[product_id].append(association.RelatingClassification.id())
|
||||
|
||||
@classmethod
|
||||
def load_classifications(cls):
|
||||
cls.classifications = {}
|
||||
for classification in cls._file.by_type("IfcClassification"):
|
||||
data = classification.get_info()
|
||||
if cls._file.schema == "IFC2X3" and data["EditionDate"]:
|
||||
data["EditionDate"] = datetime(
|
||||
classification.EditionDate.YearComponent,
|
||||
classification.EditionDate.MonthComponent,
|
||||
classification.EditionDate.DayComponent,
|
||||
).isoformat()
|
||||
cls.classifications[classification.id()] = data
|
||||
|
||||
@classmethod
|
||||
def load_references(cls):
|
||||
cls.references = {}
|
||||
for reference in cls._file.by_type("IfcClassificationReference"):
|
||||
data = reference.get_info()
|
||||
if reference.ReferencedSource:
|
||||
#data["ReferencedSource"] = cls.get_referenced_source(reference.ReferencedSource)
|
||||
data["ReferencedSource"] = reference.ReferencedSource.id()
|
||||
cls.references[reference.id()] = data
|
||||
|
||||
@classmethod
|
||||
def get_referenced_source(cls, reference):
|
||||
if reference.is_a("IfcClassification"):
|
||||
return reference
|
||||
elif reference.is_a("IfcClassificationReference") and reference.ReferencedSource:
|
||||
return cls.get_referenced_source(reference.ReferencedSource)
|
||||
|
||||
@classmethod
|
||||
def load_library(cls, filepath):
|
||||
cls.library_file = ifcopenshell.open(filepath)
|
||||
cls.library_classifications = {}
|
||||
for classification in cls.library_file.by_type("IfcClassification"):
|
||||
cls.library_classifications[classification.id()] = classification.Name
|
||||
@@ -0,0 +1,13 @@
|
||||
class Usecase:
|
||||
def __init__(self, file, settings=None):
|
||||
self.file = file
|
||||
self.settings = {
|
||||
"classification": None,
|
||||
"attributes": {}
|
||||
}
|
||||
for key, value in settings.items():
|
||||
self.settings[key] = value
|
||||
|
||||
def execute(self):
|
||||
for name, value in self.settings["attributes"].items():
|
||||
setattr(self.settings["classification"], name, value)
|
||||
@@ -0,0 +1,13 @@
|
||||
class Usecase:
|
||||
def __init__(self, file, settings=None):
|
||||
self.file = file
|
||||
self.settings = {
|
||||
"reference": None,
|
||||
"attributes": {}
|
||||
}
|
||||
for key, value in settings.items():
|
||||
self.settings[key] = value
|
||||
|
||||
def execute(self):
|
||||
for name, value in self.settings["attributes"].items():
|
||||
setattr(self.settings["reference"], name, value)
|
||||
@@ -0,0 +1,229 @@
|
||||
import bpy
|
||||
import json
|
||||
import blenderbim.bim.module.classification.add_classification as add_classification
|
||||
import blenderbim.bim.module.classification.remove_classification as remove_classification
|
||||
import blenderbim.bim.module.classification.edit_classification as edit_classification
|
||||
import blenderbim.bim.module.classification.add_reference as add_reference
|
||||
import blenderbim.bim.module.classification.remove_reference as remove_reference
|
||||
import blenderbim.bim.module.classification.edit_reference as edit_reference
|
||||
from blenderbim.bim.ifc import IfcStore
|
||||
from blenderbim.bim.module.classification.data import Data
|
||||
from blenderbim.bim.module.classification.prop import getClassifications, getReferences
|
||||
|
||||
|
||||
class LoadClassificationLibrary(bpy.types.Operator):
|
||||
bl_idname = "bim.load_classification_library"
|
||||
bl_label = "Load Classification Library"
|
||||
filename_ext = ".ifc"
|
||||
filter_glob: bpy.props.StringProperty(default="*.ifc;*.ifczip;*.ifcxml", options={"HIDDEN"})
|
||||
filepath: bpy.props.StringProperty(subtype="FILE_PATH")
|
||||
|
||||
def execute(self, context):
|
||||
Data.load_library(self.filepath)
|
||||
getClassifications(self, context)
|
||||
return {"FINISHED"}
|
||||
|
||||
def invoke(self, context, event):
|
||||
context.window_manager.fileselect_add(self)
|
||||
return {"RUNNING_MODAL"}
|
||||
|
||||
|
||||
class AddClassification(bpy.types.Operator):
|
||||
bl_idname = "bim.add_classification"
|
||||
bl_label = "Add Classification"
|
||||
|
||||
def execute(self, context):
|
||||
props = context.scene.BIMClassificationProperties
|
||||
add_classification.Usecase(
|
||||
IfcStore.get_file(), {"classification": Data.library_file.by_id(int(props.available_classifications))}
|
||||
).execute()
|
||||
Data.load()
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class EnableEditingClassification(bpy.types.Operator):
|
||||
bl_idname = "bim.enable_editing_classification"
|
||||
bl_label = "Enable Editing Classification"
|
||||
classification: bpy.props.IntProperty()
|
||||
|
||||
def execute(self, context):
|
||||
props = context.scene.BIMClassificationProperties
|
||||
while len(props.classification_attributes) > 0:
|
||||
props.classification_attributes.remove(0)
|
||||
classification_data = Data.classifications[self.classification]
|
||||
for attribute in IfcStore.get_schema().declaration_by_name("IfcClassification").all_attributes():
|
||||
new = props.classification_attributes.add()
|
||||
new.name = attribute.name()
|
||||
new.is_null = classification_data[attribute.name()] is None
|
||||
new.is_optional = attribute.optional()
|
||||
if attribute.name() == "ReferenceTokens":
|
||||
new.string_value = "" if new.is_null else json.dumps(classification_data[attribute.name()])
|
||||
else:
|
||||
new.string_value = "" if new.is_null else classification_data[attribute.name()]
|
||||
props.active_classification_id = self.classification
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class DisableEditingClassification(bpy.types.Operator):
|
||||
bl_idname = "bim.disable_editing_classification"
|
||||
bl_label = "Disable Editing Classification"
|
||||
|
||||
def execute(self, context):
|
||||
context.scene.BIMClassificationProperties.active_classification_id = 0
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class RemoveClassification(bpy.types.Operator):
|
||||
bl_idname = "bim.remove_classification"
|
||||
bl_label = "Remove Classification"
|
||||
classification: bpy.props.IntProperty()
|
||||
|
||||
def execute(self, context):
|
||||
self.file = IfcStore.get_file()
|
||||
remove_classification.Usecase(self.file, {"classification": self.file.by_id(self.classification)}).execute()
|
||||
Data.load()
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class EditClassification(bpy.types.Operator):
|
||||
bl_idname = "bim.edit_classification"
|
||||
bl_label = "Edit Classification"
|
||||
|
||||
def execute(self, context):
|
||||
props = context.scene.BIMClassificationProperties
|
||||
attributes = {}
|
||||
for attribute in props.classification_attributes:
|
||||
if attribute.is_null:
|
||||
attributes[attribute.name] = None
|
||||
elif attribute.name == "ReferenceTokens":
|
||||
attributes[attribute.name] = json.loads(attribute.string_value)
|
||||
else:
|
||||
attributes[attribute.name] = attribute.string_value
|
||||
self.file = IfcStore.get_file()
|
||||
edit_classification.Usecase(
|
||||
self.file, {"classification": self.file.by_id(props.active_classification_id), "attributes": attributes}
|
||||
).execute()
|
||||
Data.load()
|
||||
bpy.ops.bim.disable_editing_classification()
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class EnableEditingClassificationReference(bpy.types.Operator):
|
||||
bl_idname = "bim.enable_editing_classification_reference"
|
||||
bl_label = "Enable Editing Classification Reference"
|
||||
reference: bpy.props.IntProperty()
|
||||
obj: bpy.props.StringProperty()
|
||||
|
||||
def execute(self, context):
|
||||
obj = bpy.data.objects.get(self.obj) if self.obj else bpy.context.active_object
|
||||
props = obj.BIMClassificationReferenceProperties
|
||||
while len(props.reference_attributes) > 0:
|
||||
props.reference_attributes.remove(0)
|
||||
reference_data = Data.references[self.reference]
|
||||
for attribute in IfcStore.get_schema().declaration_by_name("IfcClassificationReference").all_attributes():
|
||||
if attribute.name() == "ReferencedSource":
|
||||
continue
|
||||
new = props.reference_attributes.add()
|
||||
new.name = attribute.name()
|
||||
new.is_null = reference_data[attribute.name()] is None
|
||||
new.is_optional = attribute.optional()
|
||||
new.string_value = "" if new.is_null else reference_data[attribute.name()]
|
||||
props.active_reference_id = self.reference
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class DisableEditingClassificationReference(bpy.types.Operator):
|
||||
bl_idname = "bim.disable_editing_classification_reference"
|
||||
bl_label = "Disable Editing Classification Reference"
|
||||
obj: bpy.props.StringProperty()
|
||||
|
||||
def execute(self, context):
|
||||
obj = bpy.data.objects.get(self.obj) if self.obj else bpy.context.active_object
|
||||
obj.BIMClassificationReferenceProperties.active_reference_id = 0
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class RemoveClassificationReference(bpy.types.Operator):
|
||||
bl_idname = "bim.remove_classification_reference"
|
||||
bl_label = "Remove Classification Reference"
|
||||
reference: bpy.props.IntProperty()
|
||||
obj: bpy.props.StringProperty()
|
||||
|
||||
def execute(self, context):
|
||||
obj = bpy.data.objects.get(self.obj) if self.obj else bpy.context.active_object
|
||||
self.file = IfcStore.get_file()
|
||||
remove_reference.Usecase(
|
||||
self.file,
|
||||
{
|
||||
"reference": self.file.by_id(self.reference),
|
||||
"product": self.file.by_id(obj.BIMObjectProperties.ifc_definition_id),
|
||||
},
|
||||
).execute()
|
||||
Data.load(obj.BIMObjectProperties.ifc_definition_id)
|
||||
Data.load()
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class EditClassificationReference(bpy.types.Operator):
|
||||
bl_idname = "bim.edit_classification_reference"
|
||||
bl_label = "Edit Classification Reference"
|
||||
obj: bpy.props.StringProperty()
|
||||
|
||||
def execute(self, context):
|
||||
obj = bpy.data.objects.get(self.obj) if self.obj else bpy.context.active_object
|
||||
props = obj.BIMClassificationReferenceProperties
|
||||
attributes = {}
|
||||
for attribute in props.reference_attributes:
|
||||
if attribute.is_null:
|
||||
attributes[attribute.name] = None
|
||||
else:
|
||||
attributes[attribute.name] = attribute.string_value
|
||||
self.file = IfcStore.get_file()
|
||||
edit_reference.Usecase(
|
||||
self.file, {"reference": self.file.by_id(props.active_reference_id), "attributes": attributes}
|
||||
).execute()
|
||||
Data.load()
|
||||
bpy.ops.bim.disable_editing_classification_reference()
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class AddClassificationReference(bpy.types.Operator):
|
||||
bl_idname = "bim.add_classification_reference"
|
||||
bl_label = "Add Classification Reference"
|
||||
reference: bpy.props.IntProperty()
|
||||
obj: bpy.props.StringProperty()
|
||||
|
||||
def execute(self, context):
|
||||
obj = bpy.data.objects.get(self.obj) if self.obj else bpy.context.active_object
|
||||
self.file = IfcStore.get_file()
|
||||
|
||||
classification = None
|
||||
|
||||
props = context.scene.BIMClassificationProperties
|
||||
classification_name = Data.library_classifications[int(props.available_classifications)]
|
||||
for classification_id, classification in Data.classifications.items():
|
||||
if classification["Name"] == classification_name:
|
||||
classification = self.file.by_id(classification_id)
|
||||
break
|
||||
|
||||
add_reference.Usecase(
|
||||
self.file,
|
||||
{
|
||||
"reference": Data.library_file.by_id(self.reference),
|
||||
"product": self.file.by_id(obj.BIMObjectProperties.ifc_definition_id),
|
||||
"classification": classification
|
||||
},
|
||||
).execute()
|
||||
Data.load(obj.BIMObjectProperties.ifc_definition_id)
|
||||
Data.load()
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class ChangeClassificationLevel(bpy.types.Operator):
|
||||
bl_idname = "bim.change_classification_level"
|
||||
bl_label = "Change Classification Level"
|
||||
parent_id: bpy.props.IntProperty()
|
||||
|
||||
def execute(self, context):
|
||||
getReferences(self, context, parent_id=self.parent_id)
|
||||
return {"FINISHED"}
|
||||
@@ -0,0 +1,71 @@
|
||||
import bpy
|
||||
from blenderbim.bim.prop import StrProperty, Attribute
|
||||
from blenderbim.bim.module.classification.data import Data
|
||||
from bpy.types import PropertyGroup
|
||||
from bpy.props import (
|
||||
PointerProperty,
|
||||
StringProperty,
|
||||
EnumProperty,
|
||||
BoolProperty,
|
||||
IntProperty,
|
||||
FloatProperty,
|
||||
FloatVectorProperty,
|
||||
CollectionProperty,
|
||||
)
|
||||
|
||||
classification_enum = []
|
||||
|
||||
|
||||
def getClassifications(self, context):
|
||||
global classification_enum
|
||||
if len(classification_enum) < 1:
|
||||
classification_enum.clear()
|
||||
classification_enum.extend([(str(i), n, "") for i, n in Data.library_classifications.items()])
|
||||
if classification_enum:
|
||||
getReferences(self, context, parent_id=int(classification_enum[0][0]))
|
||||
return classification_enum
|
||||
|
||||
|
||||
def updateClassification(self, context):
|
||||
getReferences(self, context, parent_id=int(self.available_classifications))
|
||||
|
||||
|
||||
def getReferences(self, context, parent_id=None):
|
||||
props = context.scene.BIMClassificationProperties
|
||||
while len(props.available_library_references) > 0:
|
||||
props.available_library_references.remove(0)
|
||||
for reference in Data.library_file.by_id(parent_id).HasReferences:
|
||||
new = props.available_library_references.add()
|
||||
new.identification = reference.Identification or ""
|
||||
new.name = reference.Name or ""
|
||||
new.ifc_definition_id = reference.id()
|
||||
new.has_references = bool(reference.HasReferences)
|
||||
new.referenced_source
|
||||
if reference.ReferencedSource.is_a("IfcClassificationReference"):
|
||||
props.active_library_referenced_source = reference.ReferencedSource.ReferencedSource.id()
|
||||
else:
|
||||
props.active_library_referenced_source = 0
|
||||
|
||||
|
||||
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")
|
||||
|
||||
|
||||
class BIMClassificationProperties(PropertyGroup):
|
||||
available_classifications: EnumProperty(
|
||||
items=getClassifications, name="Available Classifications", update=updateClassification
|
||||
)
|
||||
classification_attributes: CollectionProperty(name="Classification Attributes", type=Attribute)
|
||||
active_classification_id: IntProperty(name="Active Classification Id")
|
||||
available_library_references: CollectionProperty(name="Available Library References", type=ClassificationReference)
|
||||
active_library_referenced_source: IntProperty(name="Active Library Referenced Source")
|
||||
active_library_reference_index: IntProperty(name="Active Library Reference Index")
|
||||
|
||||
|
||||
class BIMClassificationReferenceProperties(PropertyGroup):
|
||||
reference_attributes: CollectionProperty(name="Reference Attributes", type=Attribute)
|
||||
active_reference_id: IntProperty(name="Active Reference Id")
|
||||
@@ -0,0 +1,27 @@
|
||||
import ifcopenshell.util.schema
|
||||
|
||||
|
||||
class Usecase:
|
||||
def __init__(self, file, settings=None):
|
||||
self.file = file
|
||||
self.settings = {"classification": None}
|
||||
for key, value in settings.items():
|
||||
self.settings[key] = value
|
||||
|
||||
def execute(self):
|
||||
references = self.get_references(self.settings["classification"])
|
||||
for reference in references:
|
||||
self.file.remove(reference)
|
||||
self.file.remove(self.settings["classification"])
|
||||
for rel in self.file.by_type("IfcRelAssociatesClassification"):
|
||||
if not rel.RelatingClassification:
|
||||
self.file.remove(rel)
|
||||
|
||||
def get_references(self, classification):
|
||||
results = []
|
||||
if not classification.HasReferences:
|
||||
return results
|
||||
for reference in classification.HasReferences:
|
||||
results.append(reference)
|
||||
results.extend(self.get_references(reference))
|
||||
return results
|
||||
@@ -0,0 +1,28 @@
|
||||
import ifcopenshell.util.schema
|
||||
|
||||
|
||||
class Usecase:
|
||||
def __init__(self, file, settings=None):
|
||||
self.file = file
|
||||
self.settings = {"reference": None, "product": None}
|
||||
for key, value in settings.items():
|
||||
self.settings[key] = value
|
||||
|
||||
def execute(self):
|
||||
total_related_objects = 0
|
||||
for association in self.file.by_type("IfcRelAssociatesClassification"):
|
||||
if association.RelatingClassification == self.settings["reference"] and association.RelatedObjects:
|
||||
total_related_objects += len(association.RelatedObjects)
|
||||
related_objects = list(association.RelatedObjects)
|
||||
try:
|
||||
related_objects.remove(self.settings["product"])
|
||||
except:
|
||||
continue
|
||||
if len(related_objects):
|
||||
association.RelatedObjects = related_objects
|
||||
else:
|
||||
self.file.remove(association)
|
||||
|
||||
# TODO: we only handle lightweight classifications here
|
||||
if total_related_objects == 1:
|
||||
self.file.remove(self.settings["reference"])
|
||||
@@ -0,0 +1,159 @@
|
||||
from bpy.types import Panel, UIList
|
||||
from blenderbim.bim.ifc import IfcStore
|
||||
from blenderbim.bim.module.classification.data import Data
|
||||
|
||||
|
||||
class BIM_PT_classifications(Panel):
|
||||
bl_label = "IFC Classifications"
|
||||
bl_idname = "BIM_PT_classifications"
|
||||
bl_options = {"DEFAULT_CLOSED"}
|
||||
bl_space_type = "PROPERTIES"
|
||||
bl_region_type = "WINDOW"
|
||||
bl_context = "scene"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return IfcStore.get_file()
|
||||
|
||||
def draw(self, context):
|
||||
if not Data.is_loaded:
|
||||
Data.load()
|
||||
|
||||
self.props = context.scene.BIMClassificationProperties
|
||||
|
||||
if Data.library_file:
|
||||
row = self.layout.row(align=True)
|
||||
row.prop(self.props, "available_classifications", text="")
|
||||
row.operator("bim.load_classification_library", text="", icon="IMPORT")
|
||||
row.operator("bim.add_classification", text="", icon="ADD")
|
||||
else:
|
||||
row = self.layout.row(align=True)
|
||||
row.label(text="No Active Classification Library")
|
||||
row.operator("bim.load_classification_library", text="", icon="IMPORT")
|
||||
|
||||
for classification_id, classification in Data.classifications.items():
|
||||
if self.props.active_classification_id == classification_id:
|
||||
self.draw_editable_ui(classification)
|
||||
else:
|
||||
self.draw_ui(classification_id, classification)
|
||||
|
||||
def draw_editable_ui(self, classification):
|
||||
row = self.layout.row(align=True)
|
||||
row.prop(self.props.classification_attributes.get("Name"), "string_value", text="", icon="ASSET_MANAGER")
|
||||
row.operator("bim.edit_classification", text="", icon="CHECKMARK")
|
||||
row.operator("bim.disable_editing_classification", text="", icon="X")
|
||||
|
||||
for attribute in self.props.classification_attributes:
|
||||
if attribute.name == "Name":
|
||||
continue
|
||||
row = self.layout.row(align=True)
|
||||
row.prop(attribute, "string_value", text=attribute.name)
|
||||
if attribute.is_optional:
|
||||
row.prop(attribute, "is_null", icon="RADIOBUT_OFF" if attribute.is_null else "RADIOBUT_ON", text="")
|
||||
|
||||
def draw_ui(self, classification_id, classification):
|
||||
row = self.layout.row(align=True)
|
||||
row.label(text=classification["Name"], icon="ASSET_MANAGER")
|
||||
if not self.props.active_classification_id:
|
||||
op = row.operator("bim.enable_editing_classification", text="", icon="GREASEPENCIL")
|
||||
op.classification = classification_id
|
||||
row.operator("bim.remove_classification", text="", icon="X").classification = classification_id
|
||||
|
||||
|
||||
class BIM_PT_classification_references(Panel):
|
||||
bl_label = "IFC Classification References"
|
||||
bl_idname = "BIM_PT_classification_references"
|
||||
bl_options = {"DEFAULT_CLOSED"}
|
||||
bl_space_type = "PROPERTIES"
|
||||
bl_region_type = "WINDOW"
|
||||
bl_context = "object"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return bool(context.active_object.BIMObjectProperties.ifc_definition_id)
|
||||
|
||||
def draw(self, context):
|
||||
obj = context.active_object
|
||||
self.oprops = obj.BIMObjectProperties
|
||||
self.sprops = context.scene.BIMClassificationProperties
|
||||
self.props = obj.BIMClassificationReferenceProperties
|
||||
self.file = IfcStore.get_file()
|
||||
if not Data.is_loaded:
|
||||
Data.load()
|
||||
if self.oprops.ifc_definition_id not in Data.products:
|
||||
Data.load(self.oprops.ifc_definition_id)
|
||||
|
||||
self.draw_add_ui()
|
||||
|
||||
reference_ids = Data.products[self.oprops.ifc_definition_id]
|
||||
if not reference_ids:
|
||||
row = self.layout.row(align=True)
|
||||
row.label(text="No References")
|
||||
|
||||
for reference_id in reference_ids:
|
||||
reference = Data.references[reference_id]
|
||||
if self.props.active_reference_id == reference_id:
|
||||
self.draw_editable_ui(reference)
|
||||
else:
|
||||
self.draw_ui(reference_id, reference)
|
||||
|
||||
def draw_add_ui(self):
|
||||
if not self.sprops.available_classifications:
|
||||
return
|
||||
|
||||
name = Data.library_classifications[int(self.sprops.available_classifications)]
|
||||
if name in [c["Name"] for c in Data.classifications.values()]:
|
||||
row = self.layout.row(align=True)
|
||||
row.prop(self.sprops, "available_classifications", text="")
|
||||
if self.sprops.active_library_referenced_source:
|
||||
op = row.operator("bim.change_classification_level", text="", icon="FRAME_PREV")
|
||||
op.parent_id = self.sprops.active_library_referenced_source
|
||||
op = row.operator("bim.add_classification_reference", text="", icon="ADD")
|
||||
op.reference = self.sprops.available_library_references[
|
||||
self.sprops.active_library_reference_index
|
||||
].ifc_definition_id
|
||||
self.layout.template_list(
|
||||
"BIM_UL_classifications",
|
||||
"",
|
||||
self.sprops,
|
||||
"available_library_references",
|
||||
self.sprops,
|
||||
"active_library_reference_index",
|
||||
)
|
||||
|
||||
def draw_editable_ui(self, reference):
|
||||
row = self.layout.row(align=True)
|
||||
row.prop(self.props.reference_attributes.get("Name"), "string_value", text="", icon="ASSET_MANAGER")
|
||||
row.operator("bim.edit_classification_reference", text="", icon="CHECKMARK")
|
||||
row.operator("bim.disable_editing_classification_reference", text="", icon="X")
|
||||
|
||||
for attribute in self.props.reference_attributes:
|
||||
if attribute.name == "Name":
|
||||
continue
|
||||
row = self.layout.row(align=True)
|
||||
row.prop(attribute, "string_value", text=attribute.name)
|
||||
if attribute.is_optional:
|
||||
row.prop(attribute, "is_null", icon="RADIOBUT_OFF" if attribute.is_null else "RADIOBUT_ON", text="")
|
||||
|
||||
def draw_ui(self, reference_id, reference):
|
||||
row = self.layout.row(align=True)
|
||||
if self.file.schema == "IFC2X3":
|
||||
name = reference["ItemReference"] or "No Identification"
|
||||
else:
|
||||
name = reference["Identification"] or "No Identification"
|
||||
row.label(text=name, icon="ASSET_MANAGER")
|
||||
row.label(text=reference["Name"] or "")
|
||||
if not self.props.active_reference_id:
|
||||
op = row.operator("bim.enable_editing_classification_reference", text="", icon="GREASEPENCIL")
|
||||
op.reference = reference_id
|
||||
row.operator("bim.remove_classification_reference", text="", icon="X").reference = reference_id
|
||||
|
||||
|
||||
class BIM_UL_classifications(UIList):
|
||||
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
|
||||
if item:
|
||||
if item.has_references:
|
||||
op = layout.operator("bim.change_classification_level", text="", icon="DISCLOSURE_TRI_RIGHT")
|
||||
op.parent_id = item.ifc_definition_id
|
||||
layout.label(text=item.identification)
|
||||
layout.label(text=item.name)
|
||||
@@ -1156,106 +1156,6 @@ class SelectSchemaDir(bpy.types.Operator):
|
||||
return {"RUNNING_MODAL"}
|
||||
|
||||
|
||||
class LoadClassification(bpy.types.Operator):
|
||||
bl_idname = "bim.load_classification"
|
||||
bl_label = "Load Classification"
|
||||
is_file: bpy.props.BoolProperty()
|
||||
classification_index: bpy.props.IntProperty()
|
||||
|
||||
def execute(self, context):
|
||||
from . import prop
|
||||
|
||||
if self.is_file:
|
||||
prop.ClassificationView.raw_data = schema.ifc.load_classification(
|
||||
context.scene.BIMProperties.classification
|
||||
)
|
||||
else:
|
||||
prop.ClassificationView.raw_data = schema.ifc.load_classification(
|
||||
context.scene.BIMProperties.classifications[self.classification_index].name, self.classification_index
|
||||
)
|
||||
context.scene.BIMProperties.classification_references.root = ""
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class AddClassification(bpy.types.Operator):
|
||||
bl_idname = "bim.add_classification"
|
||||
bl_label = "Add Classification"
|
||||
|
||||
def execute(self, context):
|
||||
if context.scene.BIMProperties.classification not in schema.ifc.classifications:
|
||||
return {"FINISHED"}
|
||||
data = schema.ifc.classifications[context.scene.BIMProperties.classification]
|
||||
classification = context.scene.BIMProperties.classifications.add()
|
||||
data_map = {
|
||||
"name": "Name",
|
||||
"source": "Source",
|
||||
"edition": "Edition",
|
||||
"edition_date": "EditionDate",
|
||||
"description": "Description",
|
||||
"location": "Location",
|
||||
"reference_tokens": "ReferenceTokens",
|
||||
}
|
||||
for key, value in data_map.items():
|
||||
if hasattr(data, value) and getattr(data, value):
|
||||
setattr(classification, key, str(getattr(data, value)))
|
||||
classification.data = schema.ifc.classification_files[context.scene.BIMProperties.classification].to_string()
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class RemoveClassification(bpy.types.Operator):
|
||||
bl_idname = "bim.remove_classification"
|
||||
bl_label = "Remove Classification"
|
||||
classification_index: bpy.props.IntProperty()
|
||||
|
||||
def execute(self, context):
|
||||
bpy.context.scene.BIMProperties.classifications.remove(self.classification_index)
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class AssignClassification(bpy.types.Operator):
|
||||
bl_idname = "bim.assign_classification"
|
||||
bl_label = "Assign Classification"
|
||||
|
||||
def execute(self, context):
|
||||
for obj in bpy.context.selected_objects:
|
||||
classification = obj.BIMObjectProperties.classifications.add()
|
||||
refs = bpy.context.scene.BIMProperties.classification_references
|
||||
data = refs.root["children"][refs.children[refs.active_index].name]
|
||||
if data["identification"]:
|
||||
classification.name = data["identification"]
|
||||
if data["name"]:
|
||||
classification.human_name = data["name"]
|
||||
for key in ["location", "description"]:
|
||||
if data[key]:
|
||||
setattr(classification, key, data[key])
|
||||
classification.referenced_source = bpy.context.scene.BIMProperties.active_classification_name
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class UnassignClassification(bpy.types.Operator):
|
||||
bl_idname = "bim.unassign_classification"
|
||||
bl_label = "Unassign Classification"
|
||||
|
||||
def execute(self, context):
|
||||
refs = bpy.context.scene.BIMProperties.classification_references
|
||||
key = refs.children[refs.active_index].name
|
||||
for obj in bpy.context.selected_objects:
|
||||
index = obj.BIMObjectProperties.classifications.find(key)
|
||||
if index != -1:
|
||||
obj.BIMObjectProperties.classifications.remove(index)
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class RemoveClassificationReference(bpy.types.Operator):
|
||||
bl_idname = "bim.remove_classification_reference"
|
||||
bl_label = "Remove Classification Reference"
|
||||
classification_index: bpy.props.IntProperty()
|
||||
|
||||
def execute(self, context):
|
||||
bpy.context.active_object.BIMObjectProperties.classifications.remove(self.classification_index)
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class FetchExternalMaterial(bpy.types.Operator):
|
||||
bl_idname = "bim.fetch_external_material"
|
||||
bl_label = "Fetch External Material"
|
||||
@@ -1735,27 +1635,6 @@ class CopyAttributeToSelection(bpy.types.Operator):
|
||||
return self.applicable_attributes_cache[ifc_class]
|
||||
|
||||
|
||||
class BIM_OT_ChangeClassificationLevel(bpy.types.Operator):
|
||||
bl_idname = "bim.change_classification_level"
|
||||
bl_label = "Change Classification Level"
|
||||
|
||||
# string representing the id-data (e.g. the scene).
|
||||
path_sid: bpy.props.StringProperty()
|
||||
# path from the id-data to the classification view object
|
||||
path_lst: bpy.props.StringProperty()
|
||||
# name of child entity to enter (empty = go up one level)
|
||||
path_itm: bpy.props.StringProperty()
|
||||
|
||||
def invoke(self, context, event):
|
||||
id_data = eval(self.path_sid)
|
||||
lst = id_data.path_resolve(self.path_lst)
|
||||
if self.path_itm:
|
||||
lst.root = self.path_itm
|
||||
else:
|
||||
lst.root = ""
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class AddPropertySetTemplate(bpy.types.Operator):
|
||||
bl_idname = "bim.add_property_set_template"
|
||||
bl_label = "Add Property Set Template"
|
||||
|
||||
@@ -37,7 +37,6 @@ materialpsetnames_enum = []
|
||||
psetfiles_enum = []
|
||||
psettemplatefiles_enum = []
|
||||
propertysettemplates_enum = []
|
||||
classification_enum = []
|
||||
attributes_enum = []
|
||||
materialattributes_enum = []
|
||||
contexts_enum = []
|
||||
@@ -357,21 +356,6 @@ def getPropertySetTemplates(self, context):
|
||||
return propertysettemplates_enum
|
||||
|
||||
|
||||
def getClassifications(self, context):
|
||||
global classification_enum
|
||||
if len(classification_enum) < 1:
|
||||
classification_enum.clear()
|
||||
files = os.listdir(os.path.join(self.schema_dir, "classifications"))
|
||||
classification_enum.extend([(f.replace(".ifc", ""), f.replace(".ifc", ""), "") for f in files])
|
||||
return classification_enum
|
||||
|
||||
|
||||
def refreshReferences(self, context):
|
||||
context.scene.BIMProperties.classification_references.root = None
|
||||
ClassificationView.raw_data = schema.ifc.load_classification(context.scene.BIMProperties.classification)
|
||||
context.scene.BIMProperties.classification_references.root = ""
|
||||
|
||||
|
||||
def getMaterialPsetNames(self, context):
|
||||
global materialpsetnames_enum
|
||||
materialpsetnames_enum.clear()
|
||||
@@ -922,76 +906,6 @@ class PropertyTemplate(PropertyGroup):
|
||||
)
|
||||
|
||||
|
||||
class Classification(PropertyGroup):
|
||||
name: StringProperty(name="Name")
|
||||
source: StringProperty(name="Source")
|
||||
edition: StringProperty(name="Edition")
|
||||
edition_date: StringProperty(name="Edition Date")
|
||||
description: StringProperty(name="Description")
|
||||
location: StringProperty(name="Location")
|
||||
reference_tokens: StringProperty(name="Reference Tokens")
|
||||
data: StringProperty(name="Data")
|
||||
|
||||
|
||||
class ClassificationReference(PropertyGroup):
|
||||
name: StringProperty(name="Identification")
|
||||
location: StringProperty(name="Location")
|
||||
human_name: StringProperty(name="Name")
|
||||
referenced_source: StringProperty(name="Source")
|
||||
description: StringProperty(name="Description")
|
||||
sort: StringProperty(name="Sort")
|
||||
|
||||
|
||||
class ClassificationView(PropertyGroup):
|
||||
crumbs: None
|
||||
children: None
|
||||
active_index: bpy.props.IntProperty()
|
||||
raw_data = {}
|
||||
|
||||
@property
|
||||
def root(self):
|
||||
data = self.raw_data
|
||||
for crumb in self.crumbs:
|
||||
data = data["children"].get(crumb.name)
|
||||
if not data:
|
||||
raise TypeError("Cannot resolve crumb path")
|
||||
return data
|
||||
|
||||
@root.setter
|
||||
def root(self, rt):
|
||||
if rt == None:
|
||||
self.crumbs.clear()
|
||||
self.children.clear()
|
||||
elif rt == "":
|
||||
if self.crumbs:
|
||||
self.crumbs.remove(len(self.crumbs) - 1)
|
||||
self.children.clear()
|
||||
for child in self.root["children"].keys():
|
||||
self.children.add().name = child
|
||||
else:
|
||||
data = self.root
|
||||
if rt in data["children"].keys():
|
||||
self.crumbs.add().name = rt
|
||||
self.children.clear()
|
||||
for child in data["children"][rt]["children"].keys():
|
||||
self.children.add().name = child
|
||||
|
||||
def draw_stub(self, context, layout):
|
||||
if not self.children:
|
||||
op = layout.operator("bim.change_classification_level", text="@Toplevel")
|
||||
else:
|
||||
op = layout.operator("bim.change_classification_level", text=self.root["name"])
|
||||
op.path_sid = "%r" % self.id_data
|
||||
op.path_lst = self.path_from_id()
|
||||
op.path_itm = ""
|
||||
layout.template_list("BIM_UL_classifications", self.path_from_id(), self, "children", self, "active_index")
|
||||
|
||||
|
||||
# Monkey-patched, just to keep registration in one block
|
||||
ClassificationView.__annotations__["crumbs"] = bpy.props.CollectionProperty(type=StrProperty)
|
||||
ClassificationView.__annotations__["children"] = bpy.props.CollectionProperty(type=StrProperty)
|
||||
|
||||
|
||||
class BIMProperties(PropertyGroup):
|
||||
schema_dir: StringProperty(default=os.path.join(cwd, "schema") + os.path.sep, name="Schema Directory")
|
||||
data_dir: StringProperty(default=os.path.join(cwd, "data") + os.path.sep, name="Data Directory")
|
||||
@@ -1042,14 +956,10 @@ class BIMProperties(PropertyGroup):
|
||||
search_pset_name: StringProperty(name="Search Pset Name")
|
||||
search_prop_name: StringProperty(name="Search Prop Name")
|
||||
search_pset_value: StringProperty(name="Search Pset Value")
|
||||
classification: EnumProperty(items=getClassifications, name="Classification", update=refreshReferences)
|
||||
active_classification_name: StringProperty(name="Active Classification Name")
|
||||
classifications: CollectionProperty(name="Classifications", type=Classification)
|
||||
contexts: EnumProperty(items=getContexts, name="Contexts")
|
||||
available_contexts: EnumProperty(items=[("Model", "Model", ""), ("Plan", "Plan", "")], name="Available Contexts")
|
||||
available_subcontexts: EnumProperty(items=getSubcontexts, name="Available Subcontexts")
|
||||
available_target_views: EnumProperty(items=getTargetViews, name="Available Target Views")
|
||||
classification_references: PointerProperty(type=ClassificationView)
|
||||
pset_template_files: EnumProperty(
|
||||
items=getPsetTemplateFiles, name="Pset Template Files", update=refreshPropertySetTemplates
|
||||
)
|
||||
@@ -1188,7 +1098,6 @@ class BIMObjectProperties(PropertyGroup):
|
||||
active_document_reference_index: IntProperty(name="Active Document Reference Index")
|
||||
constraints: CollectionProperty(name="Constraints", type=Constraint)
|
||||
active_constraint_index: IntProperty(name="Active Constraint Index")
|
||||
classifications: CollectionProperty(name="Classifications", type=ClassificationReference)
|
||||
has_boundary_condition: BoolProperty(name="Has Boundary Condition")
|
||||
boundary_condition: PointerProperty(name="Boundary Condition", type=BoundaryCondition)
|
||||
structural_member_connection: PointerProperty(name="Structural Member Connection", type=bpy.types.Object)
|
||||
|
||||
@@ -266,36 +266,6 @@ class BIM_PT_constraint_relations(Panel):
|
||||
layout.label(text="Constraint is invalid")
|
||||
|
||||
|
||||
class BIM_PT_classification_references(Panel):
|
||||
bl_label = "IFC Classification References"
|
||||
bl_idname = "BIM_PT_classification_references"
|
||||
bl_options = {"DEFAULT_CLOSED"}
|
||||
bl_space_type = "PROPERTIES"
|
||||
bl_region_type = "WINDOW"
|
||||
bl_context = "object"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.use_property_split = True
|
||||
props = context.active_object.BIMObjectProperties
|
||||
|
||||
if not props.classifications:
|
||||
layout.label(text="No classifications found")
|
||||
|
||||
for index, classification in enumerate(props.classifications):
|
||||
row = layout.row(align=True)
|
||||
row.prop(classification, "name")
|
||||
row.operator("bim.remove_classification_reference", icon="X", text="").classification_index = index
|
||||
row = layout.row(align=True)
|
||||
row.prop(classification, "human_name")
|
||||
row = layout.row(align=True)
|
||||
row.prop(classification, "location")
|
||||
row = layout.row(align=True)
|
||||
row.prop(classification, "description")
|
||||
row = layout.row(align=True)
|
||||
row.prop(classification, "referenced_source")
|
||||
|
||||
|
||||
class BIM_PT_psets(Panel):
|
||||
bl_label = "IFC Property Sets"
|
||||
bl_idname = "BIM_PT_psets"
|
||||
@@ -340,58 +310,6 @@ class BIM_PT_psets(Panel):
|
||||
row.operator("bim.remove_property_template", icon="X", text="").index = index
|
||||
|
||||
|
||||
class BIM_PT_classifications(Panel):
|
||||
bl_label = "IFC Classifications"
|
||||
bl_idname = "BIM_PT_classifications"
|
||||
bl_options = {"DEFAULT_CLOSED"}
|
||||
bl_space_type = "PROPERTIES"
|
||||
bl_region_type = "WINDOW"
|
||||
bl_context = "scene"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
props = context.scene.BIMProperties
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.prop(props, "classification", text="")
|
||||
row.operator("bim.add_classification", text="", icon="ADD")
|
||||
|
||||
if context.scene.BIMProperties.classification_references.raw_data:
|
||||
context.scene.BIMProperties.classification_references.draw_stub(context, layout)
|
||||
row = layout.row(align=True)
|
||||
row.operator("bim.assign_classification")
|
||||
row.operator("bim.unassign_classification")
|
||||
else:
|
||||
row = layout.row(align=True)
|
||||
row.operator("bim.load_classification").is_file = True
|
||||
|
||||
if not props.classifications:
|
||||
return
|
||||
|
||||
layout.label(text="Classifications:")
|
||||
|
||||
for index, classification in enumerate(props.classifications):
|
||||
row = layout.row(align=True)
|
||||
row.prop(classification, "name")
|
||||
row.operator("bim.load_classification", icon="IMPORT", text="").classification_index = index
|
||||
row.operator("bim.remove_classification", icon="X", text="").classification_index = index
|
||||
row = layout.row(align=True)
|
||||
row.prop(classification, "source")
|
||||
row = layout.row(align=True)
|
||||
row.prop(classification, "edition")
|
||||
row = layout.row(align=True)
|
||||
row.prop(classification, "edition_date")
|
||||
row = layout.row(align=True)
|
||||
row.prop(classification, "description")
|
||||
row = layout.row(align=True)
|
||||
row.prop(classification, "location")
|
||||
row = layout.row(align=True)
|
||||
row.prop(classification, "reference_tokens")
|
||||
|
||||
row = layout.row()
|
||||
row.prop(props, "classifications")
|
||||
|
||||
|
||||
class BIM_PT_presentation_layer_data(Panel):
|
||||
bl_label = "IFC Presentation Layers"
|
||||
bl_idname = "BIM_PT_presentation"
|
||||
@@ -1015,25 +933,6 @@ class BIM_UL_document_references(bpy.types.UIList):
|
||||
layout.label(text="", translate=False)
|
||||
|
||||
|
||||
class BIM_UL_classifications(bpy.types.UIList):
|
||||
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
|
||||
if self.layout_type in {"DEFAULT", "COMPACT"}:
|
||||
rt = data.root
|
||||
ch = rt["children"]
|
||||
itemdata = ch[item.name]
|
||||
if itemdata.get("children", {}):
|
||||
op = layout.operator(
|
||||
"bim.change_classification_level", text="", emboss=False, icon="DISCLOSURE_TRI_RIGHT"
|
||||
)
|
||||
op.path_sid = "%r" % active_data.id_data # get id-data
|
||||
op.path_lst = active_data.path_from_id() # path to view
|
||||
op.path_itm = item.name # name of child. empty = go up
|
||||
else:
|
||||
layout.label(text="", icon="BLANK1")
|
||||
layout.prop(item, "name", text="", emboss=False)
|
||||
layout.label(text=itemdata["name"])
|
||||
|
||||
|
||||
class BIM_ADDON_preferences(bpy.types.AddonPreferences):
|
||||
bl_idname = "blenderbim"
|
||||
svg2pdf_command: StringProperty(name="SVG to PDF Command", description="E.g. [['inkscape', svg, '-o', pdf]]")
|
||||
|
||||
Reference in New Issue
Block a user