mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-10 17:58:20 +00:00
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:
@@ -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,
|
||||
|
||||
Binary file not shown.
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"blender": {
|
||||
"uri": "high-res.blend",
|
||||
"identification": "high-res"
|
||||
}
|
||||
}
|
||||
Binary file not shown.
@@ -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():
|
||||
|
||||
@@ -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'}
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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'}:
|
||||
|
||||
Reference in New Issue
Block a user