diff --git a/src/ifcblenderexport/blenderbim/bim/__init__.py b/src/ifcblenderexport/blenderbim/bim/__init__.py index efb70cbdbf..2009d6f05c 100644 --- a/src/ifcblenderexport/blenderbim/bim/__init__.py +++ b/src/ifcblenderexport/blenderbim/bim/__init__.py @@ -63,6 +63,14 @@ if bpy is not None: operator.AssignConstraint, operator.UnassignConstraint, operator.RemoveObjectConstraint, + operator.AddPerson, + operator.RemovePerson, + operator.AddPersonAddress, + operator.RemovePersonAddress, + operator.AddOrganisation, + operator.RemoveOrganisation, + operator.AddOrganisationAddress, + operator.RemoveOrganisationAddress, operator.AddDocumentInformation, operator.RemoveDocumentInformation, operator.AssignDocumentInformation, @@ -150,6 +158,9 @@ if bpy is not None: operator.ConvertLocalToGlobal, prop.StrProperty, prop.Variable, + prop.Address, + prop.Person, + prop.Organisation, prop.Classification, prop.ClassificationReference, prop.ClassificationView, @@ -196,6 +207,8 @@ if bpy is not None: ui.BIM_PT_ifcclash, ui.BIM_PT_bcf, ui.BIM_PT_owner, + ui.BIM_PT_people, + ui.BIM_PT_organisations, ui.BIM_PT_context, ui.BIM_PT_qa, ui.BIM_PT_library, @@ -211,6 +224,7 @@ if bpy is not None: ui.BIM_PT_constraint_relations, ui.BIM_PT_camera, ui.BIM_PT_text, + ui.BIM_UL_generic, ui.BIM_UL_clash_sets, ui.BIM_UL_constraints, ui.BIM_UL_document_information, diff --git a/src/ifcblenderexport/blenderbim/bim/operator.py b/src/ifcblenderexport/blenderbim/bim/operator.py index 24f42720f0..aca6e0bf76 100644 --- a/src/ifcblenderexport/blenderbim/bim/operator.py +++ b/src/ifcblenderexport/blenderbim/bim/operator.py @@ -877,6 +877,86 @@ class RemoveObjectConstraint(bpy.types.Operator): return {'FINISHED'} +class AddPerson(bpy.types.Operator): + bl_idname = 'bim.add_person' + bl_label = 'Add Person' + + def execute(self, context): + new = bpy.context.scene.BIMProperties.people.add() + new.name = 'New Person' + return {'FINISHED'} + + +class RemovePerson(bpy.types.Operator): + bl_idname = 'bim.remove_person' + bl_label = 'Remove Person' + index: bpy.props.IntProperty() + + def execute(self, context): + bpy.context.scene.BIMProperties.people.remove(self.index) + return {'FINISHED'} + + +class AddPersonAddress(bpy.types.Operator): + bl_idname = 'bim.add_person_address' + bl_label = 'Add Person Address' + + def execute(self, context): + new = bpy.context.scene.BIMProperties.people[bpy.context.scene.BIMProperties.active_person_index].addresses.add() + new.name = 'IfcPostalAddress' + return {'FINISHED'} + + +class RemovePersonAddress(bpy.types.Operator): + bl_idname = 'bim.remove_person_address' + bl_label = 'Remove Person Address' + index: bpy.props.IntProperty() + + def execute(self, context): + bpy.context.scene.BIMProperties.people[bpy.context.scene.BIMProperties.active_person_index].addresses.remove(self.index) + return {'FINISHED'} + + +class AddOrganisation(bpy.types.Operator): + bl_idname = 'bim.add_organisation' + bl_label = 'Add Organisation' + + def execute(self, context): + new = bpy.context.scene.BIMProperties.organisations.add() + new.name = 'New Organisation' + return {'FINISHED'} + + +class RemoveOrganisation(bpy.types.Operator): + bl_idname = 'bim.remove_organisation' + bl_label = 'Remove Organisation' + index: bpy.props.IntProperty() + + def execute(self, context): + bpy.context.scene.BIMProperties.organisations.remove(self.index) + return {'FINISHED'} + + +class AddOrganisationAddress(bpy.types.Operator): + bl_idname = 'bim.add_organisation_address' + bl_label = 'Add Organisation Address' + + def execute(self, context): + new = bpy.context.scene.BIMProperties.organisations[bpy.context.scene.BIMProperties.active_organisation_index].addresses.add() + new.name = 'IfcPostalAddress' + return {'FINISHED'} + + +class RemoveOrganisationAddress(bpy.types.Operator): + bl_idname = 'bim.remove_organisation_address' + bl_label = 'Remove Organisation Address' + index: bpy.props.IntProperty() + + def execute(self, context): + bpy.context.scene.BIMProperties.organisations[bpy.context.scene.BIMProperties.active_organisation_index].addresses.remove(self.index) + return {'FINISHED'} + + class AddDocumentInformation(bpy.types.Operator): bl_idname = 'bim.add_document_information' bl_label = 'Add Document Information' diff --git a/src/ifcblenderexport/blenderbim/bim/prop.py b/src/ifcblenderexport/blenderbim/bim/prop.py index 3d01a0b806..ac1936212c 100644 --- a/src/ifcblenderexport/blenderbim/bim/prop.py +++ b/src/ifcblenderexport/blenderbim/bim/prop.py @@ -828,6 +828,48 @@ class PropertyTemplate(PropertyGroup): ], name='Primary Measure Type') +class Address(PropertyGroup): + name: StringProperty(name="Name") # Stores IfcPostalAddress or IfcTelecomAddress + purpose: StringProperty(name="Purpose") + description: StringProperty(name="Description") + user_defined_purpose: StringProperty(name="Custom Purpose") + + internal_location: StringProperty(name="Internal Location") + address_lines: StringProperty(name="Address") + postal_box: StringProperty(name="PO Box") + town: StringProperty(name="Town") + region: StringProperty(name="Region") + postal_code: StringProperty(name="Postal Code") + country: StringProperty(name="Country") + + telephone_numbers: StringProperty(name="Telephone Numbers") + fascimile_numbers: StringProperty(name="Fascimile Numbers") + pager_number: StringProperty(name="Pager Number") + electronic_mail_addresses: StringProperty(name="Emails") + www_home_page_url: StringProperty(name="Websites") + messaging_ids: StringProperty(name="IMs") + + +class Organisation(PropertyGroup): + name: StringProperty(name="Name") + description: StringProperty(name="Description") + roles: StringProperty(name="Roles") + addresses: CollectionProperty(name="Addresses", type=Address) + active_address_index: bpy.props.IntProperty() + + +class Person(PropertyGroup): + name: StringProperty(name="Identification") + family_name: StringProperty(name="Family Name") + given_name: StringProperty(name="Given Name") + middle_names: StringProperty(name="Middle Names") + prefix_titles: StringProperty(name="Prefixes") + suffix_titles: StringProperty(name="Suffixes") + roles: StringProperty(name="Roles") + addresses: CollectionProperty(name="Addresses", type=Address) + active_address_index: bpy.props.IntProperty() + + class Classification(PropertyGroup): name: StringProperty(name="Name") source: StringProperty(name="Source") @@ -938,6 +980,10 @@ class BIMProperties(PropertyGroup): qa_reject_element_reason: StringProperty(name="Element Rejection Reason") person: EnumProperty(items=getPersons, name="Person") organisation: EnumProperty(items=getOrganisations, name="Organisation") + people: CollectionProperty(name="People", type=Person) + organisations: CollectionProperty(name="Organisations", type=Organisation) + active_person_index: IntProperty(name='Active Person Index') + active_organisation_index: IntProperty(name='Active Organisation Index') has_georeferencing: BoolProperty(name="Has Georeferencing", default=False) has_library: BoolProperty(name="Has Project Library", default=False) search_regex: BoolProperty(name="Search With Regex", default=False) diff --git a/src/ifcblenderexport/blenderbim/bim/ui.py b/src/ifcblenderexport/blenderbim/bim/ui.py index 24315f7d9d..435cf83c62 100644 --- a/src/ifcblenderexport/blenderbim/bim/ui.py +++ b/src/ifcblenderexport/blenderbim/bim/ui.py @@ -840,6 +840,7 @@ class BIM_PT_text(Panel): class BIM_PT_owner(Panel): bl_label = "IFC Owner History" bl_idname = "BIM_PT_owner" + bl_options = {'DEFAULT_CLOSED'} bl_space_type = 'PROPERTIES' bl_region_type = 'WINDOW' bl_context = "scene" @@ -858,6 +859,137 @@ class BIM_PT_owner(Panel): row.prop(props, 'organisation') +class BIM_PT_people(Panel): + bl_label = "IFC People" + bl_idname = "BIM_PT_people" + bl_options = {'DEFAULT_CLOSED'} + bl_space_type = 'PROPERTIES' + bl_region_type = 'WINDOW' + bl_context = "scene" + + def draw(self, context): + layout = self.layout + layout.use_property_split = True + + props = context.scene.BIMProperties + + row = layout.row() + row.operator('bim.add_person') + + if props.people: + layout.template_list('BIM_UL_topics', '', + props, 'people', props, 'active_person_index') + + if props.active_person_index < len(props.people): + person = props.people[props.active_person_index] + row = layout.row() + row.prop(person, 'name') + row.operator('bim.remove_person', icon='X', text='').index = props.active_person_index + row = layout.row() + row.prop(person, 'family_name') + row = layout.row() + row.prop(person, 'given_name') + row = layout.row() + row.prop(person, 'middle_names') + row = layout.row() + row.prop(person, 'prefix_titles') + row = layout.row() + row.prop(person, 'suffix_titles') + row = layout.row() + row.prop(person, 'roles') + + layout.label(text="Addresses:") + + draw_addresses_ui(layout, person, 'person') + + +class BIM_PT_organisations(Panel): + bl_label = "IFC Organisations" + bl_idname = "BIM_PT_organisations" + bl_options = {'DEFAULT_CLOSED'} + bl_space_type = 'PROPERTIES' + bl_region_type = 'WINDOW' + bl_context = "scene" + + def draw(self, context): + layout = self.layout + layout.use_property_split = True + + props = context.scene.BIMProperties + + row = layout.row() + row.operator('bim.add_organisation') + + if props.organisations: + layout.template_list('BIM_UL_topics', '', + props, 'organisations', props, 'active_organisation_index') + + if props.active_organisation_index < len(props.organisations): + organisation = props.organisations[props.active_organisation_index] + row = layout.row() + row.prop(organisation, 'name') + row.operator('bim.remove_organisation', icon='X', text='').index = props.active_organisation_index + row = layout.row() + row.prop(organisation, 'description') + row = layout.row() + row.prop(organisation, 'roles') + + layout.label(text="Addresses:") + + draw_addresses_ui(layout, organisation, 'organisation') + + +def draw_addresses_ui(layout, parent, parent_type): + row = layout.row() + row.operator(f'bim.add_{parent_type}_address') + + if parent.addresses: + layout.template_list('BIM_UL_topics', '', + parent, 'addresses', parent, 'active_address_index') + + if parent.active_address_index < len(parent.addresses): + address = parent.addresses[parent.active_address_index] + row = layout.row() + row.prop(address, 'name') + row.operator(f'bim.remove_{parent_type}_address', icon='X', text='').index = parent.active_address_index + row = layout.row() + row.prop(address, 'purpose') + if address.purpose == 'USERDEFINED': + row = layout.row() + row.prop(address, 'user_defined_purpose') + row = layout.row() + row.prop(address, 'description') + + if 'IfcPostalAddress' in address.name: + row = layout.row() + row.prop(address, 'internal_location') + row = layout.row() + row.prop(address, 'address_lines') + row = layout.row() + row.prop(address, 'postal_box') + row = layout.row() + row.prop(address, 'town') + row = layout.row() + row.prop(address, 'region') + row = layout.row() + row.prop(address, 'postal_code') + row = layout.row() + row.prop(address, 'country') + elif 'IfcTelecomAddress' in address.name: + row = layout.row() + row.prop(address, 'telephone_numbers') + row = layout.row() + row.prop(address, 'fascimile_numbers') + row = layout.row() + row.prop(address, 'pager_number') + row = layout.row() + row.prop(address, 'electronic_mail_addresses') + row = layout.row() + row.prop(address, 'www_home_page_url') + row = layout.row() + row.prop(address, 'messaging_ids') + + class BIM_PT_context(Panel): bl_label = "IFC Geometric Representation Contexts" bl_idname = "BIM_PT_context" @@ -1353,6 +1485,15 @@ class BIM_PT_mvd(Panel): row.prop(bim_properties, 'import_should_treat_styled_item_as_material') +class BIM_UL_generic(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_topics(bpy.types.UIList): def draw_item(self, context, layout, data, item, icon, active_data, active_propname): ob = data