New document reference UI, where all docs are imported regardless of object association, and you can edit almost all metadata

This commit is contained in:
Dion Moult
2020-05-01 17:24:59 +10:00
parent 6e0fb6145e
commit 784a394298
9 changed files with 194 additions and 116 deletions
@@ -55,8 +55,11 @@ if bpy is not None:
operator.RemoveMaterialPset,
operator.AddDocumentInformation,
operator.RemoveDocumentInformation,
operator.AddDocument,
operator.RemoveDocument,
operator.AddDocumentReference,
operator.RemoveDocumentReference,
operator.AssignDocumentReference,
operator.UnassignDocumentReference,
operator.RemoveObjectDocumentReference,
operator.GenerateGlobalId,
operator.AddAttribute,
operator.RemoveAttribute,
@@ -119,6 +122,7 @@ if bpy is not None:
prop.PropertySetTemplate,
prop.PropertyTemplate,
prop.DocumentInformation,
prop.DocumentReference,
prop.BcfTopic,
prop.BcfTopicLabel,
prop.BcfTopicFile,
@@ -135,7 +139,6 @@ if bpy is not None:
prop.Attribute,
prop.BoundaryCondition,
prop.PsetQto,
prop.Document,
prop.GlobalId,
prop.BIMObjectProperties,
prop.BIMMaterialProperties,
@@ -165,6 +168,7 @@ if bpy is not None:
ui.BIM_PT_documents,
ui.BIM_PT_camera,
ui.BIM_UL_document_information,
ui.BIM_UL_document_references,
ui.BIM_UL_topics,
ui.BIM_UL_classifications,
ui.BIM_ADDON_preferences,
@@ -1,6 +0,0 @@
{
"blender": {
"uri": "high-res.blend",
"identification": "high-res"
}
}
@@ -88,7 +88,7 @@ class IfcParser():
self.people = []
self.organisations = []
self.psets = {}
self.documents = {}
self.document_references = {}
self.classifications = []
self.classification_references = {}
self.objectives = {}
@@ -138,7 +138,7 @@ class IfcParser():
self.categorise_selected_objects(unique_objects)
self.material_psets = self.get_material_psets()
self.document_information = self.get_document_information()
self.documents = self.get_documents()
self.document_references = self.get_document_references()
self.classifications = self.get_classifications()
self.classification_references = self.get_classification_references()
self.objectives = self.get_objectives()
@@ -453,9 +453,9 @@ class IfcParser():
self.get_product_psets_qtos(product, obj, is_pset=True)
self.get_product_psets_qtos(product, obj, is_qto=True)
for document in obj.BIMObjectProperties.documents:
for reference in obj.BIMObjectProperties.document_references:
self.rel_associates_document_object.setdefault(
document.file, []).append(product)
reference.name, []).append(product)
for classification in obj.BIMObjectProperties.classifications:
self.rel_associates_classification_object.setdefault(
@@ -673,19 +673,25 @@ class IfcParser():
with open(self.data_dir + 'owner/organisation.json') as file:
return [{'raw': o} for o in json.load(file)]
def get_documents(self):
documents = {}
doc_path = self.data_dir + 'doc/'
for filename in Path(doc_path).glob('**/*'):
uri = str(filename.relative_to(doc_path).as_posix())
documents[uri] = {
def get_document_references(self):
results = {}
for reference in bpy.context.scene.BIMProperties.document_references:
data_map = {
'name': 'Identification',
'human_name': 'Name',
'description': 'Description',
'location': 'Location'
}
attributes = {}
for key, value in data_map.items():
if getattr(reference, key):
attributes[value] = getattr(reference, key)
results[reference.name] = {
'ifc': None,
'raw': filename,
'attributes': {
'Location': uri,
'Name': filename.stem
}}
return documents
'raw': reference,
'attributes': attributes
}
return results
def get_document_information(self):
results = {}
@@ -1140,7 +1146,7 @@ class IfcExporter():
self.create_project()
self.create_library_information()
self.create_document_information()
self.create_documents()
self.create_document_references()
self.create_classifications()
self.create_classification_references()
self.create_objectives()
@@ -1339,13 +1345,13 @@ class IfcExporter():
information['ifc'] = self.file.create_entity(
'IfcDocumentInformation', **information['attributes'])
def create_documents(self):
for document in self.ifc_parser.documents.values():
document['ifc'] = self.file.create_entity(
'IfcDocumentReference', **document['attributes'])
def create_document_references(self):
for reference in self.ifc_parser.document_references.values():
reference['ifc'] = self.file.create_entity(
'IfcDocumentReference', **reference['attributes'])
self.file.createIfcRelAssociatesDocument(
ifcopenshell.guid.new(), None, None, None,
[self.ifc_parser.project['ifc']], document['ifc'])
[self.ifc_parser.project['ifc']], reference['ifc'])
def create_classifications(self):
for classification in self.ifc_parser.classifications.values():
@@ -2431,7 +2437,7 @@ class IfcExporter():
self.file.createIfcRelAssociatesDocument(
ifcopenshell.guid.new(), self.owner_history, None, None,
[o['ifc'] for o in related_objects],
self.ifc_parser.documents[relating_document_key]['ifc'])
self.ifc_parser.document_references[relating_document_key]['ifc'])
def relate_to_classifications(self, relationships):
for relating_key, related_objects in relationships.items():
@@ -224,6 +224,7 @@ class IfcImporter():
self.calculate_unit_scale()
self.create_project()
self.create_classifications()
self.create_document_references()
self.create_spatial_hierarchy()
self.purge_diff()
self.create_type_products()
@@ -749,6 +750,19 @@ class IfcImporter():
results.extend(self.file.get_inverse(reference))
return results
def create_document_references(self):
for data in self.file.by_type('IfcDocumentReference'):
reference = bpy.context.scene.BIMProperties.document_references.add()
data_map = {
'location': 'Location',
'name': 'Identification',
'human_name': 'Name',
'description': 'Description'
}
for key, value in data_map.items():
if hasattr(data, value) and getattr(data, value):
setattr(reference, key, getattr(data, value))
def create_spatial_hierarchy(self):
if self.project['ifc'].IsDecomposedBy:
for rel_aggregate in self.project['ifc'].IsDecomposedBy:
@@ -857,18 +871,8 @@ class IfcImporter():
def add_element_document_relations(self, element, obj):
for association in element.HasAssociations:
if association.is_a('IfcRelAssociatesDocument'):
data = association.RelatingDocument
document = obj.BIMObjectProperties.documents.add()
data_map = {
'file': 'Location',
'location': 'Location',
'identification': 'Identification',
'name': 'Name',
'description': 'Description'
}
for key, value in data_map.items():
if hasattr(data, value) and getattr(data, value):
setattr(document, key, getattr(data, value))
reference = obj.BIMObjectProperties.document_references.add()
reference.name = association.RelatingDocument.Identification
def place_objects_in_spatial_tree(self):
for global_id, obj in self.added_data.items():
+78 -29
View File
@@ -792,22 +792,90 @@ class RemoveMaterialPset(bpy.types.Operator):
return {'FINISHED'}
class AddDocument(bpy.types.Operator):
bl_idname = 'bim.add_document'
bl_label = 'Add Document'
class AddDocumentInformation(bpy.types.Operator):
bl_idname = 'bim.add_document_information'
bl_label = 'Add Document Information'
def execute(self, context):
document = bpy.context.active_object.BIMObjectProperties.documents.add()
document.file = bpy.context.active_object.BIMObjectProperties.applicable_documents
info = bpy.context.scene.BIMProperties.document_information.add()
info.name = 'New Document ID'
return {'FINISHED'}
class RemoveDocument(bpy.types.Operator):
bl_idname = 'bim.remove_document'
bl_label = 'Remove Document'
document_index: bpy.props.IntProperty()
class RemoveDocumentInformation(bpy.types.Operator):
bl_idname = 'bim.remove_document_information'
bl_label = 'Remove Document Information'
index: bpy.props.IntProperty()
def execute(self, context):
bpy.context.active_object.BIMObjectProperties.documents.remove(self.document_index)
bpy.context.scene.BIMProperties.document_information.remove(self.index)
return {'FINISHED'}
class AddDocumentReference(bpy.types.Operator):
bl_idname = 'bim.add_document_reference'
bl_label = 'Add Document Reference'
def execute(self, context):
document = bpy.context.scene.BIMProperties.document_references.add()
document.name = 'New Document Reference ID'
return {'FINISHED'}
class RemoveDocumentReference(bpy.types.Operator):
bl_idname = 'bim.remove_document_reference'
bl_label = 'Remove Document Reference'
index: bpy.props.IntProperty()
def execute(self, context):
bpy.context.scene.BIMProperties.document_references.remove(self.index)
return {'FINISHED'}
class RemoveObjectDocumentReference(bpy.types.Operator):
bl_idname = 'bim.remove_object_document_reference'
bl_label = 'Remove Object Document Reference'
index: bpy.props.IntProperty()
def execute(self, context):
bpy.context.active_object.BIMObjectProperties.document_references.remove(self.index)
return {'FINISHED'}
class AssignDocumentReference(bpy.types.Operator):
bl_idname = 'bim.assign_document_reference'
bl_label = 'Assign Document Reference'
def execute(self, context):
identification = bpy.context.scene.BIMProperties.document_references[bpy.context.scene.BIMProperties.active_document_reference_index].name
for obj in bpy.context.selected_objects:
if obj.BIMObjectProperties.document_references.get(identification):
continue
reference = obj.BIMObjectProperties.document_references.add()
reference.name = identification
return {'FINISHED'}
class UnassignDocumentReference(bpy.types.Operator):
bl_idname = 'bim.unassign_document_reference'
bl_label = 'Unassign Document Reference'
def execute(self, context):
identification = bpy.context.scene.BIMProperties.document_references[bpy.context.scene.BIMProperties.active_document_reference_index].name
for obj in bpy.context.selected_objects:
index = obj.BIMObjectProperties.document_references.find(identification)
if index >= 0:
obj.BIMObjectProperties.document_references.remove(index)
return {'FINISHED'}
class RemoveObjectDocumentReference(bpy.types.Operator):
bl_idname = 'bim.remove_object_document_reference'
bl_label = 'Remove Object Document Reference'
index: bpy.props.IntProperty()
def execute(self, context):
bpy.context.active_object.BIMObjectProperties.document_references.remove(self.index)
return {'FINISHED'}
class GenerateGlobalId(bpy.types.Operator):
@@ -2236,22 +2304,3 @@ class SelectSimilarType(bpy.types.Operator):
if obj.BIMObjectProperties.relating_type == relating_type:
obj.select_set(True)
return {'FINISHED'}
class AddDocumentInformation(bpy.types.Operator):
bl_idname = 'bim.add_document_information'
bl_label = 'Add Document Information'
def execute(self, context):
info = bpy.context.scene.BIMProperties.document_information.add()
info.name = 'New Document ID'
return {'FINISHED'}
class RemoveDocumentInformation(bpy.types.Operator):
bl_idname = 'bim.remove_document_information'
bl_label = 'Remove Document Information'
index: bpy.props.IntProperty()
def execute(self, context):
bpy.context.scene.BIMProperties.document_information.remove(self.index)
return {'FINISHED'}
+11 -22
View File
@@ -40,7 +40,6 @@ attributes_enum = []
psetnames_enum = []
qtonames_enum = []
materialattributes_enum = []
documents_enum = []
materialtypes_enum = []
contexts_enum = []
subcontexts_enum = []
@@ -309,16 +308,6 @@ def refreshProfileAttributes(self, context):
profile_attribute.name = attribute['name']
def getApplicableDocuments(self, context):
global documents_enum
documents_enum.clear()
doc_path = os.path.join(context.scene.BIMProperties.data_dir, 'doc')
for filename in Path(doc_path).glob('**/*'):
uri = str(filename.relative_to(doc_path).as_posix())
documents_enum.append((uri, uri, ''))
return documents_enum
def getMaterialTypes(self, context):
global materialtypes_enum
materialtypes_enum.clear()
@@ -433,6 +422,13 @@ class DocumentInformation(PropertyGroup):
], name='Status')
class DocumentReference(PropertyGroup):
location: StringProperty(name="Location")
name: StringProperty(name="Identification")
human_name: StringProperty(name="Name")
description: StringProperty(name="Description")
class BcfTopic(PropertyGroup):
name: StringProperty(name='Name')
@@ -892,6 +888,8 @@ class BIMProperties(PropertyGroup):
csv_attributes: CollectionProperty(name='CSV Attributes', type=StrProperty)
document_information: CollectionProperty(name='Document Information', type=DocumentInformation)
active_document_information_index: IntProperty(name='Active Document Information Index')
document_references: CollectionProperty(name='Document References', type=DocumentReference)
active_document_reference_index: IntProperty(name='Active Document Reference Index')
class BCFProperties(PropertyGroup):
@@ -959,18 +957,9 @@ class Attribute(PropertyGroup):
class PsetQto(PropertyGroup):
name: StringProperty(name="Name")
file: StringProperty(name="File")
properties: CollectionProperty(name="Properties", type=Attribute)
class Document(PropertyGroup):
file: StringProperty(name="File")
location: StringProperty(name="Location")
identification: StringProperty(name="Identification")
name: StringProperty(name="Name")
description: StringProperty(name="Description")
class GlobalId(PropertyGroup):
name: StringProperty(name="Name")
@@ -988,8 +977,8 @@ class BIMObjectProperties(PropertyGroup):
psets: CollectionProperty(name="Psets", type=PsetQto)
qtos: CollectionProperty(name="Qtos", type=PsetQto)
applicable_attributes: EnumProperty(items=getApplicableAttributes, name="Attribute Names")
documents: CollectionProperty(name="Documents", type=Document)
applicable_documents: EnumProperty(items=getApplicableDocuments, name="Available Documents")
document_references: CollectionProperty(name="Document References", type=DocumentReference)
active_document_reference_index: IntProperty(name='Active Document Reference Index')
classifications: CollectionProperty(name="Classifications", type=ClassificationReference)
material_type: EnumProperty(items=getMaterialTypes, name="Material Type")
pset_name: EnumProperty(items=getPsetNames, name='Pset Name')
+53 -21
View File
@@ -102,7 +102,7 @@ class BIM_PT_object(Panel):
class BIM_PT_document_information(Panel):
bl_label = 'Document Information'
bl_label = 'Documents'
bl_idname = 'BIM_PT_document_information'
bl_options = {'DEFAULT_CLOSED'}
bl_space_type = 'PROPERTIES'
@@ -117,9 +117,7 @@ class BIM_PT_document_information(Panel):
row = layout.row()
row.operator('bim.add_document_information')
if not props.document_information:
layout.label(text="No document information found")
else:
if props.document_information:
layout.template_list('BIM_UL_document_information', '', props, 'document_information', props, 'active_document_information_index')
if props.active_document_information_index < len(props.document_information):
@@ -156,6 +154,28 @@ class BIM_PT_document_information(Panel):
row = layout.row()
row.prop(information, 'status')
row = layout.row()
row.operator('bim.add_document_reference')
if props.document_references:
layout.template_list('BIM_UL_document_references', '', props, 'document_references', props, 'active_document_reference_index')
if props.active_document_reference_index < len(props.document_references):
reference = props.document_references[props.active_document_reference_index]
row = layout.row(align=True)
row.prop(reference, 'name')
row.operator('bim.remove_document_reference', icon='X', text='').index = props.active_document_reference_index
row = layout.row()
row.prop(reference, 'human_name')
row = layout.row()
row.prop(reference, 'location')
row = layout.row()
row.prop(reference, 'description')
row = layout.row(align=True)
row.operator('bim.assign_document_reference', text='Assign Reference')
row.operator('bim.unassign_document_reference', text='Unassign Reference')
class BIM_PT_documents(Panel):
bl_label = 'Documents'
@@ -167,30 +187,33 @@ class BIM_PT_documents(Panel):
def draw(self, context):
layout = self.layout
layout.use_property_split = True
props = context.active_object.BIMObjectProperties
if not props.documents:
if not props.document_references:
layout.label(text="No documents found")
row = layout.row(align=True)
row.prop(props, 'applicable_documents', text='')
row.operator('bim.add_document')
row = layout.row()
row.operator('bim.fetch_object_passport')
for index, document in enumerate(props.documents):
row = layout.row(align=True)
row.prop(document, 'identification')
row.operator('bim.remove_document', icon='X', text='').document_index = index
row = layout.row(align=True)
row.prop(document, 'file')
row = layout.row(align=True)
row.prop(document, 'location')
row = layout.row(align=True)
row.prop(document, 'name')
row = layout.row(align=True)
row.prop(document, 'description')
if props.document_references:
layout.template_list('BIM_UL_document_references', '', props, 'document_references', props, 'active_document_reference_index')
if props.active_document_reference_index < len(props.document_references):
reference = props.document_references[props.active_document_reference_index]
row = layout.row(align=True)
row.prop(reference, 'name')
if reference.name in bpy.context.scene.BIMProperties.document_references:
reference = bpy.context.scene.BIMProperties.document_references[reference.name]
row.operator('bim.remove_object_document_reference', icon='X', text='').index = props.active_document_reference_index
row = layout.row()
row.prop(reference, 'human_name')
row = layout.row()
row.prop(reference, 'location')
row = layout.row()
row.prop(reference, 'description')
else:
layout.label(text="Reference is invalid")
class BIM_PT_classification_references(Panel):
@@ -1081,6 +1104,15 @@ class BIM_UL_document_information(bpy.types.UIList):
layout.label(text="", translate=False)
class BIM_UL_document_references(bpy.types.UIList):
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
ob = data
if item:
layout.prop(item, 'name', text='', emboss=False)
else:
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'}: