From 574d9a3036beb9af15fdf6897773e653bcdafcbf Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Wed, 16 Oct 2019 23:17:48 +1100 Subject: [PATCH] Add attributes interface --- .../io_export_ifc/__init__.py | 7 +++ .../io_export_ifc/export_ifc.py | 8 ++- .../io_export_ifc/operator.py | 55 ++++++++++++++++--- src/ifcblenderexport/io_export_ifc/ui.py | 38 ++++++++++++- 4 files changed, 97 insertions(+), 11 deletions(-) diff --git a/src/ifcblenderexport/io_export_ifc/__init__.py b/src/ifcblenderexport/io_export_ifc/__init__.py index 33251a0dc3..b7fba5c53c 100644 --- a/src/ifcblenderexport/io_export_ifc/__init__.py +++ b/src/ifcblenderexport/io_export_ifc/__init__.py @@ -33,7 +33,11 @@ classes = ( operator.AssignSweptSolidExtrusion, operator.AssignPset, operator.RemovePset, + operator.GenerateGlobalId, + operator.AddAttribute, + operator.RemoveAttribute, ui.BIMProperties, + ui.Attribute, ui.ObjectProperties, ui.MaterialProperties, ui.MeshProperties, @@ -41,6 +45,7 @@ classes = ( ui.MVDPanel, ui.MaterialPanel, ui.MeshPanel, + ui.ObjectPanel, ) def menu_func_export(self, context): @@ -58,6 +63,7 @@ def register(): bpy.types.TOPBAR_MT_file_import.append(menu_func_import) bpy.types.Scene.BIMProperties = bpy.props.PointerProperty(type=ui.BIMProperties) bpy.types.Object.ObjectProperties = bpy.props.PointerProperty(type=ui.ObjectProperties) + bpy.types.Collection.ObjectProperties = bpy.props.PointerProperty(type=ui.ObjectProperties) bpy.types.Material.MaterialProperties = bpy.props.PointerProperty(type=ui.MaterialProperties) bpy.types.Mesh.MeshProperties = bpy.props.PointerProperty(type=ui.MeshProperties) @@ -68,6 +74,7 @@ def unregister(): bpy.types.TOPBAR_MT_file_import.remove(menu_func_import) del(bpy.types.Scene.BIMProperties) del(bpy.types.Object.ObjectProperties) + del(bpy.types.Collection.ObjectProperties) del(bpy.types.Material.MaterialProperties) del(bpy.types.Mesh.MeshProperties) diff --git a/src/ifcblenderexport/io_export_ifc/export_ifc.py b/src/ifcblenderexport/io_export_ifc/export_ifc.py index f3389d3b08..f8672b35c4 100644 --- a/src/ifcblenderexport/io_export_ifc/export_ifc.py +++ b/src/ifcblenderexport/io_export_ifc/export_ifc.py @@ -175,9 +175,11 @@ class IfcParser(): def get_object_attributes(self, object): attributes = { 'Name': self.get_ifc_name(object.name) } - if 'IfcGlobalId' not in object: - object['IfcGlobalId'] = ifcopenshell.guid.new() - attributes.update({ key[3:]: object[key] for key in object.keys() if key[0:3] == 'Ifc'}) + if object.ObjectProperties.attributes.find('GlobalId') == -1: + global_id = object.ObjectProperties.attributes.add() + global_id.name = 'GlobalId' + global_id.string_value = ifcopenshell.guid.new() + attributes.update({ a.name: a.string_value for a in object.ObjectProperties.attributes}) return attributes def get_products(self): diff --git a/src/ifcblenderexport/io_export_ifc/operator.py b/src/ifcblenderexport/io_export_ifc/operator.py index 94493b62ce..d00b2f0a7f 100644 --- a/src/ifcblenderexport/io_export_ifc/operator.py +++ b/src/ifcblenderexport/io_export_ifc/operator.py @@ -1,6 +1,7 @@ import bpy import time import logging +from . import ifcopenshell from . import export_ifc from . import import_ifc from bpy_extras.io_utils import ImportHelper @@ -78,14 +79,19 @@ class AssignClass(bpy.types.Operator): object.name = '{}/{}'.format( bpy.context.scene.BIMProperties.ifc_class, object.name) - if existing_class != bpy.context.scene.BIMProperties.ifc_class \ - and 'IfcPredefinedType' in object.keys(): - del(object['IfcPredefinedType']) - object['IfcPredefinedType'] = bpy.context.scene.BIMProperties.ifc_predefined_type + predefined_type_index = object.ObjectProperties.attributes.find('PredefinedType') + if predefined_type_index >= 0: + object.ObjectProperties.attributes.remove(predefined_type_index) + object_type_index = object.ObjectProperties.attributes.find('ObjectType') + if object_type_index >= 0: + object.ObjectProperties.attributes.remove(object_type_index) + predefined_type = object.ObjectProperties.attributes.add() + predefined_type.name = 'PredefinedType' + predefined_type.string_value = bpy.context.scene.BIMProperties.ifc_predefined_type # TODO: make it an enum if bpy.context.scene.BIMProperties.ifc_predefined_type == 'USERDEFINED': - object['IfcObjectType'] = bpy.context.scene.BIMProperties.ifc_userdefined_type - elif 'IfcObjectType' in object.keys(): - del(object['IfcObjectType']) + object_type = object.ObjectProperties.attributes.add() + object_type.name = 'ObjectType' + object_type.string_value = bpy.context.scene.BIMProperties.ifc_userdefined_type return {'FINISHED'} class SelectClass(bpy.types.Operator): @@ -220,6 +226,41 @@ class RemovePset(bpy.types.Operator): del(object[bpy.context.scene.BIMProperties.pset_name]) return {'FINISHED'} +class GenerateGlobalId(bpy.types.Operator): + bl_idname = 'bim.generate_global_id' + bl_label = 'Generate GlobalId' + + def execute(self, context): + global_id = None + for attribute in bpy.context.active_object.ObjectProperties.attributes: + if attribute.name == 'GlobalId': + global_id = attribute + break + if not global_id: + global_id = bpy.context.active_object.ObjectProperties.attributes.add() + global_id.name = 'GlobalId' + global_id.data_type = 'string' + global_id.string_value = ifcopenshell.guid.new() + return {'FINISHED'} + +class AddAttribute(bpy.types.Operator): + bl_idname = 'bim.add_attribute' + bl_label = 'Add Attribute' + + # This is a temporary measure until we get a better UI + def execute(self, context): + bpy.context.active_object.ObjectProperties.attributes.add() + return {'FINISHED'} + +class RemoveAttribute(bpy.types.Operator): + bl_idname = 'bim.remove_attribute' + bl_label = 'Remove Attribute' + attribute_index: bpy.props.IntProperty() + + def execute(self, context): + bpy.context.active_object.ObjectProperties.attributes.remove(self.attribute_index) + return {'FINISHED'} + class AssignSweptSolidProfile(bpy.types.Operator): bl_idname = 'bim.assign_swept_solid_profile' bl_label = 'Assign Profile' diff --git a/src/ifcblenderexport/io_export_ifc/ui.py b/src/ifcblenderexport/io_export_ifc/ui.py index 941c4c2c2c..b37e6c3182 100644 --- a/src/ifcblenderexport/io_export_ifc/ui.py +++ b/src/ifcblenderexport/io_export_ifc/ui.py @@ -47,8 +47,16 @@ class BIMProperties(bpy.types.PropertyGroup): pset_name: bpy.props.EnumProperty(items=getPsetNames, name="Pset Name") pset_file: bpy.props.EnumProperty(items=getPsetFiles, name="Pset File") +class Attribute(bpy.types.PropertyGroup): + name: bpy.props.StringProperty(name="Name") + data_type: bpy.props.StringProperty(name="Data Type") + string_value: bpy.props.StringProperty(name="Value") + bool_value: bpy.props.BoolProperty(name="Value") + int_value: bpy.props.IntProperty(name="Value") + float_value: bpy.props.FloatProperty(name="Value") + class ObjectProperties(bpy.types.PropertyGroup): - global_id: bpy.props.StringProperty(name="GlobalId") + attributes: bpy.props.CollectionProperty(name="Attributes", type=Attribute) class MaterialProperties(bpy.types.PropertyGroup): is_external: bpy.props.BoolProperty(name="Has External Definition") @@ -60,6 +68,34 @@ class MeshProperties(bpy.types.PropertyGroup): is_wireframe: bpy.props.BoolProperty(name="Is Wireframe") is_swept_solid: bpy.props.BoolProperty(name="Is Swept Solid") +class ObjectPanel(bpy.types.Panel): + bl_label = 'IFC Object' + bl_idname = 'BIM_PT_object' + bl_space_type = 'PROPERTIES' + bl_region_type = 'WINDOW' + bl_context = 'object' + + def draw(self, context): + if not bpy.context.active_object: + return + layout = self.layout + layout.label(text="Software Identity:") + row = layout.row() + row.operator('bim.generate_global_id') + + layout.label(text="Attributes:") + row = layout.row() + row.operator('bim.add_attribute') + + for index, attribute in enumerate(bpy.context.active_object.ObjectProperties.attributes): + row = layout.row(align=True) + row.prop(attribute, 'name', text='') + row.prop(attribute, 'string_value', text='') + row.operator('bim.remove_attribute', icon='CANCEL', text='').attribute_index = index + + row = layout.row() + row.prop(bpy.context.active_object.ObjectProperties, 'attributes') + class MeshPanel(bpy.types.Panel): bl_label = 'IFC Representations' bl_idname = 'BIM_PT_mesh'