diff --git a/src/bonsai/bonsai/bim/module/owner/__init__.py b/src/bonsai/bonsai/bim/module/owner/__init__.py index 9318b42ba0..52c1c7cc19 100644 --- a/src/bonsai/bonsai/bim/module/owner/__init__.py +++ b/src/bonsai/bonsai/bim/module/owner/__init__.py @@ -23,6 +23,7 @@ classes = ( operator.AddActor, operator.AddAddress, operator.AddAddressAttribute, + operator.AddApplication, operator.AddOrganisation, operator.AddPerson, operator.AddPersonAndOrganisation, @@ -32,16 +33,19 @@ classes = ( operator.ClearUser, operator.DisableEditingActor, operator.DisableEditingAddress, + operator.DisableEditingApplication, operator.DisableEditingOrganisation, operator.DisableEditingPerson, operator.DisableEditingRole, operator.EditActor, operator.EditAddress, + operator.EditApplication, operator.EditOrganisation, operator.EditPerson, operator.EditRole, operator.EnableEditingActor, operator.EnableEditingAddress, + operator.EnableEditingApplication, operator.EnableEditingOrganisation, operator.EnableEditingPerson, operator.EnableEditingRole, diff --git a/src/bonsai/bonsai/bim/module/owner/operator.py b/src/bonsai/bonsai/bim/module/owner/operator.py index 4d3b90b8de..2e77180936 100644 --- a/src/bonsai/bonsai/bim/module/owner/operator.py +++ b/src/bonsai/bonsai/bim/module/owner/operator.py @@ -521,3 +521,46 @@ class RemoveApplication(bpy.types.Operator, tool.Ifc.Operator): def _execute(self, context): ifc_file = tool.Ifc.get() ifcopenshell.api.owner.remove_application(ifc_file, ifc_file.by_id(self.application_id)) + + +class EnableEditingApplication(bpy.types.Operator): + bl_idname = "bim.enable_editing_application" + bl_label = "Enable Editing Application" + bl_options = {"REGISTER", "UNDO"} + application_id: bpy.props.IntProperty() # pyright: ignore[reportRedeclaration] + + if TYPE_CHECKING: + application_id: int + + def execute(self, context) -> "set[rna_enums.OperatorReturnItems]": + core.enable_editing_application(tool.Owner, tool.Ifc.get().by_id(self.application_id)) + return {"FINISHED"} + + +class DisableEditingApplication(bpy.types.Operator): + bl_idname = "bim.disable_editing_application" + bl_label = "Disable Editing Application" + bl_options = {"REGISTER", "UNDO"} + + def execute(self, context) -> "set[rna_enums.OperatorReturnItems]": + core.disable_editing_application(tool.Owner) + return {"FINISHED"} + + +class EditApplication(bpy.types.Operator, tool.Ifc.Operator): + bl_idname = "bim.edit_application" + bl_label = "Edit Application" + bl_options = {"REGISTER", "UNDO"} + + def _execute(self, context) -> "set[rna_enums.OperatorReturnItems]": + core.edit_application(tool.Ifc, tool.Owner) + return {"FINISHED"} + + +class AddApplication(bpy.types.Operator, tool.Ifc.Operator): + bl_idname = "bim.add_application" + bl_label = "Add Application" + bl_options = {"REGISTER", "UNDO"} + + def _execute(self, context) -> None: + core.add_application(tool.Ifc, tool.Owner) diff --git a/src/bonsai/bonsai/bim/module/owner/prop.py b/src/bonsai/bonsai/bim/module/owner/prop.py index 801586dd20..ecd8b8f723 100644 --- a/src/bonsai/bonsai/bim/module/owner/prop.py +++ b/src/bonsai/bonsai/bim/module/owner/prop.py @@ -121,6 +121,9 @@ class BIMOwnerProperties(PropertyGroup): ) actor: EnumProperty(items=get_actor, name="Actor") + active_application_id: IntProperty() + application_attributes: CollectionProperty(type=Attribute) + if TYPE_CHECKING: active_person_id: int person_attributes: bpy.types.bpy_prop_collection_idprop[Attribute] @@ -147,3 +150,6 @@ class BIMOwnerProperties(PropertyGroup): actor_type: str the_actor: str actor: str + + active_application_id: int + application_attributes: bpy.types.bpy_prop_collection_idprop[Attribute] diff --git a/src/bonsai/bonsai/bim/module/owner/ui.py b/src/bonsai/bonsai/bim/module/owner/ui.py index 0133cacbc5..9249754e46 100644 --- a/src/bonsai/bonsai/bim/module/owner/ui.py +++ b/src/bonsai/bonsai/bim/module/owner/ui.py @@ -362,10 +362,24 @@ class BIM_PT_applications(bpy.types.Panel): assert (layout := self.layout) props = tool.Owner.get_owner_props() + row = self.layout.row() + row.operator("bim.add_application", icon="ADD") + apps_data: list[dict[str, Any]] = ApplicationsData.data["applications"] if not apps_data: layout.label(text="No Applications Found") + return + for app_data in apps_data: - row = layout.row() - row.label(text=app_data["name"]) - row.operator("bim.remove_application", icon="X", text="").application_id = app_data["id"] + if props.active_application_id == app_data["id"]: + box = self.layout.box() + row = box.row(align=True) + row.operator("bim.edit_application", icon="CHECKMARK") + row.operator("bim.disable_editing_application", icon="CANCEL", text="") + bonsai.bim.helper.draw_attributes(props.application_attributes, box) + else: + row = layout.row(align=True) + row.label(text=app_data["name"]) + op = row.operator("bim.enable_editing_application", icon="GREASEPENCIL", text="") + op.application_id = app_data["id"] + row.operator("bim.remove_application", icon="X", text="").application_id = app_data["id"] diff --git a/src/bonsai/bonsai/core/owner.py b/src/bonsai/bonsai/core/owner.py index da9f2847ad..f2dd366138 100644 --- a/src/bonsai/bonsai/core/owner.py +++ b/src/bonsai/bonsai/core/owner.py @@ -195,3 +195,24 @@ def unassign_actor( ifc: type[tool.Ifc], actor: ifcopenshell.entity_instance, element: ifcopenshell.entity_instance ) -> None: ifc.run("owner.unassign_actor", relating_actor=actor, related_object=element) + + +def enable_editing_application(owner: type[tool.Owner], application: ifcopenshell.entity_instance) -> None: + owner.set_application(application) + owner.import_application_attributes() + + +def disable_editing_application(owner: type[tool.Owner]) -> None: + owner.clear_application() + + +def edit_application(ifc: type[tool.Ifc], owner: type[tool.Owner]) -> None: + application = owner.get_application() + ifc.run("owner.edit_application", application=application, attributes=owner.export_application_attributes()) + owner.clear_application() + + +def add_application(ifc: type[tool.Ifc], owner: type[tool.Owner]) -> ifcopenshell.entity_instance: + application = ifc.run("owner.add_application") + enable_editing_application(owner, application) + return application diff --git a/src/bonsai/bonsai/tool/owner.py b/src/bonsai/bonsai/tool/owner.py index 19747c985c..2e6c0d3cdf 100644 --- a/src/bonsai/bonsai/tool/owner.py +++ b/src/bonsai/bonsai/tool/owner.py @@ -303,3 +303,34 @@ class Owner(bonsai.core.tool.Owner): def get_actor(cls) -> ifcopenshell.entity_instance: props = cls.get_owner_props() return tool.Ifc().get().by_id(props.active_actor_id) + + # Application. + @classmethod + def get_application(cls) -> ifcopenshell.entity_instance: + props = cls.get_owner_props() + return tool.Ifc.get().by_id(props.active_application_id) + + @classmethod + def set_application(cls, application: ifcopenshell.entity_instance) -> None: + props = cls.get_owner_props() + props.active_application_id = application.id() + + @classmethod + def clear_application(cls) -> None: + props = cls.get_owner_props() + if "active_application_id" in props: + del props["active_application_id"] + + @classmethod + def import_application_attributes(cls) -> None: + props = cls.get_owner_props() + application = tool.Ifc.get().by_id(props.active_application_id) + props.application_attributes.clear() + + bonsai.bim.helper.import_attributes("IfcApplication", props.application_attributes, application.get_info()) + + @classmethod + def export_application_attributes(cls) -> dict[str, Any]: + props = cls.get_owner_props() + attributes = bonsai.bim.helper.export_attributes(props.application_attributes) + return attributes