WIP refactor root module properties. See #1222.

This commit is contained in:
Dion Moult
2021-01-23 12:54:27 +11:00
parent d1e2ac4c5a
commit 86e3d1e548
8 changed files with 138 additions and 111 deletions
@@ -5,6 +5,7 @@ import os
import webbrowser import webbrowser
from pathlib import Path from pathlib import Path
from itertools import cycle from itertools import cycle
from blenderbim.bim.ifc import IfcStore
class ExecuteBIMTester(bpy.types.Operator): class ExecuteBIMTester(bpy.types.Operator):
@@ -67,12 +68,11 @@ class RejectElement(bpy.types.Operator):
def execute(self, context): def execute(self, context):
lines = [] lines = []
for object in bpy.context.selected_objects: self.file = IfcStore.get_file()
for obj in bpy.context.selected_objects:
lines.append( lines.append(
" * The element {} should not exist because {}".format( " * The element {} should not exist because {}".format(
object.BIMObjectProperties.attributes[ self.file.by_id(obj.BIMObjectProperties.ifc_definition_id).GlobalId,
object.BIMObjectProperties.attributes.find("GlobalId")
].string_value,
bpy.context.scene.BimTesterProperties.qa_reject_element_reason, bpy.context.scene.BimTesterProperties.qa_reject_element_reason,
) )
) )
@@ -112,14 +112,16 @@ class ApproveClass(bpy.types.Operator):
def execute(self, context): def execute(self, context):
lines = [] lines = []
for object in bpy.context.selected_objects: self.file = IfcStore.get_file()
index = object.BIMObjectProperties.attributes.find("GlobalId") for obj in bpy.context.selected_objects:
if index != -1: if not obj.BIMObjectProperties.ifc_definition_id:
lines.append( continue
" * The element {} is an {}".format( element = self.file.by_id(obj.BIMObjectProperties.ifc_definition_id)
object.BIMObjectProperties.attributes[index].string_value, object.name.split("/")[0] lines.append(
) " * The element {} is an {}".format(
element.GlobalId, element.is_a()
) )
)
QAHelper.append_to_scenario(lines) QAHelper.append_to_scenario(lines)
return {"FINISHED"} return {"FINISHED"}
@@ -129,12 +131,13 @@ class RejectClass(bpy.types.Operator):
def execute(self, context): def execute(self, context):
lines = [] lines = []
for object in bpy.context.selected_objects: self.file = IfcStore.get_file()
for obj in bpy.context.selected_objects:
if not obj.BIMObjectProperties.ifc_definition_id:
continue
lines.append( lines.append(
" * The element {} is an {}".format( " * The element {} is an {}".format(
object.BIMObjectProperties.attributes[ self.file.by_id(obj.BIMObjectProperties.ifc_definition_id).GlobalId,
object.BIMObjectProperties.attributes.find("GlobalId")
].string_value,
bpy.context.scene.BimTesterProperties.audit_ifc_class, bpy.context.scene.BimTesterProperties.audit_ifc_class,
) )
) )
@@ -147,6 +150,7 @@ class SelectAudited(bpy.types.Operator):
def execute(self, context): def execute(self, context):
audited_global_ids = [] audited_global_ids = []
self.file = IfcStore.get_file()
for filename in Path(bpy.context.scene.BimTesterProperties.features_dir).glob("*.feature"): for filename in Path(bpy.context.scene.BimTesterProperties.features_dir).glob("*.feature"):
with open(filename, "r") as feature_file: with open(filename, "r") as feature_file:
lines = feature_file.readlines() lines = feature_file.readlines()
@@ -155,10 +159,11 @@ class SelectAudited(bpy.types.Operator):
for word in words: for word in words:
if self.is_a_global_id(word): if self.is_a_global_id(word):
audited_global_ids.append(word) audited_global_ids.append(word)
for object in bpy.context.visible_objects: for obj in bpy.context.visible_objects:
index = object.BIMObjectProperties.attributes.find("GlobalId") if not obj.BIMObjectProperties.ifc_definition_id:
if index != -1 and object.BIMObjectProperties.attributes[index].string_value in audited_global_ids: continue
object.select_set(True) if self.file.by_id(obj.BIMObjectProperties.ifc_definition_id).GlobalId in audited_global_ids:
obj.select_set(True)
return {"FINISHED"} return {"FINISHED"}
def is_a_global_id(self, word): def is_a_global_id(self, word):
@@ -90,9 +90,10 @@ class EyedropIfcCsv(bpy.types.Operator):
def execute(self, context): def execute(self, context):
global_ids = [] global_ids = []
self.file = IfcStore.get_file()
for obj in context.selected_objects: for obj in context.selected_objects:
if hasattr(obj, "BIMObjectProperties") and obj.BIMObjectProperties.attributes.get("GlobalId"): if hasattr(obj, "BIMObjectProperties") and obj.BIMObjectProperties.ifc_definition_id:
global_ids.append("#" + obj.BIMObjectProperties.attributes.get("GlobalId").string_value) global_ids.append("#" + self.file.by_id(obj.BIMObjectProperties.ifc_definition_id).GlobalId)
context.scene.CsvProperties.ifc_selector = "|".join(global_ids) context.scene.CsvProperties.ifc_selector = "|".join(global_ids)
return {"FINISHED"} return {"FINISHED"}
@@ -32,7 +32,6 @@ class VisualiseDiff(bpy.types.Operator):
for obj in bpy.context.visible_objects: for obj in bpy.context.visible_objects:
obj.color = (1.0, 1.0, 1.0, 0.2) obj.color = (1.0, 1.0, 1.0, 0.2)
global_id = ifc_file.by_id(obj.BIMObjectProperties.ifc_definition_id).GlobalId global_id = ifc_file.by_id(obj.BIMObjectProperties.ifc_definition_id).GlobalId
#global_id = obj.BIMObjectProperties.attributes.get("GlobalId")
if not global_id: if not global_id:
continue continue
if global_id.string_value in diff["deleted"]: if global_id.string_value in diff["deleted"]:
@@ -1,5 +1,5 @@
import bpy import bpy
from . import ui, operator from . import ui, prop, operator
classes = ( classes = (
operator.EnableReassignClass, operator.EnableReassignClass,
@@ -7,13 +7,14 @@ classes = (
operator.ReassignClass, operator.ReassignClass,
operator.AssignClass, operator.AssignClass,
operator.UnassignClass, operator.UnassignClass,
prop.BIMRootProperties,
ui.BIM_PT_class, ui.BIM_PT_class,
) )
def register(): def register():
pass bpy.types.Scene.BIMRootProperties = bpy.props.PointerProperty(type=prop.BIMRootProperties)
def unregister(): def unregister():
pass del bpy.types.Scene.BIMRootProperties
@@ -14,6 +14,7 @@ class EnableReassignClass(bpy.types.Operator):
def execute(self, context): def execute(self, context):
obj = bpy.context.active_object obj = bpy.context.active_object
self.file = IfcStore.get_file()
ifc_class = obj.name.split("/")[0] ifc_class = obj.name.split("/")[0]
bpy.context.active_object.BIMObjectProperties.is_reassigning_class = True bpy.context.active_object.BIMObjectProperties.is_reassigning_class = True
ifc_products = [ ifc_products = [
@@ -28,11 +29,11 @@ class EnableReassignClass(bpy.types.Operator):
] ]
for ifc_product in ifc_products: for ifc_product in ifc_products:
if ifcopenshell.util.schema.is_a(IfcStore.get_schema().declaration_by_name(ifc_class), ifc_product): if ifcopenshell.util.schema.is_a(IfcStore.get_schema().declaration_by_name(ifc_class), ifc_product):
bpy.context.scene.BIMProperties.ifc_product = ifc_product bpy.context.scene.BIMRootProperties.ifc_product = ifc_product
bpy.context.scene.BIMProperties.ifc_class = obj.name.split("/")[0] element = self.file.by_id(obj.BIMObjectProperties.ifc_definition_id)
predefined_type = obj.BIMObjectProperties.attributes.get("PredefinedType") bpy.context.scene.BIMRootProperties.ifc_class = element.is_a()
if predefined_type: if hasattr(element, "PredefinedType") and element.PredefinedType:
bpy.context.scene.BIMProperties.ifc_predefined_type = predefined_type.string_value bpy.context.scene.BIMRootProperties.ifc_predefined_type = element.PredefinedType
return {"FINISHED"} return {"FINISHED"}
@@ -52,14 +53,14 @@ class ReassignClass(bpy.types.Operator):
def execute(self, context): def execute(self, context):
obj = bpy.context.active_object obj = bpy.context.active_object
self.file = IfcStore.get_file() self.file = IfcStore.get_file()
predefined_type = bpy.context.scene.BIMProperties.ifc_predefined_type predefined_type = bpy.context.scene.BIMRootProperties.ifc_predefined_type
if predefined_type == "USERDEFINED": if predefined_type == "USERDEFINED":
predefined_type = bpy.context.scene.BIMProperties.ifc_userdefined_type predefined_type = bpy.context.scene.BIMRootProperties.ifc_userdefined_type
product = reassign_class.Usecase( product = reassign_class.Usecase(
self.file, self.file,
{ {
"product": self.file.by_id(obj.BIMObjectProperties.ifc_definition_id), "product": self.file.by_id(obj.BIMObjectProperties.ifc_definition_id),
"ifc_class": bpy.context.scene.BIMProperties.ifc_class, "ifc_class": bpy.context.scene.BIMRootProperties.ifc_class,
"predefined_type": predefined_type, "predefined_type": predefined_type,
}, },
).execute() ).execute()
@@ -0,0 +1,94 @@
import bpy
from blenderbim.bim.ifc import IfcStore
from bpy.types import PropertyGroup
from bpy.props import (
PointerProperty,
StringProperty,
EnumProperty,
BoolProperty,
IntProperty,
FloatProperty,
FloatVectorProperty,
CollectionProperty,
)
products_enum = []
classes_enum = []
types_enum = []
def getIfcPredefinedTypes(self, context):
global types_enum
file = IfcStore.get_file()
if len(types_enum) < 1 and file:
declaration = IfcStore.get_schema().declaration_by_name(self.ifc_class)
for attribute in declaration.attributes():
if attribute.name() == "PredefinedType":
types_enum.extend(
[(e, e, "") for e in attribute.type_of_attribute().declared_type().enumeration_items()]
)
break
return types_enum
def refreshClasses(self, context):
global classes_enum
classes_enum.clear()
enum = getIfcClasses(self, context)
context.scene.BIMRootProperties.ifc_class = enum[0][0]
def refreshPredefinedTypes(self, context):
global types_enum
types_enum.clear()
enum = getIfcPredefinedTypes(self, context)
context.scene.BIMRootProperties.ifc_predefined_type = enum[0][0]
def getIfcProducts(self, context):
global products_enum
file = IfcStore.get_file()
if len(products_enum) < 1:
products_enum.extend(
[
(e, e, "")
for e in [
"IfcElement",
"IfcElementType",
"IfcSpatialElement",
"IfcGroup",
"IfcStructuralItem",
"IfcContext",
"IfcAnnotation",
]
]
)
if file.schema == "IFC2X3":
products_enum[2] = ("IfcSpatialStructureElement", "IfcSpatialStructureElement", "")
return products_enum
def getIfcClasses(self, context):
global classes_enum
file = IfcStore.get_file()
if len(classes_enum) < 1 and file:
declaration = IfcStore.get_schema().declaration_by_name(self.ifc_product)
def get_classes(declaration):
results = []
if not declaration.is_abstract():
results.append(declaration.name())
for subtype in declaration.subtypes():
results.extend(get_classes(subtype))
return results
classes = get_classes(declaration)
classes_enum.extend([(c, c, "") for c in sorted(classes)])
return classes_enum
class BIMRootProperties(PropertyGroup):
ifc_product: EnumProperty(items=getIfcProducts, name="Products", update=refreshClasses)
ifc_class: EnumProperty(items=getIfcClasses, name="Class", update=refreshPredefinedTypes)
ifc_predefined_type: EnumProperty(items=getIfcPredefinedTypes, name="Predefined Type", default=None)
ifc_userdefined_type: StringProperty(name="Userdefined Type")
@@ -41,12 +41,12 @@ class BIM_PT_class(Panel):
row = self.layout.row(align=True) row = self.layout.row(align=True)
op = row.operator("bim.assign_class") op = row.operator("bim.assign_class")
op.obj = context.active_object.name op.obj = context.active_object.name
op.ifc_class = bpy.context.scene.BIMProperties.ifc_class op.ifc_class = bpy.context.scene.BIMRootProperties.ifc_class
op.predefined_type = bpy.context.scene.BIMProperties.ifc_predefined_type op.predefined_type = bpy.context.scene.BIMRootProperties.ifc_predefined_type
op.userdefined_type = bpy.context.scene.BIMProperties.ifc_userdefined_type op.userdefined_type = bpy.context.scene.BIMRootProperties.ifc_userdefined_type
def draw_class_dropdowns(self): def draw_class_dropdowns(self):
props = bpy.context.scene.BIMProperties props = bpy.context.scene.BIMRootProperties
row = self.layout.row() row = self.layout.row()
row.prop(props, "ifc_product") row.prop(props, "ifc_product")
row = self.layout.row() row = self.layout.row()
@@ -26,10 +26,7 @@ from bpy.props import (
cwd = os.path.dirname(os.path.realpath(__file__)) cwd = os.path.dirname(os.path.realpath(__file__))
diagram_scales_enum = [] diagram_scales_enum = []
products_enum = []
profiledef_enum = [] profiledef_enum = []
classes_enum = []
types_enum = []
availablematerialpsets_enum = [] availablematerialpsets_enum = []
ifcpatchrecipes_enum = [] ifcpatchrecipes_enum = []
titleblocks_enum = [] titleblocks_enum = []
@@ -117,32 +114,6 @@ def setDefaultProperties(scene):
bpy.ops.bim.save_drawing_style(index="2") bpy.ops.bim.save_drawing_style(index="2")
def getIfcPredefinedTypes(self, context):
global types_enum
file = IfcStore.get_file()
if len(types_enum) < 1 and file:
declaration = IfcStore.get_schema().declaration_by_name(self.ifc_class)
for attribute in declaration.attributes():
if attribute.name() == "PredefinedType":
types_enum.extend([(e, e, "") for e in attribute.type_of_attribute().declared_type().enumeration_items()])
break
return types_enum
def refreshClasses(self, context):
global classes_enum
classes_enum.clear()
enum = getIfcClasses(self, context)
context.scene.BIMProperties.ifc_class = enum[0][0]
def refreshPredefinedTypes(self, context):
global types_enum
types_enum.clear()
enum = getIfcPredefinedTypes(self, context)
context.scene.BIMProperties.ifc_predefined_type = enum[0][0]
def getDiagramScales(self, context): def getDiagramScales(self, context):
global diagram_scales_enum global diagram_scales_enum
if ( if (
@@ -239,46 +210,6 @@ def refreshActiveDrawingIndex(self, context):
bpy.ops.bim.activate_view(drawing_index=context.scene.DocProperties.active_drawing_index) bpy.ops.bim.activate_view(drawing_index=context.scene.DocProperties.active_drawing_index)
def getIfcProducts(self, context):
global products_enum
file = IfcStore.get_file()
if len(products_enum) < 1:
products_enum.extend(
[
(e, e, "")
for e in [
"IfcElement",
"IfcElementType",
"IfcSpatialElement",
"IfcGroup",
"IfcStructuralItem",
"IfcContext",
"IfcAnnotation",
]
]
)
if file.schema == "IFC2X3":
products_enum[2] = ("IfcSpatialStructureElement", "IfcSpatialStructureElement", "")
return products_enum
def getIfcClasses(self, context):
global classes_enum
file = IfcStore.get_file()
if len(classes_enum) < 1 and file:
declaration = IfcStore.get_schema().declaration_by_name(self.ifc_product)
def get_classes(declaration):
results = []
if not declaration.is_abstract():
results.append(declaration.name())
for subtype in declaration.subtypes():
results.extend(get_classes(subtype))
return results
classes = get_classes(declaration)
classes_enum.extend([(c, c, "") for c in sorted(classes)])
return classes_enum
def getAttributeEnumValues(self, context): def getAttributeEnumValues(self, context):
return [(e, e, "") for e in json.loads(self.enum_items)] return [(e, e, "") for e in json.loads(self.enum_items)]
@@ -859,10 +790,6 @@ class BIMProperties(PropertyGroup):
schema_dir: StringProperty(default=os.path.join(cwd, "schema") + os.path.sep, name="Schema Directory") 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") data_dir: StringProperty(default=os.path.join(cwd, "data") + os.path.sep, name="Data Directory")
ifc_file: StringProperty(name="IFC File") ifc_file: StringProperty(name="IFC File")
ifc_product: EnumProperty(items=getIfcProducts, name="Products", update=refreshClasses)
ifc_class: EnumProperty(items=getIfcClasses, name="Class", update=refreshPredefinedTypes)
ifc_predefined_type: EnumProperty(items=getIfcPredefinedTypes, name="Predefined Type", default=None)
ifc_userdefined_type: StringProperty(name="Userdefined Type")
export_schema: EnumProperty(items=[("IFC4", "IFC4", ""), ("IFC2X3", "IFC2X3", "")], name="IFC Schema") export_schema: EnumProperty(items=[("IFC4", "IFC4", ""), ("IFC2X3", "IFC2X3", "")], name="IFC Schema")
export_json_version: EnumProperty(items=[("4", "4", ""), ("5a", "5a", "")], name="IFC JSON Version") export_json_version: EnumProperty(items=[("4", "4", ""), ("5a", "5a", "")], name="IFC JSON Version")
export_json_compact: BoolProperty(name="Export Compact IFCJSON", default=False) export_json_compact: BoolProperty(name="Export Compact IFCJSON", default=False)
@@ -884,7 +811,6 @@ class BIMProperties(PropertyGroup):
import_should_use_cpu_multiprocessing: BoolProperty(name="Import with CPU Multiprocessing", default=True) import_should_use_cpu_multiprocessing: BoolProperty(name="Import with CPU Multiprocessing", default=True)
import_should_import_with_profiling: BoolProperty(name="Import with Profiling", default=True) import_should_import_with_profiling: BoolProperty(name="Import with Profiling", default=True)
import_should_import_aggregates: BoolProperty(name="Import Aggregates", default=True) import_should_import_aggregates: BoolProperty(name="Import Aggregates", default=True)
import_should_merge_aggregates: BoolProperty(name="Import and Merge Aggregates", default=False)
import_should_merge_by_class: BoolProperty(name="Import and Merge by Class", default=False) import_should_merge_by_class: BoolProperty(name="Import and Merge by Class", default=False)
import_should_merge_by_material: BoolProperty(name="Import and Merge by Material", default=False) import_should_merge_by_material: BoolProperty(name="Import and Merge by Material", default=False)
import_should_merge_materials_by_colour: BoolProperty(name="Import and Merge Materials by Colour", default=False) import_should_merge_materials_by_colour: BoolProperty(name="Import and Merge Materials by Colour", default=False)