From 6107c39c1cb860bb43ebb0fb28808145dd716382 Mon Sep 17 00:00:00 2001 From: bosonprojets Date: Sat, 24 Apr 2021 23:34:38 +0000 Subject: [PATCH] Update to IfcResources panel and authoring subtypes of IfcConstructionResource with ifcopenshell.api --- .../bim/module/resource/__init__.py | 2 +- .../bim/module/resource/operator.py | 18 +++++-------- .../blenderbim/bim/module/resource/prop.py | 16 ++++++----- .../blenderbim/bim/module/resource/ui.py | 26 ++++++++++-------- .../api/resource/add_crew_resource.py | 14 +++++++--- .../api/resource/add_equipment_resource.py | 27 +++++++++++++++++++ .../api/resource/add_labor_resource.py | 27 +++++++++++++++++++ .../api/resource/add_material_resource.py | 27 +++++++++++++++++++ .../api/resource/add_product_resource.py | 27 +++++++++++++++++++ .../api/resource/add_subcontract_resource.py | 14 +++++++--- .../ifcopenshell/api/resource/data.py | 1 - .../api/resource/edit_resource.py | 10 +++++++ 12 files changed, 170 insertions(+), 39 deletions(-) create mode 100644 src/ifcopenshell-python/ifcopenshell/api/resource/add_equipment_resource.py create mode 100644 src/ifcopenshell-python/ifcopenshell/api/resource/add_labor_resource.py create mode 100644 src/ifcopenshell-python/ifcopenshell/api/resource/add_material_resource.py create mode 100644 src/ifcopenshell-python/ifcopenshell/api/resource/add_product_resource.py create mode 100644 src/ifcopenshell-python/ifcopenshell/api/resource/edit_resource.py diff --git a/src/blenderbim/blenderbim/bim/module/resource/__init__.py b/src/blenderbim/blenderbim/bim/module/resource/__init__.py index 4ab2948d2e..1ca53e99e9 100644 --- a/src/blenderbim/blenderbim/bim/module/resource/__init__.py +++ b/src/blenderbim/blenderbim/bim/module/resource/__init__.py @@ -16,7 +16,7 @@ classes = ( operator.RemoveResource, operator.EnableEditingNestedResource, operator.LoadNestedResourceProperties, - operator.DisableNestedResourceEditingUI, + # operator.DisableNestedResourceEditingUI, prop.Resource, prop.BIMResourceProperties, prop.BIMResourceTreeProperties, diff --git a/src/blenderbim/blenderbim/bim/module/resource/operator.py b/src/blenderbim/blenderbim/bim/module/resource/operator.py index f6fe4604ba..224e0ad609 100644 --- a/src/blenderbim/blenderbim/bim/module/resource/operator.py +++ b/src/blenderbim/blenderbim/bim/module/resource/operator.py @@ -37,9 +37,9 @@ class EnableEditingResource(bpy.types.Operator): def enable_editing_resource(self): data = Data.resources[self.resource] - for attribute in IfcStore.get_schema().declaration_by_name("IfcResource").all_attributes(): + for attribute in IfcStore.get_schema().declaration_by_name("IfcCrewResource").all_attributes(): data_type = ifcopenshell.util.attribute.get_primitive_type(attribute) - if data_type == "entity": + if data_type == "entity" or isinstance(data_type, tuple): continue new = self.props.resource_attributes.add() new.name = attribute.name() @@ -113,6 +113,7 @@ class DisableEditingResource(bpy.types.Operator): context.scene.BIMResourceProperties.active_resource_id = 0 return {"FINISHED"} + class DisableResourceEditingUI(bpy.types.Operator): bl_idname = "bim.disable_resource_editing_ui" bl_label = "Disable Resources Editing UI" @@ -121,13 +122,6 @@ class DisableResourceEditingUI(bpy.types.Operator): context.scene.BIMResourceProperties.is_loaded = False return {"FINISHED"} -class DisableNestedResourceEditingUI(bpy.types.Operator): - bl_idname = "bim.disable_nested_resource_editing_ui" - bl_label = "Disable Task Editing UI" - - def execute(self, context): - context.scene.BIMNestedResourceProperties.is_editing = False - return {"FINISHED"} class AddSubcontractResource(bpy.types.Operator): bl_idname = "bim.add_subcontract_resource" @@ -166,13 +160,13 @@ class AddCrewResource(bpy.types.Operator): class AddEquipementResource(bpy.types.Operator): - bl_idname = "bim.add_equipement_resource" + bl_idname = "bim.add_equipment_resource" bl_label = "Add Equipement Resource" resource: bpy.props.IntProperty() def execute(self, context): ifcopenshell.api.run( - "resource.add_equipement_resource", + "resource.add_equipment_resource", IfcStore.get_file(), resource=IfcStore.get_file().by_id(self.resource) ) @@ -229,7 +223,7 @@ class EditResource(bpy.types.Operator): def execute(self, context): props = context.scene.BIMResourceProperties attributes = {} - for attribute in props.cost_resource_attributes: + for attribute in props.nested_resource_attributes: if attribute.is_null: attributes[attribute.name] = None else: diff --git a/src/blenderbim/blenderbim/bim/module/resource/prop.py b/src/blenderbim/blenderbim/bim/module/resource/prop.py index 644c0f9abc..0ca5406a19 100644 --- a/src/blenderbim/blenderbim/bim/module/resource/prop.py +++ b/src/blenderbim/blenderbim/bim/module/resource/prop.py @@ -16,6 +16,8 @@ from bpy.props import ( ) + + class Resource(PropertyGroup): name: StringProperty(name="Name") ifc_definition_id: IntProperty(name="IFC Definition ID") @@ -23,16 +25,18 @@ class Resource(PropertyGroup): is_expanded: BoolProperty(name="Is Expanded") level_index: IntProperty(name="Level Index") +class BIMResourceTreeProperties(PropertyGroup): + nested_resources: CollectionProperty(name="nested_resources", type=Resource) class BIMResourceProperties(PropertyGroup): resource_attributes: CollectionProperty(name="Resource Attributes", type=Attribute) - is_editing: BoolProperty(name="Is Editing") + is_editing: StringProperty(name="Is Editing") + active_resource_index: IntProperty(name="Active Resource Index") active_resource_id: IntProperty(name="Active Resource Id") - active_resource_index: IntProperty(name="Active Resource Id") + active_nested_resource_index: IntProperty(name="Active nested_resource Index") + active_nested_resource_id: IntProperty(name="Active nested_resource Id") + nested_resource_attributes: CollectionProperty(name="nested_resource Attributes", type=Attribute) + contracted_nested_resources: StringProperty(name="Contracted nested_resource Items", default="[]") is_nested_resource_update_enabled: BoolProperty(name="Is nested_resource Update Enabled", default=True) resources: CollectionProperty(name="Resource", type=Resource) is_loaded: BoolProperty(name="Is Editing") - active_nested_resource_id: IntProperty(name="Active Nested Ressource Id") - active_nested_resource_index: IntProperty(name="Active Nested Resource Index") - nested_resource_attributes: CollectionProperty(name="Nested Resource Attributes", type=Attribute) - contracted_nested_resources: StringProperty(name="Contracted Cost Items", default="[]") diff --git a/src/blenderbim/blenderbim/bim/module/resource/ui.py b/src/blenderbim/blenderbim/bim/module/resource/ui.py index 107fb4319d..60a3f48082 100644 --- a/src/blenderbim/blenderbim/bim/module/resource/ui.py +++ b/src/blenderbim/blenderbim/bim/module/resource/ui.py @@ -21,7 +21,6 @@ class BIM_PT_resources(Panel): if self.props.is_loaded: row.operator("bim.disable_resource_editing_ui", text="CANCEL EDITING RESOURCES", icon="CANCEL") else: - row = self.layout.row() row.operator("bim.load_resources", text="Load Resources", icon="GREASEPENCIL") if not Data.is_loaded: @@ -37,18 +36,23 @@ class BIM_PT_resources(Panel): row = self.layout.row() row.label(text=resource["Name"] or "Unnamed", icon="BOOKMARKS") if self.props.active_resource_id and self.props.active_resource_id == resource_id: - row.operator("bim.add_subcontract_resource", text="", icon="FILE_TICK").resource = resource_id - row.operator("bim.add_crew_resource", text="", icon="COMMUNITY").resource = resource_id - row.operator("bim.add_equipement_resource", text="", icon="TOOL_SETTINGS").resource = resource_id - row.operator("bim.add_labor_resource", text="", icon="ARMATURE_DATA").resource = resource_id - row.operator("bim.add_material_resource", text="", icon="MATERIAL").resource = resource_id - row.operator("bim.add_product_resource", text="", icon="PACKAGE").resource = resource_id - row.operator("bim.edit_resource", text="", icon="CHECKMARK") - row.operator("bim.disable_nested_resource_editing_ui", text="", icon="CANCEL") + if self.props.is_editing == "RESOURCE": + row.operator("bim.edit_resource", text="", icon="CHECKMARK") + elif self.props.is_editing == "NESTED_RESOURCE": + row.operator("bim.add_subcontract_resource", text="", icon="FILE_TICK").resource = resource_id + row.operator("bim.add_crew_resource", text="", icon="COMMUNITY").resource = resource_id + row.operator("bim.add_equipment_resource", text="", icon="TOOL_SETTINGS").resource = resource_id + row.operator("bim.add_labor_resource", text="", icon="ARMATURE_DATA").resource = resource_id + row.operator("bim.add_material_resource", text="", icon="MATERIAL").resource = resource_id + row.operator("bim.add_product_resource", text="", icon="PACKAGE").resource = resource_id + row.operator("bim.edit_resource", text="", icon="CHECKMARK")#.resource = resource_id + #TODO add if statement in operator for editing resource so that it doesnt toggle the wrong panel + row.operator("bim.disable_editing_resource", text="", icon="CANCEL") + elif self.props.active_resource_id: + row.operator("bim.remove_resource", text="", icon="X").resource = resource_id else: row.operator("bim.enable_editing_nested_resources", text="", icon="ACTION").resource = resource_id row.operator("bim.enable_editing_resource", text="", icon="GREASEPENCIL").resource = resource_id - row.operator("bim.remove_resource", text="", icon="X").resource = resource_id if self.props.active_resource_id == resource_id: if self.props.is_editing == "RESOURCE": @@ -57,7 +61,7 @@ class BIM_PT_resources(Panel): self.draw_editable_nested_resource_ui(resource_id) def draw_editable_resource_ui(self): - for attribute in self.props.resources: + for attribute in self.props.resource_attributes: row = self.layout.row(align=True) if attribute.data_type == "string": row.prop(attribute, "string_value", text=attribute.name) diff --git a/src/ifcopenshell-python/ifcopenshell/api/resource/add_crew_resource.py b/src/ifcopenshell-python/ifcopenshell/api/resource/add_crew_resource.py index 1937dfe26a..179d09b650 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/resource/add_crew_resource.py +++ b/src/ifcopenshell-python/ifcopenshell/api/resource/add_crew_resource.py @@ -7,6 +7,7 @@ class Usecase: def __init__(self, file, **settings): self.file = file self.settings = { + "parent_resource": None, "name": "Unnamed", "predefined_type": "NOTDEFINED", } @@ -23,8 +24,13 @@ class Usecase: ) # TODO: this is an ambiguity by buildingSMART: Can we nest and IfcCrewResource under an ifcCrewResource ? # See https://forums.buildingsmart.org/t/is-the-ifcCrewResource-project-declaration-mutually-exclusive-to-aggregation-within-a-relating-ifcworkplan/3510 - context = self.file.by_type("IfcContext")[0] - ifcopenshell.api.run( - "project.assign_declaration", self.file, definition=crew_resource, relating_context=context - ) + if self.settings["parent_resource"]: + ifcopenshell.api.run( + "nest.assign_object", self.file, related_object=resource, relating_object=self.settings["parent_resource"] + ) + else: + context = self.file.by_type("IfcContext")[0] + ifcopenshell.api.run( + "project.assign_declaration", self.file, definition=crew_resource, relating_context=context + ) return crew_resource diff --git a/src/ifcopenshell-python/ifcopenshell/api/resource/add_equipment_resource.py b/src/ifcopenshell-python/ifcopenshell/api/resource/add_equipment_resource.py new file mode 100644 index 0000000000..68d63a40a5 --- /dev/null +++ b/src/ifcopenshell-python/ifcopenshell/api/resource/add_equipment_resource.py @@ -0,0 +1,27 @@ +import ifcopenshell.api +import ifcopenshell + + +class Usecase: + def __init__(self, file, **settings): + self.file = file + self.settings = { + "parent_resource": None, + } + for key, value in settings.items(): + self.settings[key] = value + + def execute(self): + equipment_resource = ifcopenshell.api.run( + "root.create_entity", + self.file, + ifc_class="IfcConstructionEquipmentResource", + name=None, + predefined_type="NOTDEFINED", + identification="none", + ) + if self.settings["parent_resource"]: + ifcopenshell.api.run( + "nest.assign_object", self.file, related_object=equipment_resource, relating_object=self.settings["parent_resource"] + ) + return equipment_resource diff --git a/src/ifcopenshell-python/ifcopenshell/api/resource/add_labor_resource.py b/src/ifcopenshell-python/ifcopenshell/api/resource/add_labor_resource.py new file mode 100644 index 0000000000..780c74c759 --- /dev/null +++ b/src/ifcopenshell-python/ifcopenshell/api/resource/add_labor_resource.py @@ -0,0 +1,27 @@ +import ifcopenshell.api +import ifcopenshell + + +class Usecase: + def __init__(self, file, **settings): + self.file = file + self.settings = { + "parent_resource": None, + } + for key, value in settings.items(): + self.settings[key] = value + + def execute(self): + labor_resource = ifcopenshell.api.run( + "root.create_entity", + self.file, + ifc_class="IfcLaborResource", + name=None, + predefined_type="NOTDEFINED", + identification="none", + ) + if self.settings["parent_resource"]: + ifcopenshell.api.run( + "nest.assign_object", self.file, related_object=labor_resource, relating_object=self.settings["parent_resource"] + ) + return labor_resource diff --git a/src/ifcopenshell-python/ifcopenshell/api/resource/add_material_resource.py b/src/ifcopenshell-python/ifcopenshell/api/resource/add_material_resource.py new file mode 100644 index 0000000000..ca508b684e --- /dev/null +++ b/src/ifcopenshell-python/ifcopenshell/api/resource/add_material_resource.py @@ -0,0 +1,27 @@ +import ifcopenshell.api +import ifcopenshell + + +class Usecase: + def __init__(self, file, **settings): + self.file = file + self.settings = { + "parent_resource": None, + } + for key, value in settings.items(): + self.settings[key] = value + + def execute(self): + material_resource = ifcopenshell.api.run( + "root.create_entity", + self.file, + ifc_class="IfcConstructionMaterialResource", + name=None, + predefined_type="NOTDEFINED", + identification="none", + ) + if self.settings["parent_resource"]: + ifcopenshell.api.run( + "nest.assign_object", self.file, related_object=material_resource, relating_object=self.settings["parent_resource"] + ) + return material_resource diff --git a/src/ifcopenshell-python/ifcopenshell/api/resource/add_product_resource.py b/src/ifcopenshell-python/ifcopenshell/api/resource/add_product_resource.py new file mode 100644 index 0000000000..b620bbaf25 --- /dev/null +++ b/src/ifcopenshell-python/ifcopenshell/api/resource/add_product_resource.py @@ -0,0 +1,27 @@ +import ifcopenshell.api +import ifcopenshell + + +class Usecase: + def __init__(self, file, **settings): + self.file = file + self.settings = { + "parent_resource": None, + } + for key, value in settings.items(): + self.settings[key] = value + + def execute(self): + product_resource = ifcopenshell.api.run( + "root.create_entity", + self.file, + ifc_class="IfcConstructionProductResource", + name=None, + predefined_type="NOTDEFINED", + identification="none", + ) + if self.settings["parent_resource"]: + ifcopenshell.api.run( + "nest.assign_object", self.file, related_object=product_resource, relating_object=self.settings["parent_resource"] + ) + return product_resource diff --git a/src/ifcopenshell-python/ifcopenshell/api/resource/add_subcontract_resource.py b/src/ifcopenshell-python/ifcopenshell/api/resource/add_subcontract_resource.py index 87516a4219..5f26bf5480 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/resource/add_subcontract_resource.py +++ b/src/ifcopenshell-python/ifcopenshell/api/resource/add_subcontract_resource.py @@ -7,6 +7,7 @@ class Usecase: def __init__(self, file, **settings): self.file = file self.settings = { + "parent_resource": None, "name": "Unnamed", "predefined_type": "NOTDEFINED", } @@ -23,8 +24,13 @@ class Usecase: ) # TODO: this is an ambiguity by buildingSMART: Can we nest and IfcCrewResource under an ifcCrewResource ? # See https://forums.buildingsmart.org/t/is-the-ifcCrewResource-project-declaration-mutually-exclusive-to-aggregation-within-a-relating-ifcworkplan/3510 - context = self.file.by_type("IfcContext")[0] - ifcopenshell.api.run( - "project.assign_declaration", self.file, definition=subcontract_resource, relating_context=context - ) + if self.settings["parent_resource"]: + ifcopenshell.api.run( + "nest.assign_object", self.file, related_object=resource, relating_object=self.settings["parent_resource"] + ) + else: + context = self.file.by_type("IfcContext")[0] + ifcopenshell.api.run( + "project.assign_declaration", self.file, definition=subcontract_resource, relating_context=context + ) return subcontract_resource diff --git a/src/ifcopenshell-python/ifcopenshell/api/resource/data.py b/src/ifcopenshell-python/ifcopenshell/api/resource/data.py index 5fdc7c5a68..c07c0d5648 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/resource/data.py +++ b/src/ifcopenshell-python/ifcopenshell/api/resource/data.py @@ -19,5 +19,4 @@ class Data: for rel in resource.IsNestedBy: [data["RelatedObjects"].append(o.id()) for o in rel.RelatedObjects if o.is_a("IfcCrewResource") or o.is_a("IfcsubcontractResource")] cls.resources[resource.id()] = data - cls.is_loaded=True diff --git a/src/ifcopenshell-python/ifcopenshell/api/resource/edit_resource.py b/src/ifcopenshell-python/ifcopenshell/api/resource/edit_resource.py new file mode 100644 index 0000000000..ff8ba0aa73 --- /dev/null +++ b/src/ifcopenshell-python/ifcopenshell/api/resource/edit_resource.py @@ -0,0 +1,10 @@ +class Usecase: + def __init__(self, file, **settings): + self.file = file + self.settings = {"resource": None, "attributes": {}} + for key, value in settings.items(): + self.settings[key] = value + + def execute(self): + for name, value in self.settings["attributes"].items(): + setattr(self.settings["resource"], name, value)