From 1066e5e0a71be6a1604a91a5f6863d5c1c08fcd9 Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Tue, 31 Jan 2023 17:35:54 +1100 Subject: [PATCH] See #1848. Refactor layer data class. --- .../blenderbim/bim/module/layer/data.py | 53 +++++++++++++++++++ .../blenderbim/bim/module/layer/operator.py | 18 ++----- .../blenderbim/bim/module/layer/ui.py | 13 ++--- .../test/bim/feature/system.feature | 3 ++ 4 files changed, 65 insertions(+), 22 deletions(-) create mode 100644 src/blenderbim/blenderbim/bim/module/layer/data.py diff --git a/src/blenderbim/blenderbim/bim/module/layer/data.py b/src/blenderbim/blenderbim/bim/module/layer/data.py new file mode 100644 index 0000000000..8c9cc2142c --- /dev/null +++ b/src/blenderbim/blenderbim/bim/module/layer/data.py @@ -0,0 +1,53 @@ +# BlenderBIM Add-on - OpenBIM Blender Add-on +# Copyright (C) 2023 Dion Moult +# +# This file is part of BlenderBIM Add-on. +# +# BlenderBIM Add-on is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# BlenderBIM Add-on is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with BlenderBIM Add-on. If not, see . + +import bpy +import ifcopenshell +import blenderbim.tool as tool + + +def refresh(): + LayersData.is_loaded = False + + +class LayersData: + data = {} + is_loaded = False + + @classmethod + def load(cls): + cls.data = {"total_layers": cls.total_layers(), "active_layers": cls.active_layers()} + cls.is_loaded = True + + @classmethod + def total_layers(cls): + return len(tool.Ifc.get().by_type("IfcPresentationLayerAssignment")) + + @classmethod + def active_layers(cls): + data = bpy.context.active_object.data + if not data: + return [] + if not isinstance(data, bpy.types.Mesh) or not data.BIMMeshProperties.ifc_definition_id: + return [] + results = [] + shape = tool.Ifc.get().by_id(data.BIMMeshProperties.ifc_definition_id) + for inverse in tool.Ifc.get().get_inverse(shape): + if inverse.is_a("IfcPresentationLayerAssignment"): + results.append(inverse.id()) + return results diff --git a/src/blenderbim/blenderbim/bim/module/layer/operator.py b/src/blenderbim/blenderbim/bim/module/layer/operator.py index a28d446904..32f4888639 100644 --- a/src/blenderbim/blenderbim/bim/module/layer/operator.py +++ b/src/blenderbim/blenderbim/bim/module/layer/operator.py @@ -24,7 +24,6 @@ import ifcopenshell.util.attribute import blenderbim.bim.helper import blenderbim.tool as tool from blenderbim.bim.ifc import IfcStore -from ifcopenshell.api.layer.data import Data class LoadLayers(bpy.types.Operator): @@ -36,10 +35,10 @@ class LoadLayers(bpy.types.Operator): self.file = IfcStore.get_file() props = context.scene.BIMLayerProperties props.layers.clear() - for layer_id, layer in Data.layers.items(): + for layer in tool.Ifc.get().by_type("IfcPresentationLayerAssignment"): new = props.layers.add() - new.name = layer["Name"] or "Unnamed" - new.ifc_definition_id = layer_id + new.name = layer.Name or "Unnamed" + new.ifc_definition_id = layer.id() props.is_editing = True bpy.ops.bim.disable_editing_layer() return {"FINISHED"} @@ -64,11 +63,7 @@ class EnableEditingLayer(bpy.types.Operator): def execute(self, context): props = context.scene.BIMLayerProperties props.layer_attributes.clear() - - blenderbim.bim.helper.import_attributes( - "IfcPresentationLayerAssignment", props.layer_attributes, Data.layers[self.layer] - ) - + blenderbim.bim.helper.import_attributes(tool.Ifc.get().by_id(self.layer), props.layer_attributes) props.active_layer_id = self.layer return {"FINISHED"} @@ -93,7 +88,6 @@ class AddPresentationLayer(bpy.types.Operator): def _execute(self, context): result = ifcopenshell.api.run("layer.add_layer", IfcStore.get_file()) - Data.load(IfcStore.get_file()) bpy.ops.bim.load_layers() bpy.ops.bim.enable_editing_layer(layer=result.id()) return {"FINISHED"} @@ -119,7 +113,6 @@ class EditPresentationLayer(bpy.types.Operator): ifcopenshell.api.run( "layer.edit_layer", self.file, **{"layer": self.file.by_id(props.active_layer_id), "attributes": attributes} ) - Data.load(IfcStore.get_file()) bpy.ops.bim.load_layers() return {"FINISHED"} @@ -137,7 +130,6 @@ class RemovePresentationLayer(bpy.types.Operator): props = context.scene.BIMLayerProperties self.file = IfcStore.get_file() ifcopenshell.api.run("layer.remove_layer", self.file, **{"layer": self.file.by_id(self.layer)}) - Data.load(IfcStore.get_file()) bpy.ops.bim.load_layers() return {"FINISHED"} @@ -160,7 +152,6 @@ class AssignPresentationLayer(bpy.types.Operator): self.file, **{"item": self.file.by_id(item.BIMMeshProperties.ifc_definition_id), "layer": self.file.by_id(self.layer)} ) - Data.load(IfcStore.get_file()) return {"FINISHED"} @@ -182,7 +173,6 @@ class UnassignPresentationLayer(bpy.types.Operator): self.file, **{"item": self.file.by_id(item.BIMMeshProperties.ifc_definition_id), "layer": self.file.by_id(self.layer)} ) - Data.load(IfcStore.get_file()) return {"FINISHED"} diff --git a/src/blenderbim/blenderbim/bim/module/layer/ui.py b/src/blenderbim/blenderbim/bim/module/layer/ui.py index f86c4dbf63..179ea568a2 100644 --- a/src/blenderbim/blenderbim/bim/module/layer/ui.py +++ b/src/blenderbim/blenderbim/bim/module/layer/ui.py @@ -18,7 +18,7 @@ from bpy.types import Panel, UIList, Mesh from blenderbim.bim.ifc import IfcStore -from ifcopenshell.api.layer.data import Data +from blenderbim.bim.module.layer.data import LayersData class BIM_PT_layers(Panel): @@ -35,13 +35,13 @@ class BIM_PT_layers(Panel): return IfcStore.get_file() def draw(self, context): - if not Data.is_loaded: - Data.load(IfcStore.get_file()) + if not LayersData.is_loaded: + LayersData.load() self.props = context.scene.BIMLayerProperties row = self.layout.row(align=True) - row.label(text="{} Layers Found".format(len(Data.layers.keys()))) + row.label(text=f"{LayersData.data['total_layers']} Layers Found") if self.props.is_editing: row.operator("bim.add_presentation_layer", text="", icon="ADD") row.operator("bim.disable_layer_editing_ui", text="", icon="CANCEL") @@ -77,10 +77,7 @@ class BIM_UL_layers(UIList): if context.active_object and isinstance(context.active_object.data, Mesh): mprops = context.active_object.data.BIMMeshProperties - if ( - mprops.ifc_definition_id in Data.items - and item.ifc_definition_id in Data.items[mprops.ifc_definition_id] - ): + if item.ifc_definition_id in LayersData.data["active_layers"]: op = row.operator("bim.unassign_presentation_layer", text="", icon="KEYFRAME_HLT", emboss=False) op.layer = item.ifc_definition_id else: diff --git a/src/blenderbim/test/bim/feature/system.feature b/src/blenderbim/test/bim/feature/system.feature index 1b7143fe63..a9ae5756e9 100644 --- a/src/blenderbim/test/bim/feature/system.feature +++ b/src/blenderbim/test/bim/feature/system.feature @@ -55,6 +55,7 @@ Scenario: Disable editing system Scenario: Assign system Given an empty IFC project And I press "bim.load_systems" + And I set "scene.BIMSystemProperties.system_class" to "IfcDistributionSystem" And I press "bim.add_system" And the variable "system" is "{ifc}.by_type('IfcSystem')[0].id()" And I press "bim.enable_editing_system(system={system})" @@ -69,6 +70,7 @@ Scenario: Assign system Scenario: Unassign system Given an empty IFC project And I press "bim.load_systems" + And I set "scene.BIMSystemProperties.system_class" to "IfcDistributionSystem" And I press "bim.add_system" And the variable "system" is "{ifc}.by_type('IfcSystem')[0].id()" And I press "bim.enable_editing_system(system={system})" @@ -84,6 +86,7 @@ Scenario: Unassign system Scenario: Select system products Given an empty IFC project And I press "bim.load_systems" + And I set "scene.BIMSystemProperties.system_class" to "IfcDistributionSystem" And I press "bim.add_system" And the variable "system" is "{ifc}.by_type('IfcSystem')[0].id()" And I press "bim.enable_editing_system(system={system})"