Skip to content

Commit 6e913a0

Browse files
committed
BlenderBIM Feature - Filter By Building Storey
1 parent ff4e58a commit 6e913a0

4 files changed

Lines changed: 114 additions & 18 deletions

File tree

src/blenderbim/blenderbim/bim/module/search/__init__.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@
2020
from . import ui, prop, operator
2121

2222
classes = (
23-
operator.ActivateIfcTypeFilter,
23+
operator.ActivateIfcClassFilter,
24+
operator.ActivateIfcBuildingStoreyFilter,
2425
operator.ColourByAttribute,
2526
operator.ColourByClass,
2627
operator.ColourByPset,
@@ -31,9 +32,11 @@
3132
operator.SelectIfcClass,
3233
operator.SelectPset,
3334
prop.BIMFilterClasses,
35+
prop.BIMFilterBuildingStoreys,
3436
prop.BIMSearchProperties,
3537
ui.BIM_PT_search,
36-
ui.BIM_UL_ifctype_filter,
38+
ui.BIM_UL_ifc_class_filter,
39+
ui.BIM_UL_ifc_building_storey_filter,
3740
)
3841

3942

src/blenderbim/blenderbim/bim/module/search/operator.py

Lines changed: 66 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -321,29 +321,35 @@ def execute(self, context):
321321

322322

323323
class ToggleFilterSelection(bpy.types.Operator):
324-
"Click to select/deselect all ifctype"
324+
"Click to select/deselect current selection"
325325
bl_idname = "bim.toggle_filter_selection"
326326
bl_label = "Toggle Filter Selection"
327327
action: bpy.props.EnumProperty(items=(("SELECT", "Select", ""), ("DESELECT", "Deselect", "")))
328328

329329
def execute(self, context):
330+
props = bpy.context.scene.BIMSearchProperties
330331
if self.action == "SELECT":
331332
self.selecting_actionbool = True
332333
else:
333334
self.selecting_actionbool = False
334-
for ifcelement in bpy.context.scene.BIMSearchProperties.filter_classes:
335-
ifcelement.is_selected = self.selecting_actionbool
335+
if props.filter_type == "CLASSES":
336+
for ifc_class in props.filter_classes:
337+
ifc_class.is_selected = self.selecting_actionbool
338+
elif props.filter_type == "BUILDINGSTOREYS":
339+
for building_storey in props.filter_building_storeys:
340+
building_storey.is_selected = self.selecting_actionbool
336341
return {"FINISHED"}
337342

338343

339-
class ActivateIfcTypeFilter(bpy.types.Operator):
340-
"It helps you to filter your selection by IFC class"
341-
bl_idname = "bim.activate_ifc_type_filter"
342-
bl_label = "Activate IfcType Filter"
344+
class ActivateIfcClassFilter(bpy.types.Operator):
345+
"""Filter the current selection by IFC class"""
343346

344-
def invoke(self, context, event):
345-
bpy.context.scene.BIMSearchProperties.filter_classes.clear()
347+
bl_idname = "bim.activate_ifc_class_filter"
348+
bl_label = "Filter by Class"
346349

350+
def invoke(self, context, event):
351+
props = bpy.context.scene.BIMSearchProperties
352+
props.filter_classes.clear()
347353
ifc_types = {}
348354
for obj in context.selected_objects:
349355
element = tool.Ifc.get_entity(obj)
@@ -353,9 +359,10 @@ def invoke(self, context, event):
353359
ifc_types[element.is_a()] += 1
354360

355361
for name, total in dict(sorted(ifc_types.items())).items():
356-
new = context.scene.BIMSearchProperties.filter_classes.add()
362+
new = props.filter_classes.add()
357363
new.name = name
358364
new.total = total
365+
props.filter_type = "CLASSES"
359366

360367
return context.window_manager.invoke_props_dialog(self, width=250)
361368

@@ -365,7 +372,7 @@ def execute(self, context):
365372

366373
def draw(self, context):
367374
self.layout.template_list(
368-
"BIM_UL_ifctype_filter",
375+
"BIM_UL_ifc_class_filter",
369376
"",
370377
context.scene.BIMSearchProperties,
371378
"filter_classes",
@@ -378,3 +385,51 @@ def draw(self, context):
378385
row = self.layout.row(align=True)
379386
row.operator("bim.toggle_filter_selection", text="Select All").action = "SELECT"
380387
row.operator("bim.toggle_filter_selection", text="Deselect All").action = "DESELECT"
388+
389+
390+
class ActivateIfcBuildingStoreyFilter(bpy.types.Operator):
391+
"""Filter the current selection by Building Storey"""
392+
393+
bl_idname = "bim.activate_ifc_building_storey_filter"
394+
bl_label = "Filter by Building Storey"
395+
396+
def invoke(self, context, event):
397+
props = bpy.context.scene.BIMSearchProperties
398+
props.filter_building_storeys.clear()
399+
400+
ifc_building_storeys = {}
401+
for obj in context.selected_objects:
402+
storey = tool.Misc.get_object_storey(obj)
403+
if not storey:
404+
continue
405+
ifc_building_storeys.setdefault(storey.Name, 0)
406+
ifc_building_storeys[storey.Name] += 1
407+
408+
for name, total in dict(sorted(ifc_building_storeys.items())).items():
409+
new = props.filter_building_storeys.add()
410+
new.name = name
411+
new.total = total
412+
413+
props.filter_type = "BUILDINGSTOREYS"
414+
415+
return context.window_manager.invoke_props_dialog(self, width=250)
416+
417+
def execute(self, context):
418+
bpy.context.scene.BIMSearchProperties.filter_building_storeys.clear()
419+
return {"FINISHED"}
420+
421+
def draw(self, context):
422+
self.layout.template_list(
423+
"BIM_UL_ifc_building_storey_filter",
424+
"",
425+
context.scene.BIMSearchProperties,
426+
"filter_building_storeys",
427+
context.scene.BIMSearchProperties,
428+
"filter_building_storeys_index",
429+
rows=20
430+
if len(bpy.context.scene.BIMSearchProperties.filter_building_storeys) > 20
431+
else len(bpy.context.scene.BIMSearchProperties.filter_building_storeys),
432+
)
433+
row = self.layout.row(align=True)
434+
row.operator("bim.toggle_filter_selection", text="Select All").action = "SELECT"
435+
row.operator("bim.toggle_filter_selection", text="Deselect All").action = "DESELECT"

src/blenderbim/blenderbim/bim/module/search/prop.py

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
)
3434

