Add UI for pset overrides without the need to create a CSV.

This commit is contained in:
Dion Moult
2020-01-15 17:17:03 +11:00
parent 71f836d013
commit af278b5724
9 changed files with 109 additions and 37 deletions
@@ -61,6 +61,8 @@ if bpy is not None:
operator.UnassignPset,
operator.AddPset,
operator.RemovePset,
operator.AddOverridePset,
operator.RemoveOverridePset,
operator.AddMaterialPset,
operator.RemoveMaterialPset,
operator.AddDocument,
+22 -10
View File
@@ -7,6 +7,7 @@ import os
from pathlib import Path
from mathutils import Vector, Matrix
from .helper import SIUnitHelper
from . import schema
import ifcopenshell
import addon_utils
@@ -408,6 +409,18 @@ class IfcParser():
self.rel_defines_by_pset.setdefault(
'{}/{}'.format(pset.name, pset.file), []).append(product)
for pset in obj.BIMObjectProperties.override_psets:
pset_key = '{}/{}'.format(pset.name, obj.name)
raw = {p.name: p.string_value for p in pset.properties if p.string_value}
if not raw:
continue
self.psets[pset_key] = {
'ifc': None,
'raw': raw,
'attributes': { 'Name': pset.name }
}
self.rel_defines_by_pset.setdefault(pset_key, []).append(product)
for document in obj.BIMObjectProperties.documents:
self.rel_associates_document_object.setdefault(
document.file, []).append(product)
@@ -943,10 +956,9 @@ class IfcParser():
class IfcExporter():
def __init__(self, ifc_export_settings, ifc_schema, ifc_parser, qto_calculator):
def __init__(self, ifc_export_settings, ifc_parser, qto_calculator):
self.template_file = '{}template.ifc'.format(ifc_export_settings.schema_dir)
self.ifc_export_settings = ifc_export_settings
self.ifc_schema = ifc_schema
self.ifc_parser = ifc_parser
self.qto_calculator = qto_calculator
@@ -1206,7 +1218,7 @@ class IfcExporter():
})
def create_pset_properties(self, pset):
if pset['attributes']['Name'] in self.ifc_schema.psets:
if pset['attributes']['Name'] in schema.ifc.psets:
return self.create_templated_pset_properties(pset)
return self.create_custom_pset_properties(pset)
@@ -1222,7 +1234,7 @@ class IfcExporter():
def create_templated_pset_properties(self, pset):
properties = []
templates = self.ifc_schema.psets[pset['attributes']['Name']]['HasPropertyTemplates']
templates = schema.ifc.psets[pset['attributes']['Name']]['HasPropertyTemplates']
for name, data in templates.items():
if name not in pset['raw']:
continue
@@ -1250,13 +1262,13 @@ class IfcExporter():
return properties
def cast_to_base_type(self, var_type, value):
if var_type not in self.ifc_schema.type_map:
if var_type not in schema.ifc.type_map:
return value
elif self.ifc_schema.type_map[var_type] == 'float':
elif schema.ifc.type_map[var_type] == 'float':
return float(value)
elif self.ifc_schema.type_map[var_type] == 'integer':
elif schema.ifc.type_map[var_type] == 'integer':
return int(value)
elif self.ifc_schema.type_map[var_type] == 'bool':
elif schema.ifc.type_map[var_type] == 'bool':
return True if value.lower() in ['1', 't', 'true', 'yes', 'y', 'uh-huh'] else False
return str(value)
@@ -1551,11 +1563,11 @@ class IfcExporter():
)
def get_product_attribute_type(self, product_class, attribute_name):
element_schema = self.ifc_schema.elements[product_class]
element_schema = schema.ifc.elements[product_class]
for a in element_schema['attributes']:
if a['name'] == attribute_name:
return a['type']
if element_schema['parent'] in self.ifc_schema.elements:
if element_schema['parent'] in schema.ifc.elements:
return self.get_product_attribute_type(element_schema['parent'], attribute_name)
return None
@@ -7,9 +7,7 @@ import time
import mathutils
import multiprocessing
from .helper import SIUnitHelper
from .schema import IfcSchema
ifc_schema = IfcSchema()
from . import schema
class MaterialCreator():
def __init__(self, ifc_import_settings):
@@ -402,8 +400,8 @@ class IfcImporter():
def add_element_attributes(self, element, obj):
attributes = element.get_info()
if element.is_a() in ifc_schema.elements:
applicable_attributes = [a['name'] for a in ifc_schema.elements[element.is_a()]['attributes']]
if element.is_a() in schema.ifc.elements:
applicable_attributes = [a['name'] for a in schema.ifc.elements[element.is_a()]['attributes']]
for key, value in attributes.items():
if key not in applicable_attributes \
or value is None:
+28 -3
View File
@@ -8,10 +8,10 @@ from . import export_ifc
from . import import_ifc
from . import cut_ifc
from . import sheeter
from . import schema
from bpy_extras.io_utils import ImportHelper
from itertools import cycle
from mathutils import Vector
from .schema import IfcSchema
class ExportIFC(bpy.types.Operator):
bl_idname = "export.ifc"
@@ -54,9 +54,8 @@ class ExportIFC(bpy.types.Operator):
]
})
ifc_parser = export_ifc.IfcParser(ifc_export_settings)
ifc_schema = IfcSchema()
qto_calculator = export_ifc.QtoCalculator()
ifc_exporter = export_ifc.IfcExporter(ifc_export_settings, ifc_schema, ifc_parser, qto_calculator)
ifc_exporter = export_ifc.IfcExporter(ifc_export_settings, ifc_parser, qto_calculator)
ifc_exporter.export()
ifc_export_settings.logger.info('Export finished in {:.2f} seconds'.format(time.time() - start))
return {'FINISHED'}
@@ -323,6 +322,32 @@ class RemovePset(bpy.types.Operator):
return {'FINISHED'}
class AddOverridePset(bpy.types.Operator):
bl_idname = 'bim.add_override_pset'
bl_label = 'Add Override Pset'
def execute(self, context):
pset_name = bpy.context.active_object.BIMObjectProperties.override_pset_name
if pset_name not in schema.ifc.psets:
return {'FINISHED'}
pset = bpy.context.active_object.BIMObjectProperties.override_psets.add()
pset.name = pset_name
for prop_name in schema.ifc.psets[pset_name]['HasPropertyTemplates'].keys():
prop = pset.properties.add()
prop.name = prop_name
return {'FINISHED'}
class RemoveOverridePset(bpy.types.Operator):
bl_idname = 'bim.remove_override_pset'
bl_label = 'Remove Override Pset'
pset_index: bpy.props.IntProperty()
def execute(self, context):
bpy.context.active_object.BIMObjectProperties.override_psets.remove(self.pset_index)
return {'FINISHED'}
class AddMaterialPset(bpy.types.Operator):
bl_idname = 'bim.add_material_pset'
bl_label = 'Add Material Pset'
+12 -11
View File
@@ -3,7 +3,7 @@ import os
import csv
from pathlib import Path
from . import export_ifc
from .schema import IfcSchema
from . import schema
import bpy
from bpy.types import PropertyGroup
from bpy.app.handlers import persistent
@@ -18,8 +18,6 @@ from bpy.props import (
cwd = os.path.dirname(os.path.realpath(__file__))
ifc_schema = IfcSchema()
diagram_scales_enum = []
products_enum = []
profiledef_enum = []
@@ -53,7 +51,7 @@ def setDefaultProperties(scene):
def getIfcPredefinedTypes(self, context):
global types_enum
if len(types_enum) < 1:
for name, data in ifc_schema.elements.items():
for name, data in schema.ifc.elements.items():
if name != self.ifc_class.strip():
continue
for attribute in data['attributes']:
@@ -106,14 +104,14 @@ def getIfcProducts(self, context):
def getIfcClasses(self, context):
global classes_enum
if len(classes_enum) < 1:
classes_enum.extend([(e, e, '') for e in getattr(ifc_schema, self.ifc_product)])
classes_enum.extend([(e, e, '') for e in getattr(schema.ifc, self.ifc_product)])
return classes_enum
def getProfileDef(self, context):
global profiledef_enum
if len(profiledef_enum) < 1:
profiledef_enum.extend([(e, e, '') for e in getattr(ifc_schema, 'IfcParameterizedProfileDef')])
profiledef_enum.extend([(e, e, '') for e in getattr(schema.ifc, 'IfcParameterizedProfileDef')])
return profiledef_enum
@@ -206,9 +204,9 @@ def getApplicableAttributes(self, context):
global attributes_enum
attributes_enum.clear()
if '/' in context.active_object.name \
and context.active_object.name.split('/')[0] in ifc_schema.elements:
and context.active_object.name.split('/')[0] in schema.ifc.elements:
attributes_enum.extend([(a['name'], a['name'], '') for a in
ifc_schema.elements[context.active_object.name.split('/')[0]]['attributes']
schema.ifc.elements[context.active_object.name.split('/')[0]]['attributes']
if self.attributes.find(a['name']) == -1])
return attributes_enum
@@ -217,12 +215,12 @@ def getApplicableMaterialAttributes(self, context):
global materialattributes_enum
materialattributes_enum.clear()
if '/' in context.active_object.name \
and context.active_object.name.split('/')[0] in ifc_schema.elements:
and context.active_object.name.split('/')[0] in schema.ifc.elements:
material_type = context.active_object.BIMObjectProperties.material_type
if material_type[-3:] == 'Set':
material_type = material_type[0:-3]
materialattributes_enum.extend([(a['name'], a['name'], '') for a in
ifc_schema.IfcMaterialDefinition[material_type]['attributes']
schema.ifc.IfcMaterialDefinition[material_type]['attributes']
if self.attributes.find(a['name']) == -1])
return materialattributes_enum
@@ -230,7 +228,7 @@ def getApplicableMaterialAttributes(self, context):
def refreshProfileAttributes(self, context):
while len(context.active_object.active_material.BIMMaterialProperties.profile_attributes) > 0:
context.active_object.active_material.BIMMaterialProperties.profile_attributes.remove(0)
for attribute in ifc_schema.IfcParameterizedProfileDef[self.profile_def]['attributes']:
for attribute in schema.ifc.IfcParameterizedProfileDef[self.profile_def]['attributes']:
profile_attribute = context.active_object.active_material.BIMMaterialProperties.profile_attributes.add()
profile_attribute.name = attribute['name']
@@ -384,6 +382,7 @@ class Attribute(PropertyGroup):
class Pset(PropertyGroup):
name: StringProperty(name="Name")
file: StringProperty(name="File")
properties: CollectionProperty(name="Properties", type=Attribute)
class Document(PropertyGroup):
file: StringProperty(name="File")
@@ -406,6 +405,8 @@ class BIMObjectProperties(PropertyGroup):
applicable_documents: EnumProperty(items=getApplicableDocuments, name="Available Documents")
classifications: CollectionProperty(name="Classifications", type=Classification)
material_type: EnumProperty(items=getMaterialTypes, name="Material Type")
override_psets: CollectionProperty(name="Override Psets", type=Pset)
override_pset_name: StringProperty(name="Override Pset Name")
class BIMMaterialProperties(PropertyGroup):
+15 -8
View File
@@ -1,6 +1,7 @@
import os
import json
import ifcopenshell
from pathlib import Path
cwd = os.path.dirname(os.path.realpath(__file__))
@@ -15,7 +16,10 @@ class IfcSchema():
'IfcParameterizedProfileDef'
]
self.elements = {}
self.property_file = ifcopenshell.open(os.path.join(self.schema_dir, 'IFC4_ADD2.ifc'))
self.property_files = []
property_paths = Path(self.schema_dir).glob('Pset_*.ifc')
for path in property_paths:
self.property_files.append(ifcopenshell.open(path))
self.psets = {}
self.qtos = {}
self.load()
@@ -29,10 +33,13 @@ class IfcSchema():
with open(os.path.join(self.schema_dir, 'ifc_types_IFC4.json')) as f:
self.type_map = json.load(f)
for property in self.property_file.by_type('IfcPropertySetTemplate'):
if property.Name[0:4] == 'Qto_':
# self.qtos.append({ })
pass
else:
self.psets[property.Name] = {
'HasPropertyTemplates': {p.Name: p for p in property.HasPropertyTemplates}}
for property_file in self.property_files:
for property in property_file.by_type('IfcPropertySetTemplate'):
if property.Name[0:4] == 'Qto_':
# self.qtos.append({ })
pass
else:
self.psets[property.Name] = {
'HasPropertyTemplates': {p.Name: p for p in property.HasPropertyTemplates}}
ifc = IfcSchema()
@@ -0,0 +1,14 @@
ISO-10303-21;
HEADER;
FILE_DESCRIPTION((),'2;1');
FILE_NAME('Pset_Custom.ifc','2020-01-01T00:00:00',(),(),'Sample','Sample',$);
FILE_SCHEMA(('IFC4'));
ENDSEC;
DATA;
#1= IFCPROPERTYSETTEMPLATE('05N2Dhepb9ouTCSmWBh22D',$,'Custom_Pset','An example custom pset.',.PSET_TYPEDRIVENOVERRIDE.,'IfcObject',(#2,#3));
#2= IFCSIMPLEPROPERTYTEMPLATE('37EpTDq4v96gTZh196BBXQ',$,'NumericProperty','An example numeric property',.P_SINGLEVALUE.,'IfcCountMeasure','',$,$,$,$,.READWRITE.);
#3= IFCSIMPLEPROPERTYTEMPLATE('22H7CzDvz1XfVHKkGWoYUK',$,'StringProperty','An example string property',.P_SINGLEVALUE.,'IfcLabel','',$,$,$,$,.READWRITE.);
ENDSEC;
END-ISO-10303-21;
+13
View File
@@ -54,6 +54,19 @@ class BIM_PT_object(Panel):
row = layout.row()
row.prop(props, 'psets')
row = layout.row(align=True)
row.prop(props, 'override_pset_name', text='')
row.operator('bim.add_override_pset')
for index, pset in enumerate(props.override_psets):
row = layout.row(align=True)
row.prop(pset, 'name', text='')
row.operator('bim.remove_override_pset', icon='X', text='').pset_index = index
for prop in pset.properties:
row = layout.row(align=True)
row.prop(prop, 'name', text='')
row.prop(prop, 'string_value', text='')
layout.label(text="Documents:")
row = layout.row(align=True)
row.prop(props, 'applicable_documents', text='')