From 6e913a0ff9e64adb51b58df461a4fcd49db4c5ca Mon Sep 17 00:00:00 2001 From: bosonprojets Date: Tue, 28 Dec 2021 23:46:22 +0100 Subject: [PATCH] BlenderBIM Feature - Filter By Building Storey --- .../blenderbim/bim/module/search/__init__.py | 7 +- .../blenderbim/bim/module/search/operator.py | 77 ++++++++++++++++--- .../blenderbim/bim/module/search/prop.py | 26 ++++++- .../blenderbim/bim/module/search/ui.py | 22 +++++- 4 files changed, 114 insertions(+), 18 deletions(-) diff --git a/src/blenderbim/blenderbim/bim/module/search/__init__.py b/src/blenderbim/blenderbim/bim/module/search/__init__.py index 4bfd3ca7f0..df128b9a9e 100644 --- a/src/blenderbim/blenderbim/bim/module/search/__init__.py +++ b/src/blenderbim/blenderbim/bim/module/search/__init__.py @@ -20,7 +20,8 @@ import bpy from . import ui, prop, operator classes = ( - operator.ActivateIfcTypeFilter, + operator.ActivateIfcClassFilter, + operator.ActivateIfcBuildingStoreyFilter, operator.ColourByAttribute, operator.ColourByClass, operator.ColourByPset, @@ -31,9 +32,11 @@ classes = ( operator.SelectIfcClass, operator.SelectPset, prop.BIMFilterClasses, + prop.BIMFilterBuildingStoreys, prop.BIMSearchProperties, ui.BIM_PT_search, - ui.BIM_UL_ifctype_filter, + ui.BIM_UL_ifc_class_filter, + ui.BIM_UL_ifc_building_storey_filter, ) diff --git a/src/blenderbim/blenderbim/bim/module/search/operator.py b/src/blenderbim/blenderbim/bim/module/search/operator.py index 1b20ba07cb..cd4365289e 100644 --- a/src/blenderbim/blenderbim/bim/module/search/operator.py +++ b/src/blenderbim/blenderbim/bim/module/search/operator.py @@ -321,29 +321,35 @@ class ResetObjectColours(bpy.types.Operator): class ToggleFilterSelection(bpy.types.Operator): - "Click to select/deselect all ifctype" + "Click to select/deselect current selection" bl_idname = "bim.toggle_filter_selection" bl_label = "Toggle Filter Selection" action: bpy.props.EnumProperty(items=(("SELECT", "Select", ""), ("DESELECT", "Deselect", ""))) def execute(self, context): + props = bpy.context.scene.BIMSearchProperties if self.action == "SELECT": self.selecting_actionbool = True else: self.selecting_actionbool = False - for ifcelement in bpy.context.scene.BIMSearchProperties.filter_classes: - ifcelement.is_selected = self.selecting_actionbool + if props.filter_type == "CLASSES": + for ifc_class in props.filter_classes: + ifc_class.is_selected = self.selecting_actionbool + elif props.filter_type == "BUILDINGSTOREYS": + for building_storey in props.filter_building_storeys: + building_storey.is_selected = self.selecting_actionbool return {"FINISHED"} -class ActivateIfcTypeFilter(bpy.types.Operator): - "It helps you to filter your selection by IFC class" - bl_idname = "bim.activate_ifc_type_filter" - bl_label = "Activate IfcType Filter" +class ActivateIfcClassFilter(bpy.types.Operator): + """Filter the current selection by IFC class""" + + bl_idname = "bim.activate_ifc_class_filter" + bl_label = "Filter by Class" def invoke(self, context, event): - bpy.context.scene.BIMSearchProperties.filter_classes.clear() - + props = bpy.context.scene.BIMSearchProperties + props.filter_classes.clear() ifc_types = {} for obj in context.selected_objects: element = tool.Ifc.get_entity(obj) @@ -353,9 +359,10 @@ class ActivateIfcTypeFilter(bpy.types.Operator): ifc_types[element.is_a()] += 1 for name, total in dict(sorted(ifc_types.items())).items(): - new = context.scene.BIMSearchProperties.filter_classes.add() + new = props.filter_classes.add() new.name = name new.total = total + props.filter_type = "CLASSES" return context.window_manager.invoke_props_dialog(self, width=250) @@ -365,7 +372,7 @@ class ActivateIfcTypeFilter(bpy.types.Operator): def draw(self, context): self.layout.template_list( - "BIM_UL_ifctype_filter", + "BIM_UL_ifc_class_filter", "", context.scene.BIMSearchProperties, "filter_classes", @@ -378,3 +385,51 @@ class ActivateIfcTypeFilter(bpy.types.Operator): row = self.layout.row(align=True) row.operator("bim.toggle_filter_selection", text="Select All").action = "SELECT" row.operator("bim.toggle_filter_selection", text="Deselect All").action = "DESELECT" + + +class ActivateIfcBuildingStoreyFilter(bpy.types.Operator): + """Filter the current selection by Building Storey""" + + bl_idname = "bim.activate_ifc_building_storey_filter" + bl_label = "Filter by Building Storey" + + def invoke(self, context, event): + props = bpy.context.scene.BIMSearchProperties + props.filter_building_storeys.clear() + + ifc_building_storeys = {} + for obj in context.selected_objects: + storey = tool.Misc.get_object_storey(obj) + if not storey: + continue + ifc_building_storeys.setdefault(storey.Name, 0) + ifc_building_storeys[storey.Name] += 1 + + for name, total in dict(sorted(ifc_building_storeys.items())).items(): + new = props.filter_building_storeys.add() + new.name = name + new.total = total + + props.filter_type = "BUILDINGSTOREYS" + + return context.window_manager.invoke_props_dialog(self, width=250) + + def execute(self, context): + bpy.context.scene.BIMSearchProperties.filter_building_storeys.clear() + return {"FINISHED"} + + def draw(self, context): + self.layout.template_list( + "BIM_UL_ifc_building_storey_filter", + "", + context.scene.BIMSearchProperties, + "filter_building_storeys", + context.scene.BIMSearchProperties, + "filter_building_storeys_index", + rows=20 + if len(bpy.context.scene.BIMSearchProperties.filter_building_storeys) > 20 + else len(bpy.context.scene.BIMSearchProperties.filter_building_storeys), + ) + row = self.layout.row(align=True) + row.operator("bim.toggle_filter_selection", text="Select All").action = "SELECT" + row.operator("bim.toggle_filter_selection", text="Deselect All").action = "DESELECT" diff --git a/src/blenderbim/blenderbim/bim/module/search/prop.py b/src/blenderbim/blenderbim/bim/module/search/prop.py index 5efb411845..ccd848d62d 100644 --- a/src/blenderbim/blenderbim/bim/module/search/prop.py +++ b/src/blenderbim/blenderbim/bim/module/search/prop.py @@ -33,7 +33,7 @@ from bpy.props import ( ) -def update_is_selected(self, context): +def update_is_class_selected(self, context): if self.is_selected: for obj in self.unselected_objects: obj.obj.select_set(True) @@ -46,10 +46,29 @@ def update_is_selected(self, context): new = self.unselected_objects.add() new.obj = obj +def update_is_level_selected(self, context): + if self.is_selected: + for obj in self.unselected_objects: + obj.obj.select_set(True) + self.unselected_objects.clear() + else: + for obj in context.selected_objects: + level = tool.Misc.get_object_storey(obj) + if level and level.Name == self.name: + obj.select_set(False) + new = self.unselected_objects.add() + new.obj = obj class BIMFilterClasses(PropertyGroup): name: StringProperty(name="Name") - is_selected: BoolProperty(name="Is Selected", default=True, update=update_is_selected) + is_selected: BoolProperty(name="Is Selected", default=True, update=update_is_class_selected) + total: IntProperty(name="Total") + unselected_objects: CollectionProperty(type=ObjProperty, name="Unfiltered Objects") + + +class BIMFilterBuildingStoreys(PropertyGroup): + name: StringProperty(name="Name") + is_selected: BoolProperty(name="Is Level Selected", default=True, update=update_is_level_selected) total: IntProperty(name="Total") unselected_objects: CollectionProperty(type=ObjProperty, name="Unfiltered Objects") @@ -64,5 +83,8 @@ class BIMSearchProperties(PropertyGroup): search_pset_name: StringProperty(name="Search Pset Name") search_prop_name: StringProperty(name="Search Prop Name") search_pset_value: StringProperty(name="Search Pset Value") + filter_type: StringProperty(name="Filter Type") filter_classes: CollectionProperty(type=BIMFilterClasses, name="Filter Classes") filter_classes_index: IntProperty(name="Filter Classes Index") + filter_building_storeys: CollectionProperty(type=BIMFilterBuildingStoreys, name="Filter Level") + filter_building_storeys_index: IntProperty(name="Filter Level Index") diff --git a/src/blenderbim/blenderbim/bim/module/search/ui.py b/src/blenderbim/blenderbim/bim/module/search/ui.py index 2b25a5e4d4..f2dfdd1318 100644 --- a/src/blenderbim/blenderbim/bim/module/search/ui.py +++ b/src/blenderbim/blenderbim/bim/module/search/ui.py @@ -67,11 +67,27 @@ class BIM_PT_search(Panel): row.operator("bim.colour_by_pset", text="", icon="BRUSH_DATA") row = self.layout.row(align=True) - row.operator("bim.activate_ifc_type_filter", icon="FILTER") + row.operator("bim.activate_ifc_class_filter", icon="FILTER") + row.operator("bim.activate_ifc_building_storey_filter", icon="FILTER") -class BIM_UL_ifctype_filter(bpy.types.UIList): - "This UI List is to list out all the selected IfcType and number of it as well as providing the BoolProperty to select/deselect" +class BIM_UL_ifc_class_filter(bpy.types.UIList): + use_filter_linked: bpy.props.BoolProperty(name="Included", default=True, options=set(), description="Filter") + + def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index): + split = layout + split.use_property_split = True + split.use_property_decorate = False + split.prop( + item, "is_selected", text="", emboss=False, icon="CHECKBOX_HLT" if item.is_selected else "CHECKBOX_DEHLT" + ) + split.prop(item, "name", text="", emboss=False, slider=True) + split = split.column() + split.scale_x = 0.5 + split.label(text=str(item.total)) + + +class BIM_UL_ifc_building_storey_filter(bpy.types.UIList): use_filter_linked: bpy.props.BoolProperty(name="Included", default=True, options=set(), description="Filter") def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):