diff --git a/src/blenderbim/blenderbim/bim/module/cost/prop.py b/src/blenderbim/blenderbim/bim/module/cost/prop.py index 00a5ef18af..94d05993b2 100644 --- a/src/blenderbim/blenderbim/bim/module/cost/prop.py +++ b/src/blenderbim/blenderbim/bim/module/cost/prop.py @@ -159,7 +159,7 @@ def getResourceQuantityNames(self, context): return resourcequantitynames_enum -def update_cost_item_index(self, context): +def update_active_cost_item_index(self, context): if Data.cost_schedules[self.active_cost_schedule_id]["PredefinedType"] == "SCHEDULEOFRATES": bpy.ops.bim.load_cost_item_types() else: @@ -226,7 +226,7 @@ class BIMCostProperties(PropertyGroup): cost_items: CollectionProperty(name="Cost Items", type=CostItem) active_cost_item_id: IntProperty(name="Active Cost Id") cost_item_editing_type: StringProperty(name="Cost Item Editing Type") - active_cost_item_index: IntProperty(name="Active Cost Item Index", update=update_cost_item_index) + active_cost_item_index: IntProperty(name="Active Cost Item Index", update=update_active_cost_item_index) cost_item_attributes: CollectionProperty(name="Task Attributes", type=Attribute) contracted_cost_items: StringProperty(name="Contracted Cost Items", default="[]") quantity_types: EnumProperty(items=getQuantityTypes, name="Quantity Types") diff --git a/src/blenderbim/blenderbim/bim/module/pset/ui.py b/src/blenderbim/blenderbim/bim/module/pset/ui.py index 5b6b2b5a32..75d087812a 100644 --- a/src/blenderbim/blenderbim/bim/module/pset/ui.py +++ b/src/blenderbim/blenderbim/bim/module/pset/ui.py @@ -237,6 +237,7 @@ class BIM_PT_material_psets(Panel): class BIM_PT_task_qtos(Panel): bl_label = "IFC Task Quantity Sets" bl_idname = "BIM_PT_task_qtos" + bl_options = {"DEFAULT_CLOSED"} bl_space_type = "PROPERTIES" bl_region_type = "WINDOW" bl_context = "scene" @@ -245,6 +246,8 @@ class BIM_PT_task_qtos(Panel): @classmethod def poll(cls, context): props = context.scene.BIMWorkScheduleProperties + if not props.active_work_schedule_id: + return False total_tasks = len(context.scene.BIMTaskTreeProperties.tasks) if total_tasks > 0 and props.active_task_index < total_tasks: return True @@ -270,6 +273,7 @@ class BIM_PT_task_qtos(Panel): class BIM_PT_resource_qtos(Panel): bl_label = "IFC Resource Quantity Sets" bl_idname = "BIM_PT_resource_qtos" + bl_options = {"DEFAULT_CLOSED"} bl_space_type = "PROPERTIES" bl_region_type = "WINDOW" bl_context = "scene" @@ -303,6 +307,7 @@ class BIM_PT_resource_qtos(Panel): class BIM_PT_profile_psets(Panel): bl_label = "IFC Profile Property Sets" bl_idname = "BIM_PT_profile_psets" + bl_options = {"DEFAULT_CLOSED"} bl_space_type = "PROPERTIES" bl_region_type = "WINDOW" bl_context = "scene" @@ -337,6 +342,7 @@ class BIM_PT_profile_psets(Panel): class BIM_PT_work_schedule_psets(Panel): bl_label = "IFC Work Schedule Property Sets" bl_idname = "BIM_PT_work_schedule_psets" + bl_options = {"DEFAULT_CLOSED"} bl_space_type = "PROPERTIES" bl_region_type = "WINDOW" bl_context = "scene" @@ -344,7 +350,6 @@ class BIM_PT_work_schedule_psets(Panel): @classmethod def poll(cls, context): - props = context.scene.BIMWorkScheduleProperties if not context.scene.BIMWorkScheduleProperties.active_work_schedule_id: return False return True diff --git a/src/blenderbim/blenderbim/bim/module/resource/ui.py b/src/blenderbim/blenderbim/bim/module/resource/ui.py index 060688aa7e..8c63c25cab 100644 --- a/src/blenderbim/blenderbim/bim/module/resource/ui.py +++ b/src/blenderbim/blenderbim/bim/module/resource/ui.py @@ -61,6 +61,7 @@ class BIM_PT_resources(Panel): op.resource = 0 icon_map = { + "IfcSubContractResource": "TEXT", "IfcConstructionEquipmentResource": "TOOL_SETTINGS", "IfcLaborResource": "OUTLINER_OB_ARMATURE", "IfcConstructionMaterialResource": "MATERIAL", diff --git a/src/blenderbim/blenderbim/bim/module/sequence/__init__.py b/src/blenderbim/blenderbim/bim/module/sequence/__init__.py index 956326cb60..10d973b167 100644 --- a/src/blenderbim/blenderbim/bim/module/sequence/__init__.py +++ b/src/blenderbim/blenderbim/bim/module/sequence/__init__.py @@ -95,10 +95,14 @@ classes = ( operator.AddTaskColumn, operator.RemoveTaskColumn, operator.SetTaskSortColumn, - operator.EnableAssigningProcessToResource, + operator.LoadTaskInputs, + operator.LoadTaskResources, + operator.LoadTaskOutputs, prop.WorkPlan, prop.BIMWorkPlanProperties, prop.Task, + prop.TaskResource, + prop.TaskProduct, prop.BIMWorkScheduleProperties, prop.BIMTaskTreeProperties, prop.WorkCalendar, @@ -108,7 +112,11 @@ classes = ( ui.BIM_PT_work_plans, ui.BIM_PT_work_schedules, ui.BIM_PT_work_calendars, + ui.BIM_PT_task_icom, ui.BIM_UL_task_columns, + ui.BIM_UL_task_inputs, + ui.BIM_UL_task_resources, + ui.BIM_UL_task_outputs, ui.BIM_UL_tasks, ) diff --git a/src/blenderbim/blenderbim/bim/module/sequence/operator.py b/src/blenderbim/blenderbim/bim/module/sequence/operator.py index 8f6ca758ae..0af442fffe 100644 --- a/src/blenderbim/blenderbim/bim/module/sequence/operator.py +++ b/src/blenderbim/blenderbim/bim/module/sequence/operator.py @@ -1,4 +1,3 @@ - # BlenderBIM Add-on - OpenBIM Blender Add-on # Copyright (C) 2020, 2021 Dion Moult # @@ -784,11 +783,13 @@ class AssignProduct(bpy.types.Operator): return IfcStore.execute_ifc_operator(self, context) def _execute(self, context): + self.file = IfcStore.get_file() relating_products = ( [bpy.data.objects.get(self.relating_product)] if self.relating_product else context.selected_objects ) for relating_product in relating_products: - self.file = IfcStore.get_file() + if not relating_product.BIMObjectProperties.ifc_definition_id: + continue ifcopenshell.api.run( "sequence.assign_product", self.file, @@ -810,11 +811,13 @@ class UnassignProduct(bpy.types.Operator): return IfcStore.execute_ifc_operator(self, context) def _execute(self, context): + self.file = IfcStore.get_file() relating_products = ( [bpy.data.objects.get(self.relating_product)] if self.relating_product else context.selected_objects ) for relating_product in relating_products: - self.file = IfcStore.get_file() + if not relating_product.BIMObjectProperties.ifc_definition_id: + continue ifcopenshell.api.run( "sequence.unassign_product", self.file, @@ -830,54 +833,7 @@ class AssignProcess(bpy.types.Operator): bl_label = "Assign Process" bl_options = {"REGISTER", "UNDO"} task: bpy.props.IntProperty() - related_object: bpy.props.StringProperty() - parent_resource: bpy.props.IntProperty() - - def execute(self, context): - return IfcStore.execute_ifc_operator(self, context) - - def _execute(self, context): - self.file = IfcStore.get_file() - if self.parent_resource: - resource = ifcopenshell.api.run( - "resource.add_resource", - self.file, - **{ - "parent_resource": self.file.by_id(self.parent_resource), - "ifc_class": self.file.by_id(self.parent_resource).is_a(), - "name": self.file.by_id(self.parent_resource).Name + ": " + self.file.by_id(self.task).Name, - }, - ) - ifcopenshell.api.run( - "sequence.assign_process", - self.file, - **{ - "related_object": resource, - "relating_process": self.file.by_id(self.task), - }, - ) - ResourceData.load(self.file) - bpy.ops.bim.load_resources() - else: - related_objects = ( - [bpy.data.objects.get(self.related_object)] if self.related_object else context.selected_objects - ) - for related_object in related_objects: - ifcopenshell.api.run( - "sequence.assign_process", - self.file, - related_object=self.file.by_id(related_object.BIMObjectProperties.ifc_definition_id), - relating_process=self.file.by_id(self.task), - ) - Data.load(self.file) - return {"FINISHED"} - - -class UnassignProcess(bpy.types.Operator): - bl_idname = "bim.unassign_process" - bl_label = "Unassign Process" - bl_options = {"REGISTER", "UNDO"} - task: bpy.props.IntProperty() + related_object_type: bpy.props.StringProperty() related_object: bpy.props.StringProperty() resource: bpy.props.IntProperty() @@ -886,33 +842,98 @@ class UnassignProcess(bpy.types.Operator): def _execute(self, context): self.file = IfcStore.get_file() - if self.resource: + if self.related_object_type == "RESOURCE": + self.assign_resource() + elif self.related_object_type == "PRODUCT": + self.assign_product(context) + elif self.related_object_type == "CONTROL": + pass # TODO + return {"FINISHED"} + + def assign_resource(self): + task = self.file.by_id(self.task) + resource = self.file.by_id(self.resource) + subresource = ifcopenshell.api.run( + "resource.add_resource", + self.file, + **{"parent_resource": resource, "ifc_class": resource.is_a(), "name": resource.Name}, + ) + ifcopenshell.api.run( + "sequence.assign_process", self.file, **{"related_object": subresource, "relating_process": task} + ) + ResourceData.load(self.file) + Data.load(self.file) + bpy.ops.bim.load_resources() + bpy.ops.bim.load_task_resources() + + def assign_product(self, context): + task = self.file.by_id(self.task) + related_objects = ( + [bpy.data.objects.get(self.related_object)] if self.related_object else context.selected_objects + ) + for related_object in related_objects: + if not related_object.BIMObjectProperties.ifc_definition_id: + continue + ifcopenshell.api.run( + "sequence.assign_process", + self.file, + related_object=self.file.by_id(related_object.BIMObjectProperties.ifc_definition_id), + relating_process=task, + ) + Data.load(self.file) + bpy.ops.bim.load_task_inputs() + + +class UnassignProcess(bpy.types.Operator): + bl_idname = "bim.unassign_process" + bl_label = "Unassign Process" + bl_options = {"REGISTER", "UNDO"} + task: bpy.props.IntProperty() + related_object_type: bpy.props.StringProperty() + related_object: bpy.props.StringProperty() + resource: bpy.props.IntProperty() + + def execute(self, context): + return IfcStore.execute_ifc_operator(self, context) + + def _execute(self, context): + self.file = IfcStore.get_file() + if self.related_object_type == "RESOURCE": + self.unassign_resource() + elif self.related_object_type == "PRODUCT": + self.unassign_product(context) + elif self.related_object_type == "CONTROL": + pass # TODO + return {"FINISHED"} + + def unassign_resource(self): + task = self.file.by_id(self.task) + resource = self.file.by_id(self.resource) + ifcopenshell.api.run( + "sequence.unassign_process", self.file, related_object=resource, relating_process=task + ) + ifcopenshell.api.run("resource.remove_resource", self.file, resource=resource) + ResourceData.load(self.file) + Data.load(self.file) + bpy.ops.bim.load_resources() + bpy.ops.bim.load_task_resources() + + def unassign_product(self, context): + task = self.file.by_id(self.task) + related_objects = ( + [bpy.data.objects.get(self.related_object)] if self.related_object else context.selected_objects + ) + for related_object in related_objects: + if not related_object.BIMObjectProperties.ifc_definition_id: + continue ifcopenshell.api.run( "sequence.unassign_process", self.file, - related_object=self.file.by_id(self.resource), - relating_process=self.file.by_id(self.task), + related_object=self.file.by_id(related_object.BIMObjectProperties.ifc_definition_id), + relating_process=task, ) - ifcopenshell.api.run( - "resource.remove_resource", - self.file, - resource=self.file.by_id(self.resource), - ) - ResourceData.load(self.file) - bpy.ops.bim.load_resources() - else: - related_objects = ( - [bpy.data.objects.get(self.related_object)] if self.related_object else context.selected_objects - ) - for related_object in related_objects: - ifcopenshell.api.run( - "sequence.unassign_process", - self.file, - related_object=self.file.by_id(related_object.BIMObjectProperties.ifc_definition_id), - relating_process=self.file.by_id(self.task), - ) Data.load(self.file) - return {"FINISHED"} + bpy.ops.bim.load_task_inputs() class GenerateGanttChart(bpy.types.Operator): @@ -1726,6 +1747,11 @@ class VisualiseWorkScheduleDateRange(bpy.types.Operator): area.spaces[0].shading.color_type = "OBJECT" context.scene.frame_start = self.start_frame context.scene.frame_end = self.start_frame + self.total_frames + # with open("/home/dion/animation.json", "w") as json_file: + # guid_frames = {} + # for k, v in self.product_frames.items(): + # guid_frames[self.file.by_id(k).GlobalId] = v + # json.dump(guid_frames, json_file) return {"FINISHED"} def animate_input(self, obj, product_frame): @@ -1857,13 +1883,9 @@ class VisualiseWorkScheduleDateRange(bpy.types.Operator): finish = helper.derive_date(task.id(), "ScheduleFinish", is_latest=True) if not start or not finish: return - output_ids = [r.RelatingProduct.id() for r in task.HasAssignments or [] if r.is_a("IfcRelAssignsToProduct")] - for output_id in output_ids: + for output_id in Data.tasks[task.id()]["Outputs"]: self.add_product_frame(output_id, task, start, finish, "output") - - input_ids = [] - [input_ids.extend([o.id() for o in r.RelatedObjects]) for r in task.OperatesOn or []] - for input_id in input_ids: + for input_id in Data.tasks[task.id()]["Inputs"]: self.add_product_frame(input_id, task, start, finish, "input") def add_product_frame(self, product_id, task, start, finish, relationship): @@ -2027,14 +2049,58 @@ class SetTaskSortColumn(bpy.types.Operator): return {"FINISHED"} -class EnableAssigningProcessToResource(bpy.types.Operator): - bl_idname = "bim.enable_assigning_process_to_resources" - bl_label = "Enable Assigning Resources To Tasks" +class LoadTaskResources(bpy.types.Operator): + bl_idname = "bim.load_task_resources" + bl_label = "Load Task Resources" bl_options = {"REGISTER", "UNDO"} - task: bpy.props.IntProperty() def execute(self, context): + self.file = IfcStore.get_file() self.props = context.scene.BIMWorkScheduleProperties - self.props.active_task_id = self.task - self.props.editing_task_type = "RESOURCES" + self.tprops = context.scene.BIMTaskTreeProperties + ifc_definition_id = self.tprops.tasks[self.props.active_task_index].ifc_definition_id + self.props.task_resources.clear() + for resource_id in Data.tasks[ifc_definition_id]["Resources"]: + resource = self.file.by_id(resource_id) + new = self.props.task_resources.add() + new.ifc_definition_id = resource_id + new.name = resource.Name or "Unnamed" + return {"FINISHED"} + + +class LoadTaskInputs(bpy.types.Operator): + bl_idname = "bim.load_task_inputs" + bl_label = "Load Task Inputs" + bl_options = {"REGISTER", "UNDO"} + + def execute(self, context): + self.file = IfcStore.get_file() + self.props = context.scene.BIMWorkScheduleProperties + self.tprops = context.scene.BIMTaskTreeProperties + ifc_definition_id = self.tprops.tasks[self.props.active_task_index].ifc_definition_id + self.props.task_inputs.clear() + for input_id in Data.tasks[ifc_definition_id]["Inputs"]: + product = self.file.by_id(input_id) + new = self.props.task_inputs.add() + new.ifc_definition_id = input_id + new.name = product.Name or "Unnamed" + return {"FINISHED"} + + +class LoadTaskOutputs(bpy.types.Operator): + bl_idname = "bim.load_task_outputs" + bl_label = "Load Task Outputs" + bl_options = {"REGISTER", "UNDO"} + + def execute(self, context): + self.file = IfcStore.get_file() + self.props = context.scene.BIMWorkScheduleProperties + self.tprops = context.scene.BIMTaskTreeProperties + ifc_definition_id = self.tprops.tasks[self.props.active_task_index].ifc_definition_id + self.props.task_outputs.clear() + for output_id in Data.tasks[ifc_definition_id]["outputs"]: + product = self.file.by_id(output_id) + new = self.props.task_outputs.add() + new.ifc_definition_id = output_id + new.name = product.Name or "Unnamed" return {"FINISHED"} diff --git a/src/blenderbim/blenderbim/bim/module/sequence/prop.py b/src/blenderbim/blenderbim/bim/module/sequence/prop.py index 61711c1ba7..78e7a0b0b3 100644 --- a/src/blenderbim/blenderbim/bim/module/sequence/prop.py +++ b/src/blenderbim/blenderbim/bim/module/sequence/prop.py @@ -85,6 +85,12 @@ def getWorkCalendars(self, context): return [(str(k), v["Name"], "") for k, v in Data.work_calendars.items()] +def update_active_task_index(self, context): + bpy.ops.bim.load_task_inputs() + bpy.ops.bim.load_task_resources() + bpy.ops.bim.load_task_outputs() + + def updateTaskName(self, context): props = context.scene.BIMWorkScheduleProperties if not props.is_task_update_enabled or self.name == "Unnamed": @@ -227,13 +233,6 @@ def updateVisualisationStartFinish(self, context, startfinish): setattr(self, startfinish, canonical_value) -def getResources(self, context): - self.file = IfcStore.get_file() - return [(str(k), v["Name"], "") for k, v in ResourceData.resources.items() - if self.file.by_id(k).Nests and self.file.by_id(k).Nests[0].RelatingObject.HasContext - ] - - class Task(PropertyGroup): name: StringProperty(name="Name", update=updateTaskName) identification: StringProperty(name="Identification", update=updateTaskIdentification) @@ -259,6 +258,16 @@ class WorkPlan(PropertyGroup): ifc_definition_id: IntProperty(name="IFC Definition ID") +class TaskResource(PropertyGroup): + name: StringProperty(name="Name") + ifc_definition_id: IntProperty(name="IFC Definition ID") + + +class TaskProduct(PropertyGroup): + name: StringProperty(name="Name") + ifc_definition_id: IntProperty(name="IFC Definition ID") + + class BIMWorkPlanProperties(PropertyGroup): work_plan_attributes: CollectionProperty(name="Work Plan Attributes", type=Attribute) editing_type: StringProperty(name="Editing Type") @@ -275,7 +284,7 @@ class BIMWorkScheduleProperties(PropertyGroup): editing_task_type: StringProperty(name="Editing Task Type") active_work_schedule_index: IntProperty(name="Active Work Schedules Index") active_work_schedule_id: IntProperty(name="Active Work Schedules Id") - active_task_index: IntProperty(name="Active Task Index") + active_task_index: IntProperty(name="Active Task Index", update=update_active_task_index) active_task_id: IntProperty(name="Active Task Id") task_attributes: CollectionProperty(name="Task Attributes", type=Attribute) should_show_visualisation_ui: BoolProperty(name="Should Show Visualisation UI", default=False) @@ -323,7 +332,12 @@ class BIMWorkScheduleProperties(PropertyGroup): name="Speed Type", default="FRAME_SPEED", ) - resources: EnumProperty(items=getResources, name="Resources") + task_resources: CollectionProperty(name="Task Resources", type=TaskResource) + active_task_resource_index: IntProperty(name="Active Task Resource Index") + task_inputs: CollectionProperty(name="Task Inputs", type=TaskProduct) + active_task_input_index: IntProperty(name="Active Task Input Index") + task_outputs: CollectionProperty(name="Task Outputs", type=TaskProduct) + active_task_output_index: IntProperty(name="Active Task Output Index") class BIMTaskTreeProperties(PropertyGroup): diff --git a/src/blenderbim/blenderbim/bim/module/sequence/ui.py b/src/blenderbim/blenderbim/bim/module/sequence/ui.py index 57a10f9ae4..7586690242 100644 --- a/src/blenderbim/blenderbim/bim/module/sequence/ui.py +++ b/src/blenderbim/blenderbim/bim/module/sequence/ui.py @@ -170,14 +170,8 @@ class BIM_PT_work_schedules(Panel): row.operator("bim.remove_task", text="", icon="X").task = ifc_definition_id else: row.operator("bim.enable_editing_task_sequence", text="", icon="TRACKING").task = ifc_definition_id - row.operator( - "bim.select_task_related_products", icon="RESTRICT_SELECT_OFF", text="" - ).task = ifc_definition_id row.operator("bim.enable_editing_task_time", text="", icon="TIME").task = ifc_definition_id row.operator("bim.enable_editing_task_calendar", text="", icon="VIEW_ORTHO").task = ifc_definition_id - row.operator( - "bim.enable_assigning_process_to_resources", text="", icon="COMMUNITY" - ).task = ifc_definition_id row.operator("bim.enable_editing_task", text="", icon="GREASEPENCIL").task = ifc_definition_id row.operator("bim.add_task", text="", icon="ADD").task = ifc_definition_id row.operator("bim.remove_task", text="", icon="X").task = ifc_definition_id @@ -252,8 +246,6 @@ class BIM_PT_work_schedules(Panel): self.draw_editable_task_sequence_ui() elif self.props.active_task_time_id and self.props.editing_task_type == "TASKTIME": self.draw_editable_task_time_attributes_ui() - elif self.props.active_task_id and self.props.editing_task_type == "RESOURCES": - self.draw_editable_task_resource_ui() def draw_editable_task_sequence_ui(self): task = Data.tasks[self.props.active_task_id] @@ -327,22 +319,98 @@ class BIM_PT_work_schedules(Panel): def draw_editable_task_time_attributes_ui(self): blenderbim.bim.helper.draw_attributes(self.props.task_time_attributes, self.layout) - def draw_editable_task_resource_ui(self): - row = self.layout.row(align=True) - row.prop(self.props, "resources", text="") - op = row.operator("bim.assign_process", text="", icon="ADD") - if self.props.resources: - op.parent_resource = int(self.props.resources) - op.task = self.props.active_task_id - task = Data.tasks[self.props.active_task_id] - ResourceData.load(IfcStore.get_file()) - for related_obect_id in task["OperatesOn"]: - resource = ResourceData.resources[related_obect_id] - row = self.layout.row(align=True) - row.label(text=resource["Name"], icon="COMMUNITY") - op = row.operator("bim.unassign_process", text="", icon="X") - op.task = self.props.active_task_id - op.resource = related_obect_id + +class BIM_PT_task_icom(Panel): + bl_label = "IFC Task ICOM" + bl_idname = "BIM_PT_task_icom" + bl_options = {"DEFAULT_CLOSED"} + bl_space_type = "PROPERTIES" + bl_region_type = "WINDOW" + bl_context = "scene" + bl_parent_id = "BIM_PT_work_schedules" + + @classmethod + def poll(cls, context): + props = context.scene.BIMWorkScheduleProperties + if not props.active_work_schedule_id: + return False + total_tasks = len(context.scene.BIMTaskTreeProperties.tasks) + if total_tasks > 0 and props.active_task_index < total_tasks: + return True + return False + + def draw(self, context): + self.props = context.scene.BIMWorkScheduleProperties + self.tprops = context.scene.BIMTaskTreeProperties + task = self.tprops.tasks[self.props.active_task_index] + + grid = self.layout.grid_flow(columns=3, even_columns=True) + + # Column1 + col = grid.column() + + row2 = col.row(align=True) + row2.label(text="Inputs") + + if context.selected_objects: + op = row2.operator("bim.assign_process", icon="ADD", text="") + op.task = task.ifc_definition_id + op.related_object_type = "PRODUCT" + op.related_object = "" + op = row2.operator("bim.unassign_process", icon="REMOVE", text="") + op.task = task.ifc_definition_id + op.related_object_type = "PRODUCT" + op.related_object = "" + + row2 = col.row() + row2.template_list( + "BIM_UL_task_inputs", "", self.props, "task_inputs", self.props, "active_task_input_index" + ) + + # Column2 + col = grid.column() + + row2 = col.row(align=True) + row2.label(text="Resources") + + total_resources = len(context.scene.BIMResourceTreeProperties.resources) + if total_resources and context.scene.BIMResourceProperties.active_resource_index < total_resources: + resource_id = context.scene.BIMResourceTreeProperties.resources[context.scene.BIMResourceProperties.active_resource_index].ifc_definition_id + op = row2.operator("bim.assign_process", icon="ADD", text="") + op.task = task.ifc_definition_id + op.related_object_type = "RESOURCE" + op.resource = resource_id + op = row2.operator("bim.unassign_process", icon="REMOVE", text="") + op.task = task.ifc_definition_id + op.related_object_type = "RESOURCE" + op.resource = resource_id + + row2 = col.row() + row2.template_list( + "BIM_UL_task_resources", "", self.props, "task_resources", self.props, "active_task_resource_index" + ) + + # Column3 + col = grid.column() + + row2 = col.row(align=True) + row2.label(text="Outputs") + + if context.selected_objects: + op = row2.operator("bim.assign_product", icon="ADD", text="") + op.task = task.ifc_definition_id + op.relating_product = "" + op = row2.operator("bim.unassign_product", icon="REMOVE", text="") + op.task = task.ifc_definition_id + op.relating_product = "" + + op = row2.operator("bim.select_task_related_products", icon="RESTRICT_SELECT_OFF", text="") + op.task = task.ifc_definition_id + + row2 = col.row() + row2.template_list( + "BIM_UL_task_outputs", "", self.props, "task_outputs", self.props, "active_task_output_index" + ) class BIM_UL_task_columns(UIList): @@ -356,6 +424,31 @@ class BIM_UL_task_columns(UIList): row.operator("bim.remove_task_column", text="", icon="X").name = item.name +class BIM_UL_task_inputs(UIList): + def draw_item(self, context, layout, data, item, icon, active_data, active_propname): + props = context.scene.BIMWorkScheduleProperties + if item: + row = layout.row(align=True) + row.prop(item, "name", emboss=False, text="") + #row.operator("bim.remove_task_column", text="", icon="X").name = item.name + + +class BIM_UL_task_resources(UIList): + def draw_item(self, context, layout, data, item, icon, active_data, active_propname): + props = context.scene.BIMWorkScheduleProperties + if item: + row = layout.row(align=True) + row.prop(item, "name", emboss=False, text="") + + +class BIM_UL_task_outputs(UIList): + def draw_item(self, context, layout, data, item, icon, active_data, active_propname): + props = context.scene.BIMWorkScheduleProperties + if item: + row = layout.row(align=True) + row.prop(item, "name", emboss=False, text="") + + class BIM_UL_tasks(UIList): def draw_item(self, context, layout, data, item, icon, active_data, active_propname): if item: @@ -372,23 +465,6 @@ class BIM_UL_tasks(UIList): self.draw_custom_columns(split2, item, task) - if context.active_object: - oprops = context.active_object.BIMObjectProperties - - if oprops.ifc_definition_id in Data.tasks[item.ifc_definition_id]["OperatesOn"]: - op = row.operator("bim.unassign_process", text="", icon="MARKER_HLT", emboss=False) - op.task = item.ifc_definition_id - else: - op = row.operator("bim.assign_process", text="", icon="MARKER", emboss=False) - op.task = item.ifc_definition_id - - if oprops.ifc_definition_id in Data.tasks[item.ifc_definition_id]["RelatingProducts"]: - op = row.operator("bim.unassign_product", text="", icon="KEYFRAME_HLT", emboss=False) - op.task = item.ifc_definition_id - else: - op = row.operator("bim.assign_product", text="", icon="KEYFRAME", emboss=False) - op.task = item.ifc_definition_id - if self.props.active_task_id and self.props.editing_task_type == "ATTRIBUTES": row.prop( item, diff --git a/src/ifcopenshell-python/ifcopenshell/api/project/append_asset.py b/src/ifcopenshell-python/ifcopenshell/api/project/append_asset.py index 7ecb9d31a0..9fd01fac4c 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/project/append_asset.py +++ b/src/ifcopenshell-python/ifcopenshell/api/project/append_asset.py @@ -63,8 +63,7 @@ class Usecase: for inverse in self.file.get_inverse(added_context): ifcopenshell.util.element.replace_attribute(inverse, added_context, equivalent_existing_context) for added_context in added_contexts: - if added_context.is_a() == "IfcGeometricRepresentationContext": - ifcopenshell.util.element.remove_deep(self.file, added_context) + ifcopenshell.util.element.remove_deep(self.file, added_context) return element def add_element(self, element): diff --git a/src/ifcopenshell-python/ifcopenshell/api/resource/add_resource.py b/src/ifcopenshell-python/ifcopenshell/api/resource/add_resource.py index 63c9be21c7..ccba773efc 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/resource/add_resource.py +++ b/src/ifcopenshell-python/ifcopenshell/api/resource/add_resource.py @@ -19,7 +19,7 @@ class Usecase: self.file, ifc_class=self.settings["ifc_class"], predefined_type=self.settings["predefined_type"], - name=self.settings["name"] or "Unammed", + name=self.settings["name"] or "Unnamed", ) # TODO: this is an ambiguity by buildingSMART: Can we nest an IfcCrewResource under an IfcCrewResource ? # https://forums.buildingsmart.org/t/what-are-allowed-to-be-root-level-construction-resources/3550 diff --git a/src/ifcopenshell-python/ifcopenshell/api/sequence/data.py b/src/ifcopenshell-python/ifcopenshell/api/sequence/data.py index ef41813f09..90b70af5b3 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/sequence/data.py +++ b/src/ifcopenshell-python/ifcopenshell/api/sequence/data.py @@ -126,8 +126,10 @@ class Data: del data["OwnerHistory"] data["HasAssignmentsWorkCalendar"] = [] data["RelatedObjects"] = [] - data["RelatingProducts"] = [] - data["OperatesOn"] = [] + data["Inputs"] = [] + data["Controls"] = [] + data["Outputs"] = [] + data["Resources"] = [] data["IsPredecessorTo"] = [] data["IsSuccessorFrom"] = [] if task.TaskTime: @@ -136,11 +138,13 @@ class Data: [data["RelatedObjects"].append(o.id()) for o in rel.RelatedObjects if o.is_a("IfcTask")] data["Nests"] = [r.RelatingObject.id() for r in task.Nests or []] [ - data["RelatingProducts"].append(r.RelatingProduct.id()) + data["Outputs"].append(r.RelatingProduct.id()) for r in task.HasAssignments if r.is_a("IfcRelAssignsToProduct") ] - [data["OperatesOn"].extend([o.id() for o in r.RelatedObjects]) for r in task.OperatesOn] + [data["Resources"].extend([o.id() for o in r.RelatedObjects if o.is_a("IfcResource")]) for r in task.OperatesOn] + [data["Controls"].extend([o.id() for o in r.RelatedObjects if o.is_a("IfcControl")]) for r in task.OperatesOn] + [data["Inputs"].extend([o.id() for o in r.RelatedObjects if o.is_a("IfcProduct")]) for r in task.OperatesOn] [data["IsPredecessorTo"].append(rel.id()) for rel in task.IsPredecessorTo or []] [data["IsSuccessorFrom"].append(rel.id()) for rel in task.IsSuccessorFrom or []] [