BlenderBIM Feature - Filter By Building Storey

This commit is contained in:
bosonprojets
2021-12-28 23:46:22 +01:00
parent ff4e58a8ff
commit 6e913a0ff9
4 changed files with 114 additions and 18 deletions
@@ -20,7 +20,8 @@ import bpy
from . import ui, prop, operator from . import ui, prop, operator
classes = ( classes = (
operator.ActivateIfcTypeFilter, operator.ActivateIfcClassFilter,
operator.ActivateIfcBuildingStoreyFilter,
operator.ColourByAttribute, operator.ColourByAttribute,
operator.ColourByClass, operator.ColourByClass,
operator.ColourByPset, operator.ColourByPset,
@@ -31,9 +32,11 @@ classes = (
operator.SelectIfcClass, operator.SelectIfcClass,
operator.SelectPset, operator.SelectPset,
prop.BIMFilterClasses, prop.BIMFilterClasses,
prop.BIMFilterBuildingStoreys,
prop.BIMSearchProperties, prop.BIMSearchProperties,
ui.BIM_PT_search, ui.BIM_PT_search,
ui.BIM_UL_ifctype_filter, ui.BIM_UL_ifc_class_filter,
ui.BIM_UL_ifc_building_storey_filter,
) )
@@ -321,29 +321,35 @@ class ResetObjectColours(bpy.types.Operator):
class ToggleFilterSelection(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_idname = "bim.toggle_filter_selection"
bl_label = "Toggle Filter Selection" bl_label = "Toggle Filter Selection"
action: bpy.props.EnumProperty(items=(("SELECT", "Select", ""), ("DESELECT", "Deselect", ""))) action: bpy.props.EnumProperty(items=(("SELECT", "Select", ""), ("DESELECT", "Deselect", "")))
def execute(self, context): def execute(self, context):
props = bpy.context.scene.BIMSearchProperties
if self.action == "SELECT": if self.action == "SELECT":
self.selecting_actionbool = True self.selecting_actionbool = True
else: else:
self.selecting_actionbool = False self.selecting_actionbool = False
for ifcelement in bpy.context.scene.BIMSearchProperties.filter_classes: if props.filter_type == "CLASSES":
ifcelement.is_selected = self.selecting_actionbool 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"} return {"FINISHED"}
class ActivateIfcTypeFilter(bpy.types.Operator): class ActivateIfcClassFilter(bpy.types.Operator):
"It helps you to filter your selection by IFC class" """Filter the current selection by IFC class"""
bl_idname = "bim.activate_ifc_type_filter"
bl_label = "Activate IfcType Filter" bl_idname = "bim.activate_ifc_class_filter"
bl_label = "Filter by Class"
def invoke(self, context, event): def invoke(self, context, event):
bpy.context.scene.BIMSearchProperties.filter_classes.clear() props = bpy.context.scene.BIMSearchProperties
props.filter_classes.clear()
ifc_types = {} ifc_types = {}
for obj in context.selected_objects: for obj in context.selected_objects:
element = tool.Ifc.get_entity(obj) element = tool.Ifc.get_entity(obj)
@@ -353,9 +359,10 @@ class ActivateIfcTypeFilter(bpy.types.Operator):
ifc_types[element.is_a()] += 1 ifc_types[element.is_a()] += 1
for name, total in dict(sorted(ifc_types.items())).items(): 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.name = name
new.total = total new.total = total
props.filter_type = "CLASSES"
return context.window_manager.invoke_props_dialog(self, width=250) return context.window_manager.invoke_props_dialog(self, width=250)
@@ -365,7 +372,7 @@ class ActivateIfcTypeFilter(bpy.types.Operator):
def draw(self, context): def draw(self, context):
self.layout.template_list( self.layout.template_list(
"BIM_UL_ifctype_filter", "BIM_UL_ifc_class_filter",
"", "",
context.scene.BIMSearchProperties, context.scene.BIMSearchProperties,
"filter_classes", "filter_classes",
@@ -378,3 +385,51 @@ class ActivateIfcTypeFilter(bpy.types.Operator):
row = self.layout.row(align=True) row = self.layout.row(align=True)
row.operator("bim.toggle_filter_selection", text="Select All").action = "SELECT" row.operator("bim.toggle_filter_selection", text="Select All").action = "SELECT"
row.operator("bim.toggle_filter_selection", text="Deselect All").action = "DESELECT" 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"
@@ -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: if self.is_selected:
for obj in self.unselected_objects: for obj in self.unselected_objects:
obj.obj.select_set(True) obj.obj.select_set(True)
@@ -46,10 +46,29 @@ def update_is_selected(self, context):
new = self.unselected_objects.add() new = self.unselected_objects.add()
new.obj = obj 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): class BIMFilterClasses(PropertyGroup):
name: StringProperty(name="Name") 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") total: IntProperty(name="Total")
unselected_objects: CollectionProperty(type=ObjProperty, name="Unfiltered Objects") unselected_objects: CollectionProperty(type=ObjProperty, name="Unfiltered Objects")
@@ -64,5 +83,8 @@ class BIMSearchProperties(PropertyGroup):
search_pset_name: StringProperty(name="Search Pset Name") search_pset_name: StringProperty(name="Search Pset Name")
search_prop_name: StringProperty(name="Search Prop Name") search_prop_name: StringProperty(name="Search Prop Name")
search_pset_value: StringProperty(name="Search Pset Value") search_pset_value: StringProperty(name="Search Pset Value")
filter_type: StringProperty(name="Filter Type")
filter_classes: CollectionProperty(type=BIMFilterClasses, name="Filter Classes") filter_classes: CollectionProperty(type=BIMFilterClasses, name="Filter Classes")
filter_classes_index: IntProperty(name="Filter Classes Index") 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")
@@ -67,11 +67,27 @@ class BIM_PT_search(Panel):
row.operator("bim.colour_by_pset", text="", icon="BRUSH_DATA") row.operator("bim.colour_by_pset", text="", icon="BRUSH_DATA")
row = self.layout.row(align=True) 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): class BIM_UL_ifc_class_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" 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") 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): def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):