Fix #2364. Bug where classifications couldn't be added in IFC2X3.

This commit is contained in:
Dion Moult
2022-09-02 14:03:05 +10:00
parent f9db685753
commit 0293c133ab
8 changed files with 233 additions and 213 deletions
+2
View File
@@ -39,6 +39,8 @@ class IfcStore:
edited_objs = set() edited_objs = set()
pset_template_path = "" pset_template_path = ""
pset_template_file = None pset_template_file = None
classification_path = ""
classification_file = None
library_path = "" library_path = ""
library_file = None library_file = None
element_listeners = set() element_listeners = set()
@@ -20,18 +20,19 @@ import bpy
from . import ui, prop, operator from . import ui, prop, operator
classes = ( classes = (
operator.LoadClassificationLibrary,
operator.AddClassification, operator.AddClassification,
operator.RemoveClassification,
operator.EnableEditingClassification,
operator.DisableEditingClassification,
operator.EditClassification,
operator.RemoveClassificationReference,
operator.EnableEditingClassificationReference,
operator.DisableEditingClassificationReference,
operator.EditClassificationReference,
operator.AddClassificationReference, operator.AddClassificationReference,
operator.ChangeClassificationLevel, operator.ChangeClassificationLevel,
operator.DisableEditingClassification,
operator.DisableEditingClassificationReference,
operator.DisableEditingClassificationReferences,
operator.EditClassification,
operator.EditClassificationReference,
operator.EnableEditingClassification,
operator.EnableEditingClassificationReference,
operator.LoadClassificationLibrary,
operator.RemoveClassification,
operator.RemoveClassificationReference,
prop.ClassificationReference, prop.ClassificationReference,
prop.BIMClassificationProperties, prop.BIMClassificationProperties,
prop.BIMClassificationReferenceProperties, prop.BIMClassificationReferenceProperties,
@@ -0,0 +1,91 @@
# BlenderBIM Add-on - OpenBIM Blender Add-on
# Copyright (C) 2022 Dion Moult <dion@thinkmoult.com>
#
# This file is part of BlenderBIM Add-on.
#
# BlenderBIM Add-on 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.
#
# BlenderBIM Add-on 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 BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
import bpy
import ifcopenshell
import ifcopenshell.util.date
import ifcopenshell.util.classification
import blenderbim.tool as tool
from blenderbim.bim.ifc import IfcStore
def refresh():
ClassificationsData.is_loaded = False
ClassificationReferencesData.is_loaded = False
class ClassificationsData:
data = {}
is_loaded = False
@classmethod
def load(cls):
cls.is_loaded = True
cls.data["has_classification_file"] = cls.has_classification_file()
cls.data["classifications"] = cls.classifications()
cls.data["available_classifications"] = cls.available_classifications()
@classmethod
def has_classification_file(cls):
return bool(IfcStore.classification_file)
@classmethod
def classifications(cls):
results = []
for element in tool.Ifc.get().by_type("IfcClassification"):
data = element.get_info()
if IfcStore.classification_file.schema == "IFC2X3" and element.EditionDate:
data["EditionDate"] = ifcopenshell.util.date.ifc2datetime(data["EditionDate"])
results.append(data)
return results
@classmethod
def available_classifications(cls):
if not IfcStore.classification_file:
return []
return [(str(e.id()), e.Name, "") for e in IfcStore.classification_file.by_type("IfcClassification")]
class ClassificationReferencesData:
data = {}
is_loaded = False
@classmethod
def load(cls):
cls.is_loaded = True
cls.data["references"] = cls.references()
cls.data["is_available_classification_added"] = cls.is_available_classification_added()
@classmethod
def references(cls):
results = []
element = tool.Ifc.get_entity(bpy.context.active_object)
if element:
for reference in ifcopenshell.util.classification.get_references(element):
data = reference.get_info()
del data["ReferencedSource"]
results.append(data)
return results
@classmethod
def is_available_classification_added(cls):
if not IfcStore.classification_file or not IfcStore.classification_file.by_type("IfcClassification"):
return False
props = bpy.context.scene.BIMClassificationProperties
name = IfcStore.classification_file.by_id(int(props.available_classifications)).Name
return name in [e.Name for e in tool.Ifc.get().by_type("IfcClassification")]
@@ -1,5 +1,5 @@
# BlenderBIM Add-on - OpenBIM Blender Add-on # BlenderBIM Add-on - OpenBIM Blender Add-on
# Copyright (C) 2020, 2021 Dion Moult <dion@thinkmoult.com> # Copyright (C) 2020-2022 Dion Moult <dion@thinkmoult.com>
# #
# This file is part of BlenderBIM Add-on. # This file is part of BlenderBIM Add-on.
# #
@@ -18,46 +18,40 @@
import bpy import bpy
import json import json
import ifcopenshell
import ifcopenshell.api import ifcopenshell.api
import blenderbim.tool as tool
import blenderbim.bim.helper
from blenderbim.bim.ifc import IfcStore from blenderbim.bim.ifc import IfcStore
from ifcopenshell.api.classification.data import Data
from blenderbim.bim.module.classification.prop import getClassifications, getReferences
class LoadClassificationLibrary(bpy.types.Operator): class LoadClassificationLibrary(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.load_classification_library" bl_idname = "bim.load_classification_library"
bl_label = "Load Classification Library" bl_label = "Load Classification Library"
filename_ext = ".ifc" filename_ext = ".ifc"
filter_glob: bpy.props.StringProperty(default="*.ifc;*.ifczip;*.ifcxml", options={"HIDDEN"}) filter_glob: bpy.props.StringProperty(default="*.ifc;*.ifczip;*.ifcxml", options={"HIDDEN"})
filepath: bpy.props.StringProperty(subtype="FILE_PATH") 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): def invoke(self, context, event):
context.window_manager.fileselect_add(self) context.window_manager.fileselect_add(self)
return {"RUNNING_MODAL"} return {"RUNNING_MODAL"}
def _execute(self, context):
IfcStore.classification_file = ifcopenshell.open(self.filepath)
class AddClassification(bpy.types.Operator):
class AddClassification(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.add_classification" bl_idname = "bim.add_classification"
bl_label = "Add Classification" bl_label = "Add Classification"
bl_options = {"REGISTER", "UNDO"} bl_options = {"REGISTER", "UNDO"}
def execute(self, context):
return IfcStore.execute_ifc_operator(self, context)
def _execute(self, context): def _execute(self, context):
props = context.scene.BIMClassificationProperties props = context.scene.BIMClassificationProperties
ifcopenshell.api.run( ifcopenshell.api.run(
"classification.add_classification", "classification.add_classification",
IfcStore.get_file(), tool.Ifc.get(),
**{"classification": Data.library_file.by_id(int(props.available_classifications))}, classification=IfcStore.classification_file.by_id(int(props.available_classifications)),
) )
Data.load(IfcStore.get_file())
return {"FINISHED"}
class EnableEditingClassification(bpy.types.Operator): class EnableEditingClassification(bpy.types.Operator):
@@ -67,19 +61,21 @@ class EnableEditingClassification(bpy.types.Operator):
classification: bpy.props.IntProperty() classification: bpy.props.IntProperty()
def execute(self, context): def execute(self, context):
def callback(name, prop, data):
if name == "ReferenceTokens":
new = bpy.context.scene.BIMGeoreferenceProperties.projected_crs.add()
new.name = name
new.data_type = "string"
new.is_null = data[name] is None
new.is_optional = True
new.string_value = "" if new.is_null else json.dumps(data[name])
return True
props = context.scene.BIMClassificationProperties props = context.scene.BIMClassificationProperties
props.classification_attributes.clear() props.classification_attributes.clear()
classification_data = Data.classifications[self.classification] blenderbim.bim.helper.import_attributes2(
for attribute in IfcStore.get_schema().declaration_by_name("IfcClassification").all_attributes(): tool.Ifc.get().by_id(self.classification), props.classification_attributes, callback
new = props.classification_attributes.add() )
new.name = attribute.name()
new.is_null = classification_data[attribute.name()] is None
new.is_optional = attribute.optional()
new.data_type = "string"
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 props.active_classification_id = self.classification
return {"FINISHED"} return {"FINISHED"}
@@ -94,34 +90,26 @@ class DisableEditingClassification(bpy.types.Operator):
return {"FINISHED"} return {"FINISHED"}
class RemoveClassification(bpy.types.Operator): class RemoveClassification(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.remove_classification" bl_idname = "bim.remove_classification"
bl_label = "Remove Classification" bl_label = "Remove Classification"
bl_options = {"REGISTER", "UNDO"} bl_options = {"REGISTER", "UNDO"}
classification: bpy.props.IntProperty() classification: bpy.props.IntProperty()
def execute(self, context):
return IfcStore.execute_ifc_operator(self, context)
def _execute(self, context): def _execute(self, context):
self.file = IfcStore.get_file() self.file = IfcStore.get_file()
ifcopenshell.api.run( ifcopenshell.api.run(
"classification.remove_classification", "classification.remove_classification",
self.file, tool.Ifc.get(),
**{"classification": self.file.by_id(self.classification)}, classification=self.file.by_id(self.classification),
) )
Data.load(IfcStore.get_file())
return {"FINISHED"}
class EditClassification(bpy.types.Operator): class EditClassification(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.edit_classification" bl_idname = "bim.edit_classification"
bl_label = "Edit Classification" bl_label = "Edit Classification"
bl_options = {"REGISTER", "UNDO"} bl_options = {"REGISTER", "UNDO"}
def execute(self, context):
return IfcStore.execute_ifc_operator(self, context)
def _execute(self, context): def _execute(self, context):
props = context.scene.BIMClassificationProperties props = context.scene.BIMClassificationProperties
attributes = {} attributes = {}
@@ -138,9 +126,7 @@ class EditClassification(bpy.types.Operator):
self.file, self.file,
**{"classification": self.file.by_id(props.active_classification_id), "attributes": attributes}, **{"classification": self.file.by_id(props.active_classification_id), "attributes": attributes},
) )
Data.load(IfcStore.get_file())
bpy.ops.bim.disable_editing_classification() bpy.ops.bim.disable_editing_classification()
return {"FINISHED"}
class EnableEditingClassificationReference(bpy.types.Operator): class EnableEditingClassificationReference(bpy.types.Operator):
@@ -154,16 +140,7 @@ class EnableEditingClassificationReference(bpy.types.Operator):
obj = bpy.data.objects.get(self.obj) if self.obj else context.active_object obj = bpy.data.objects.get(self.obj) if self.obj else context.active_object
props = obj.BIMClassificationReferenceProperties props = obj.BIMClassificationReferenceProperties
props.reference_attributes.clear() props.reference_attributes.clear()
reference_data = Data.references[self.reference] blenderbim.bim.helper.import_attributes2(tool.Ifc.get().by_id(self.reference), props.reference_attributes)
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.data_type = "string"
new.string_value = "" if new.is_null else reference_data[attribute.name()]
props.active_reference_id = self.reference props.active_reference_id = self.reference
return {"FINISHED"} return {"FINISHED"}
@@ -180,41 +157,30 @@ class DisableEditingClassificationReference(bpy.types.Operator):
return {"FINISHED"} return {"FINISHED"}
class RemoveClassificationReference(bpy.types.Operator): class RemoveClassificationReference(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.remove_classification_reference" bl_idname = "bim.remove_classification_reference"
bl_label = "Remove Classification Reference" bl_label = "Remove Classification Reference"
bl_options = {"REGISTER", "UNDO"} bl_options = {"REGISTER", "UNDO"}
reference: bpy.props.IntProperty() reference: bpy.props.IntProperty()
obj: bpy.props.StringProperty() obj: bpy.props.StringProperty()
def execute(self, context):
return IfcStore.execute_ifc_operator(self, context)
def _execute(self, context): def _execute(self, context):
obj = bpy.data.objects.get(self.obj) if self.obj else context.active_object obj = bpy.data.objects.get(self.obj) if self.obj else context.active_object
self.file = IfcStore.get_file() self.file = IfcStore.get_file()
ifcopenshell.api.run( ifcopenshell.api.run(
"classification.remove_reference", "classification.remove_reference",
self.file, self.file,
**{ reference=self.file.by_id(self.reference),
"reference": self.file.by_id(self.reference), product=self.file.by_id(obj.BIMObjectProperties.ifc_definition_id),
"product": self.file.by_id(obj.BIMObjectProperties.ifc_definition_id),
},
) )
Data.load(IfcStore.get_file(), obj.BIMObjectProperties.ifc_definition_id)
Data.load(IfcStore.get_file())
return {"FINISHED"}
class EditClassificationReference(bpy.types.Operator): class EditClassificationReference(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.edit_classification_reference" bl_idname = "bim.edit_classification_reference"
bl_label = "Edit Classification Reference" bl_label = "Edit Classification Reference"
bl_options = {"REGISTER", "UNDO"} bl_options = {"REGISTER", "UNDO"}
obj: bpy.props.StringProperty() obj: bpy.props.StringProperty()
def execute(self, context):
return IfcStore.execute_ifc_operator(self, context)
def _execute(self, context): def _execute(self, context):
obj = bpy.data.objects.get(self.obj) if self.obj else context.active_object obj = bpy.data.objects.get(self.obj) if self.obj else context.active_object
props = obj.BIMClassificationReferenceProperties props = obj.BIMClassificationReferenceProperties
@@ -228,48 +194,37 @@ class EditClassificationReference(bpy.types.Operator):
ifcopenshell.api.run( ifcopenshell.api.run(
"classification.edit_reference", "classification.edit_reference",
self.file, self.file,
**{"reference": self.file.by_id(props.active_reference_id), "attributes": attributes}, reference=self.file.by_id(props.active_reference_id), attributes=attributes,
) )
Data.load(IfcStore.get_file())
bpy.ops.bim.disable_editing_classification_reference() bpy.ops.bim.disable_editing_classification_reference()
return {"FINISHED"}
class AddClassificationReference(bpy.types.Operator): class AddClassificationReference(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.add_classification_reference" bl_idname = "bim.add_classification_reference"
bl_label = "Add Classification Reference" bl_label = "Add Classification Reference"
bl_options = {"REGISTER", "UNDO"} bl_options = {"REGISTER", "UNDO"}
reference: bpy.props.IntProperty() reference: bpy.props.IntProperty()
obj: bpy.props.StringProperty() obj: bpy.props.StringProperty()
def execute(self, context):
return IfcStore.execute_ifc_operator(self, context)
def _execute(self, context): def _execute(self, context):
obj = bpy.data.objects.get(self.obj) if self.obj else context.active_object obj = bpy.data.objects.get(self.obj) if self.obj else context.active_object
self.file = IfcStore.get_file() self.file = IfcStore.get_file()
classification = None
props = context.scene.BIMClassificationProperties props = context.scene.BIMClassificationProperties
classification_name = Data.library_classifications[int(props.available_classifications)] classification = None
for classification_id, classification in Data.classifications.items(): classification_name = IfcStore.classification_file.by_id(int(props.available_classifications)).Name
if classification["Name"] == classification_name: for element in tool.Ifc.get().by_type("IfcClassification"):
classification = self.file.by_id(classification_id) if element.Name == classification_name:
classification = element
break break
ifcopenshell.api.run( ifcopenshell.api.run(
"classification.add_reference", "classification.add_reference",
self.file, self.file,
**{ reference=IfcStore.classification_file.by_id(self.reference),
"reference": Data.library_file.by_id(self.reference), product=tool.Ifc.get_entity(obj),
"product": self.file.by_id(obj.BIMObjectProperties.ifc_definition_id), classification=classification,
"classification": classification,
},
) )
Data.load(IfcStore.get_file(), obj.BIMObjectProperties.ifc_definition_id)
Data.load(IfcStore.get_file())
return {"FINISHED"}
class ChangeClassificationLevel(bpy.types.Operator): class ChangeClassificationLevel(bpy.types.Operator):
@@ -279,5 +234,27 @@ class ChangeClassificationLevel(bpy.types.Operator):
parent_id: bpy.props.IntProperty() parent_id: bpy.props.IntProperty()
def execute(self, context): def execute(self, context):
getReferences(self, context, parent_id=self.parent_id) props = context.scene.BIMClassificationProperties
props.available_library_references.clear()
for reference in IfcStore.classification_file.by_id(self.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
return {"FINISHED"} return {"FINISHED"}
class DisableEditingClassificationReferences(bpy.types.Operator):
bl_idname = "bim.disable_editing_classification_references"
bl_label = "Disable Editing Classification References"
bl_options = {"REGISTER", "UNDO"}
def execute(self, context):
props = context.scene.BIMClassificationProperties
props.available_library_references.clear()
@@ -17,8 +17,9 @@
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>. # along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
import bpy import bpy
from blenderbim.bim.ifc import IfcStore
from blenderbim.bim.prop import StrProperty, Attribute from blenderbim.bim.prop import StrProperty, Attribute
from ifcopenshell.api.classification.data import Data from blenderbim.bim.module.classification.data import ClassificationsData
from bpy.types import PropertyGroup from bpy.types import PropertyGroup
from bpy.props import ( from bpy.props import (
PointerProperty, PointerProperty,
@@ -31,42 +32,10 @@ from bpy.props import (
CollectionProperty, CollectionProperty,
) )
classification_enum = [] def get_available_classifications(self, context):
if not ClassificationsData.is_loaded:
ClassificationsData.load()
def purge(): return ClassificationsData.data["available_classifications"]
global classification_enum
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
props.available_library_references.clear()
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): class ClassificationReference(PropertyGroup):
@@ -78,9 +47,7 @@ class ClassificationReference(PropertyGroup):
class BIMClassificationProperties(PropertyGroup): class BIMClassificationProperties(PropertyGroup):
available_classifications: EnumProperty( available_classifications: EnumProperty(items=get_available_classifications, name="Available Classifications")
items=getClassifications, name="Available Classifications", update=updateClassification
)
classification_attributes: CollectionProperty(name="Classification Attributes", type=Attribute) classification_attributes: CollectionProperty(name="Classification Attributes", type=Attribute)
active_classification_id: IntProperty(name="Active Classification Id") active_classification_id: IntProperty(name="Active Classification Id")
available_library_references: CollectionProperty(name="Available Library References", type=ClassificationReference) available_library_references: CollectionProperty(name="Available Library References", type=ClassificationReference)
@@ -16,10 +16,12 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>. # along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
import blenderbim.bim.helper
import blenderbim.tool as tool
import blenderbim.bim.module.classification.prop as classification_prop import blenderbim.bim.module.classification.prop as classification_prop
from bpy.types import Panel, UIList from bpy.types import Panel, UIList
from blenderbim.bim.ifc import IfcStore from blenderbim.bim.ifc import IfcStore
from ifcopenshell.api.classification.data import Data from blenderbim.bim.module.classification.data import ClassificationsData, ClassificationReferencesData
class BIM_PT_classifications(Panel): class BIM_PT_classifications(Panel):
@@ -33,15 +35,15 @@ class BIM_PT_classifications(Panel):
@classmethod @classmethod
def poll(cls, context): def poll(cls, context):
return IfcStore.get_file() return tool.Ifc.get()
def draw(self, context): def draw(self, context):
if not Data.is_loaded: if not ClassificationsData.is_loaded:
Data.load(IfcStore.get_file()) ClassificationsData.load()
self.props = context.scene.BIMClassificationProperties self.props = context.scene.BIMClassificationProperties
if Data.library_file: if ClassificationsData.data["has_classification_file"]:
row = self.layout.row(align=True) row = self.layout.row(align=True)
row.prop(self.props, "available_classifications", text="") row.prop(self.props, "available_classifications", text="")
row.operator("bim.load_classification_library", text="", icon="IMPORT") row.operator("bim.load_classification_library", text="", icon="IMPORT")
@@ -51,33 +53,25 @@ class BIM_PT_classifications(Panel):
row.label(text="No Active Classification Library") row.label(text="No Active Classification Library")
row.operator("bim.load_classification_library", text="", icon="IMPORT") row.operator("bim.load_classification_library", text="", icon="IMPORT")
for classification_id, classification in Data.classifications.items(): for classification in ClassificationsData.data["classifications"]:
if self.props.active_classification_id == classification_id: if self.props.active_classification_id == classification["id"]:
self.draw_editable_ui(classification) self.draw_editable_ui()
else: else:
self.draw_ui(classification_id, classification) self.draw_ui(classification)
def draw_editable_ui(self, classification): def draw_editable_ui(self):
row = self.layout.row(align=True) 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="Save changes", icon="CHECKMARK")
row.operator("bim.edit_classification", text="", icon="CHECKMARK")
row.operator("bim.disable_editing_classification", text="", icon="CANCEL") row.operator("bim.disable_editing_classification", text="", icon="CANCEL")
blenderbim.bim.helper.draw_attributes(self.props.classification_attributes, self.layout)
for attribute in self.props.classification_attributes: def draw_ui(self, classification):
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 = self.layout.row(align=True)
row.label(text=classification["Name"], icon="ASSET_MANAGER") row.label(text=classification["Name"], icon="ASSET_MANAGER")
if not self.props.active_classification_id: if not self.props.active_classification_id:
op = row.operator("bim.enable_editing_classification", text="", icon="GREASEPENCIL") op = row.operator("bim.enable_editing_classification", text="", icon="GREASEPENCIL")
op.classification = classification_id op.classification = classification["id"]
row.operator("bim.remove_classification", text="", icon="X").classification = classification_id row.operator("bim.remove_classification", text="", icon="X").classification = classification["id"]
class BIM_PT_classification_references(Panel): class BIM_PT_classification_references(Panel):
@@ -93,74 +87,63 @@ class BIM_PT_classification_references(Panel):
def poll(cls, context): def poll(cls, context):
if not context.active_object: if not context.active_object:
return False return False
if not IfcStore.get_element(context.active_object.BIMObjectProperties.ifc_definition_id): return bool(tool.Ifc.get_entity(context.active_object))
return False
return bool(context.active_object.BIMObjectProperties.ifc_definition_id)
def draw(self, context): def draw(self, context):
if not ClassificationReferencesData.is_loaded:
ClassificationReferencesData.load()
obj = context.active_object obj = context.active_object
self.oprops = obj.BIMObjectProperties self.oprops = obj.BIMObjectProperties
self.sprops = context.scene.BIMClassificationProperties self.sprops = context.scene.BIMClassificationProperties
self.props = obj.BIMClassificationReferenceProperties self.props = obj.BIMClassificationReferenceProperties
self.file = IfcStore.get_file() self.file = IfcStore.get_file()
if not Data.is_loaded:
Data.load(IfcStore.get_file())
if self.oprops.ifc_definition_id not in Data.products:
Data.load(IfcStore.get_file(), self.oprops.ifc_definition_id)
self.draw_add_ui(context) self.draw_add_ui(context)
reference_ids = Data.products[self.oprops.ifc_definition_id] if not ClassificationReferencesData.data["references"]:
if not reference_ids:
row = self.layout.row(align=True) row = self.layout.row(align=True)
row.label(text="No References") row.label(text="No References")
for reference_id in reference_ids: for reference in ClassificationReferencesData.data["references"]:
reference = Data.references[reference_id] if self.props.active_reference_id == reference["id"]:
if self.props.active_reference_id == reference_id: self.draw_editable_ui()
self.draw_editable_ui(reference)
else: else:
self.draw_ui(reference_id, reference) self.draw_ui(reference)
def draw_add_ui(self, context): def draw_add_ui(self, context):
if not classification_prop.getClassifications(self.sprops, context): if not ClassificationReferencesData.data["is_available_classification_added"]:
return 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 = self.layout.row(align=True)
row.prop(self.props.reference_attributes.get("Name"), "string_value", text="", icon="ASSET_MANAGER") row.prop(self.sprops, "available_classifications", text="")
row.operator("bim.edit_classification_reference", text="", icon="CHECKMARK") if not self.sprops.available_library_references:
op = row.operator("bim.change_classification_level", text="", icon="IMPORT")
op.parent_id = int(self.sprops.available_classifications)
return
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
row.operator("bim.disable_editing_classification_references", text="", icon="CANCEL")
self.layout.template_list(
"BIM_UL_classifications",
"",
self.sprops,
"available_library_references",
self.sprops,
"active_library_reference_index",
)
def draw_editable_ui(self):
row = self.layout.row(align=True)
row.operator("bim.edit_classification_reference", text="Save changes", icon="CHECKMARK")
row.operator("bim.disable_editing_classification_reference", text="", icon="CANCEL") row.operator("bim.disable_editing_classification_reference", text="", icon="CANCEL")
blenderbim.bim.helper.draw_attributes(self.props.reference_attributes, self.layout)
for attribute in self.props.reference_attributes: def draw_ui(self, reference):
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) row = self.layout.row(align=True)
if self.file.schema == "IFC2X3": if self.file.schema == "IFC2X3":
name = reference["ItemReference"] or "No Identification" name = reference["ItemReference"] or "No Identification"
@@ -170,8 +153,8 @@ class BIM_PT_classification_references(Panel):
row.label(text=reference["Name"] or "") row.label(text=reference["Name"] or "")
if not self.props.active_reference_id: if not self.props.active_reference_id:
op = row.operator("bim.enable_editing_classification_reference", text="", icon="GREASEPENCIL") op = row.operator("bim.enable_editing_classification_reference", text="", icon="GREASEPENCIL")
op.reference = reference_id op.reference = reference["id"]
row.operator("bim.remove_classification_reference", text="", icon="X").reference = reference_id row.operator("bim.remove_classification_reference", text="", icon="X").reference = reference["id"]
class BIM_UL_classifications(UIList): class BIM_UL_classifications(UIList):
@@ -18,7 +18,6 @@
import bpy import bpy
from bpy.types import Panel from bpy.types import Panel
from blenderbim.bim.ifc import IfcStore
from blenderbim.bim.helper import prop_with_search from blenderbim.bim.helper import prop_with_search
from blenderbim.bim.module.pset_template.data import PsetTemplatesData from blenderbim.bim.module.pset_template.data import PsetTemplatesData
@@ -66,7 +66,7 @@ class Data:
for classification in cls._file.by_type("IfcClassification"): for classification in cls._file.by_type("IfcClassification"):
data = classification.get_info() data = classification.get_info()
if cls._file.schema == "IFC2X3" and data["EditionDate"]: if cls._file.schema == "IFC2X3" and data["EditionDate"]:
data["EditionDate"] = ifcopenshell.util.date(data.EditionDate).isoformat() data["EditionDate"] = ifcopenshell.util.date.ifc2datetime(data["EditionDate"]).isoformat()
cls.classifications[classification.id()] = data cls.classifications[classification.id()] = data
@classmethod @classmethod