diff --git a/src/blenderbim/blenderbim/bim/module/resource/__init__.py b/src/blenderbim/blenderbim/bim/module/resource/__init__.py index 86dee57ace..4ab2948d2e 100644 --- a/src/blenderbim/blenderbim/bim/module/resource/__init__.py +++ b/src/blenderbim/blenderbim/bim/module/resource/__init__.py @@ -8,17 +8,27 @@ classes = ( operator.LoadResources, operator.AddCrewResource, operator.AddSubcontractResource, + operator.AddEquipementResource, + operator.AddLaborResource, + operator.AddProductResource, + operator.AddMaterialResource, operator.EditResource, operator.RemoveResource, + operator.EnableEditingNestedResource, + operator.LoadNestedResourceProperties, + operator.DisableNestedResourceEditingUI, prop.Resource, prop.BIMResourceProperties, + prop.BIMResourceTreeProperties, ui.BIM_PT_resources, - ui.BIM_UL_resources, + ui.BIM_UL_nested_resources, ) def register(): bpy.types.Scene.BIMResourceProperties = bpy.props.PointerProperty(type=prop.BIMResourceProperties) + bpy.types.Scene.BIMResourceTreeProperties = bpy.props.PointerProperty(type=prop.BIMResourceTreeProperties) def unregister(): del bpy.types.Scene.BIMResourceProperties + del bpy.types.Scene.BIMResourceTreeProperties diff --git a/src/blenderbim/blenderbim/bim/module/resource/operator.py b/src/blenderbim/blenderbim/bim/module/resource/operator.py index 72fc3971b6..f6fe4604ba 100644 --- a/src/blenderbim/blenderbim/bim/module/resource/operator.py +++ b/src/blenderbim/blenderbim/bim/module/resource/operator.py @@ -17,7 +17,7 @@ class LoadResources(bpy.types.Operator): new = props.resources.add() new.ifc_definition_id = ifc_definition_id new.name = resource["Name"] or "Unnamed" - props.is_editing = True + props.is_loaded = True bpy.ops.bim.disable_editing_resource() return {"FINISHED"} @@ -27,16 +27,21 @@ class EnableEditingResource(bpy.types.Operator): resource: bpy.props.IntProperty() def execute(self, context): - props = context.scene.BIMResourceProperties - while len(props.resource_attributes) > 0: - props.resource_attributes.remove(0) + self.props = context.scene.BIMResourceProperties + self.props.active_resource_id = self.resource + while len(self.props.resource_attributes) > 0: + self.props.resource_attributes.remove(0) + self.enable_editing_resource() + self.props.is_editing = "RESOURCE" + return {"FINISHED"} + def enable_editing_resource(self): data = Data.resources[self.resource] - for attribute in IfcStore.get_schema().declaration_by_name("IfcConstructionResource").all_attributes(): + for attribute in IfcStore.get_schema().declaration_by_name("IfcResource").all_attributes(): data_type = ifcopenshell.util.attribute.get_primitive_type(attribute) if data_type == "entity": continue - new = props.resource_attributes.add() + new = self.props.resource_attributes.add() new.name = attribute.name() new.is_null = data[attribute.name()] is None new.is_optional = attribute.optional() @@ -47,15 +52,65 @@ class EnableEditingResource(bpy.types.Operator): new.enum_items = json.dumps(ifcopenshell.util.attribute.get_enum_items(attribute)) if data[attribute.name()]: new.enum_value = data[attribute.name()] - props.active_resource_id = self.resource + + +class EnableEditingNestedResource(bpy.types.Operator): + bl_idname = "bim.enable_editing_nested_resources" + bl_label = "Enable Editing Nested Resource" + resource: bpy.props.IntProperty() + + def execute(self, context): + self.props = context.scene.BIMResourceProperties + self.tprops = context.scene.BIMResourceTreeProperties + self.props.active_resource_id = self.resource + while len(self.tprops.nested_resources) > 0: + self.tprops.nested_resources.remove(0) + + self.contracted_nested_resources = json.loads(self.props.contracted_nested_resources) + for related_object_id in Data.resources[self.resource]["RelatedObjects"]: + self.create_new_nested_resource_li(related_object_id, 0) + bpy.ops.bim.load_nested_resource_properties() + self.props.is_editing = "NESTED_RESOURCE" return {"FINISHED"} + def create_new_nested_resource_li(self, related_object_id, level_index): + nested_resource = Data.nested_resources[related_object_id] + new = self.tprops.nested_resources.add() + new.ifc_definition_id = related_object_id + new.is_expanded = related_object_id not in self.contracted_nested_resources + new.level_index = level_index + if nested_resource["RelatedObjects"]: + new.has_children = True + if new.is_expanded: + for related_object_id in nested_resource["RelatedObjects"]: + self.create_new_nested_resource_li(related_object_id, level_index + 1) + return {"FINISHED"} + + +class LoadNestedResourceProperties(bpy.types.Operator): + bl_idname = "bim.load_nested_resource_properties" + bl_label = "Load nested_resource Properties" + nested_resource: bpy.props.IntProperty() + + def execute(self, context): + self.props = context.scene.BIMResourceProperties + self.tprops = context.scene.BIMResourceTreeProperties + self.props.is_nested_resource_update_enabled = False + for item in self.tprops.nested_resources: + if self.nested_resource and item.ifc_definition_id != self.nested_resource: + continue + nested_resource = Data.nested_resources[item.ifc_definition_id] + item.name = nested_resource["Name"] or "Unnamed" + self.props.is_nested_resource_update_enabled = True + return {"FINISHED"} + + class DisableEditingResource(bpy.types.Operator): bl_idname = "bim.disable_editing_resource" bl_label = "Disable Editing Workplan" def execute(self, context): - context.scene.BIMWorkPlanProperties.active_resource_id = 0 + context.scene.BIMResourceProperties.active_resource_id = 0 return {"FINISHED"} class DisableResourceEditingUI(bpy.types.Operator): @@ -63,16 +118,31 @@ class DisableResourceEditingUI(bpy.types.Operator): bl_label = "Disable Resources Editing UI" def execute(self, context): - context.scene.BIMResourceProperties.is_editing = False + 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" bl_label = "Add Subcontract Resource" + resource: bpy.props.IntProperty() def execute(self, context): - ifcopenshell.api.run("resource.add_subcontract_resource", IfcStore.get_file()) + if self.resource: + ifcopenshell.api.run( + "resource.add_subcontract_resource", + IfcStore.get_file(), + resource=IfcStore.get_file().by_id(self.resource) + ) + else: + ifcopenshell.api.run("resource.add_subcontract_resource", IfcStore.get_file()) Data.load(IfcStore.get_file()) return {"FINISHED"} @@ -80,13 +150,78 @@ class AddSubcontractResource(bpy.types.Operator): class AddCrewResource(bpy.types.Operator): bl_idname = "bim.add_crew_resource" bl_label = "Add Crew Resource" + resource: bpy.props.IntProperty() def execute(self, context): - ifcopenshell.api.run("resource.add_crew_resource", IfcStore.get_file()) + if self.resource: + ifcopenshell.api.run( + "resource.add_crew_resource", + IfcStore.get_file(), + resource=IfcStore.get_file().by_id(self.resource) + ) + else: + ifcopenshell.api.run("resource.add_crew_resource", IfcStore.get_file()) Data.load(IfcStore.get_file()) return {"FINISHED"} +class AddEquipementResource(bpy.types.Operator): + bl_idname = "bim.add_equipement_resource" + bl_label = "Add Equipement Resource" + resource: bpy.props.IntProperty() + + def execute(self, context): + ifcopenshell.api.run( + "resource.add_equipement_resource", + IfcStore.get_file(), + resource=IfcStore.get_file().by_id(self.resource) + ) + Data.load(IfcStore.get_file()) + return {"FINISHED"} + +class AddLaborResource(bpy.types.Operator): + bl_idname = "bim.add_labor_resource" + bl_label = "Add Labor Resource" + resource: bpy.props.IntProperty() + + def execute(self, context): + ifcopenshell.api.run( + "resource.add_labor_resource", + IfcStore.get_file(), + resource=IfcStore.get_file().by_id(self.resource) + ) + Data.load(IfcStore.get_file()) + return {"FINISHED"} + + +class AddMaterialResource(bpy.types.Operator): + bl_idname = "bim.add_material_resource" + bl_label = "Add Material Resource" + resource: bpy.props.IntProperty() + + def execute(self, context): + ifcopenshell.api.run( + "resource.add_material_resource", + IfcStore.get_file(), + resource=IfcStore.get_file().by_id(self.resource) + ) + Data.load(IfcStore.get_file()) + return {"FINISHED"} + +class AddProductResource(bpy.types.Operator): + bl_idname = "bim.add_product_resource" + bl_label = "Add Product Resource" + resource: bpy.props.IntProperty() + + def execute(self, context): + ifcopenshell.api.run( + "resource.add_product_resource", + IfcStore.get_file(), + resource=IfcStore.get_file().by_id(self.resource) + ) + Data.load(IfcStore.get_file()) + return {"FINISHED"} + class EditResource(bpy.types.Operator): bl_idname = "bim.edit_resource" bl_label = "Edit Resource" diff --git a/src/blenderbim/blenderbim/bim/module/resource/prop.py b/src/blenderbim/blenderbim/bim/module/resource/prop.py index 2f94fe2939..644c0f9abc 100644 --- a/src/blenderbim/blenderbim/bim/module/resource/prop.py +++ b/src/blenderbim/blenderbim/bim/module/resource/prop.py @@ -27,10 +27,11 @@ class Resource(PropertyGroup): class BIMResourceProperties(PropertyGroup): resource_attributes: CollectionProperty(name="Resource Attributes", type=Attribute) is_editing: BoolProperty(name="Is Editing") - is_a:StringProperty(name="Contracted Cost Items", default="[]") active_resource_id: IntProperty(name="Active Resource Id") active_resource_index: IntProperty(name="Active Resource Id") + 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) diff --git a/src/blenderbim/blenderbim/bim/module/resource/ui.py b/src/blenderbim/blenderbim/bim/module/resource/ui.py index 81aa6d445a..107fb4319d 100644 --- a/src/blenderbim/blenderbim/bim/module/resource/ui.py +++ b/src/blenderbim/blenderbim/bim/module/resource/ui.py @@ -15,33 +15,49 @@ class BIM_PT_resources(Panel): return IfcStore.get_file() def draw(self, context): + self.props = context.scene.BIMResourceProperties + self.tprops = context.scene.BIMResourceTreeProperties + row = self.layout.row() + 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: Data.load(IfcStore.get_file()) - self.props = context.scene.BIMResourceProperties + if self.props.is_loaded: + row = self.layout.row(align=True) + row.operator("bim.add_subcontract_resource", text="Add Subcontract", icon="FILE_TICK") + row.operator("bim.add_crew_resource", text="Add Crew", icon="COMMUNITY") + for resource_id, resource in Data.resources.items(): + self.draw_resource_ui(resource_id, resource) - row = self.layout.row(align=True) - if self.props.is_editing: - row.operator("bim.add_subcontract_resource",emboss=False, text="", icon="FILE_TICK") - row.operator("bim.add_crew_resource",emboss=False, text="", icon="COMMUNITY") - row.operator("bim.disable_resource_editing_ui", text="", icon="CANCEL") + def draw_resource_ui(self, resource_id, resource): + 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") else: - row.operator("bim.load_resources", text="", icon="GREASEPENCIL") + 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.is_editing: - self.layout.template_list( - "BIM_UL_resources", - "", - self.props, - "resources", - self.props, - "active_resource_index", - ) + if self.props.active_resource_id == resource_id: + if self.props.is_editing == "RESOURCE": + self.draw_editable_resource_ui() + elif self.props.is_editing == "NESTED_RESOURCE": + self.draw_editable_nested_resource_ui(resource_id) - if self.props.active_resource_id: - self.draw_editable_ui(context) - - def draw_editable_ui(self, context): - for attribute in self.props.resource_attributes: + def draw_editable_resource_ui(self): + for attribute in self.props.resources: row = self.layout.row(align=True) if attribute.data_type == "string": row.prop(attribute, "string_value", text=attribute.name) @@ -56,18 +72,59 @@ class BIM_PT_resources(Panel): if attribute.is_optional: row.prop(attribute, "is_null", icon="RADIOBUT_OFF" if attribute.is_null else "RADIOBUT_ON", text="") + def draw_editable_nested_resource_ui(self, resource_id): + self.layout.template_list( + "BIM_UL_nested_resources", + "", + self.tprops, + "nested_resources", + self.props, + "active_nested_resource_index", + ) + if self.props.active_nested_resource_id: + self.draw_editable_nested_resource_attributes_ui() -class BIM_UL_resources(UIList): + + def draw_editable_nested_resource_attributes_ui(self): + for attribute in self.props.nested_resource_attributes: + row = self.layout.row(align=True) + if attribute.data_type == "string": + row.prop(attribute, "string_value", text=attribute.name) + elif attribute.data_type == "boolean": + row.prop(attribute, "bool_value", text=attribute.name) + elif attribute.data_type == "integer": + row.prop(attribute, "int_value", text=attribute.name) + elif attribute.data_type == "enum": + row.prop(attribute, "enum_value", text=attribute.name) + if attribute.is_optional: + row.prop(attribute, "is_null", icon="RADIOBUT_OFF" if attribute.is_null else "RADIOBUT_ON", text="") + + +class BIM_UL_nested_resources(UIList): def draw_item(self, context, layout, data, item, icon, active_data, active_propname): if item: + props = context.scene.BIMResourceProperties row = layout.row(align=True) - row.label(text=item.name) - if context.scene.BIMResourceProperties.active_resource_id == item.ifc_definition_id: - row.operator("bim.edit_resource", text="", icon="CHECKMARK") - row.operator("bim.disable_editing_resource", text="", icon="X") - elif context.scene.BIMResourceProperties.active_resource_id: - row.operator("bim.remove_resource", text="", icon="X").resource = item.ifc_definition_id + for i in range(0, item.level_index): + row.label(text="", icon="BLANK1") + if item.has_children: + if item.is_expanded: + row.operator( + "bim.contract_nested_resource", text="", emboss=False, icon="DISCLOSURE_TRI_DOWN" + ).nested_resource = item.ifc_definition_id + else: + row.operator( + "bim.expand_nested_resource", text="", emboss=False, icon="DISCLOSURE_TRI_RIGHT" + ).nested_resource = item.ifc_definition_id + + if props.active_nested_resource_id == item.ifc_definition_id: + row.operator("bim.edit_nested_resource", text="", icon="CHECKMARK") + row.operator("bim.disable_editing_nested_resource", text="", icon="CANCEL") + elif props.active_nested_resource_id: + row.operator("bim.add_nested_resource", text="", icon="ADD").nested_resource = item.ifc_definition_id + row.operator("bim.remove_nested_resource", text="", icon="X").nested_resource = item.ifc_definition_id else: - op = row.operator("bim.enable_editing_resource", text="", icon="GREASEPENCIL") - op.resource = item.ifc_definition_id - row.operator("bim.remove_resource", text="", icon="X").resource = item.ifc_definition_id + row.operator("bim.enable_editing_nested_resource_time", text="", icon="TIME").nested_resource = item.ifc_definition_id + row.operator("bim.enable_editing_nested_resource", text="", icon="GREASEPENCIL").nested_resource = item.ifc_definition_id + row.operator("bim.add_nested_resource", text="", icon="ADD").nested_resource = item.ifc_definition_id + row.operator("bim.remove_nested_resource", text="", icon="X").nested_resource = item.ifc_definition_id