3535

36-
def update_is_selected(self, context):
36+
def update_is_class_selected(self, context):
3737
if self.is_selected:
3838
for obj in self.unselected_objects:
3939
obj.obj.select_set(True)
@@ -46,10 +46,29 @@ def update_is_selected(self, context):
4646
new = self.unselected_objects.add()
4747
new.obj = obj
4848

49+
def update_is_level_selected(self, context):
50+
if self.is_selected:
51+
for obj in self.unselected_objects:
52+
obj.obj.select_set(True)
53+
self.unselected_objects.clear()
54+
else:
55+
for obj in context.selected_objects:
56+
level = tool.Misc.get_object_storey(obj)
57+
if level and level.Name == self.name:
58+
obj.select_set(False)
59+
new = self.unselected_objects.add()
60+
new.obj = obj
4961

5062
class BIMFilterClasses(PropertyGroup):
5163
name: StringProperty(name="Name")
52-
is_selected: BoolProperty(name="Is Selected", default=True, update=update_is_selected)
64+
is_selected: BoolProperty(name="Is Selected", default=True, update=update_is_class_selected)
65+
total: IntProperty(name="Total")
66+
unselected_objects: CollectionProperty(type=ObjProperty, name="Unfiltered Objects")
67+
68+
69+
class BIMFilterBuildingStoreys(PropertyGroup):
70+
name: StringProperty(name="Name")
71+
is_selected: BoolProperty(name="Is Level Selected", default=True, update=update_is_level_selected)
5372
total: IntProperty(name="Total")
5473
unselected_objects: CollectionProperty(type=ObjProperty, name="Unfiltered Objects")
5574

@@ -64,5 +83,8 @@ class BIMSearchProperties(PropertyGroup):
6483
search_pset_name: StringProperty(name="Search Pset Name")
6584
search_prop_name: StringProperty(name="Search Prop Name")
6685
search_pset_value: StringProperty(name="Search Pset Value")
86+
filter_type: StringProperty(name="Filter Type")
6787
filter_classes: CollectionProperty(type=BIMFilterClasses, name="Filter Classes")
6888
filter_classes_index: IntProperty(name="Filter Classes Index")
89+
filter_building_storeys: CollectionProperty(type=BIMFilterBuildingStoreys, name="Filter Level")
90+
filter_building_storeys_index: IntProperty(name="Filter Level Index")

src/blenderbim/blenderbim/bim/module/search/ui.py

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,11 +67,27 @@ def draw(self, context):
6767
row.operator("bim.colour_by_pset", text="", icon="BRUSH_DATA")
6868

6969
row = self.layout.row(align=True)
70-
row.operator("bim.activate_ifc_type_filter", icon="FILTER")
70+
row.operator("bim.activate_ifc_class_filter", icon="FILTER")
71+
row.operator("bim.activate_ifc_building_storey_filter", icon="FILTER")
7172

7273

73-
class BIM_UL_ifctype_filter(bpy.types.UIList):
74-
"This UI List is to list out all the selected IfcType and number of it as well as providing the BoolProperty to select/deselect"
74+
class BIM_UL_ifc_class_filter(bpy.types.UIList):
75+
use_filter_linked: bpy.props.BoolProperty(name="Included", default=True, options=set(), description="Filter")
76+
77+
def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
78+
split = layout
79+
split.use_property_split = True
80+
split.use_property_decorate = False
81+
split.prop(
82+
item, "is_selected", text="", emboss=False, icon="CHECKBOX_HLT" if item.is_selected else "CHECKBOX_DEHLT"
83+
)
84+
split.prop(item, "name", text="", emboss=False, slider=True)
85+
split = split.column()
86+
split.scale_x = 0.5
87+
split.label(text=str(item.total))
88+
89+
90+
class BIM_UL_ifc_building_storey_filter(bpy.types.UIList):
7591
use_filter_linked: bpy.props.BoolProperty(name="Included", default=True, options=set(), description="Filter")
7692

7793
def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):

0 commit comments

Comments
 (0)