Code review for Ifc Type filter feature. See #1823.

This commit is contained in:
Dion Moult
2021-10-25 20:12:36 +11:00
parent 41afb26d31
commit 1a84967b1b
6 changed files with 83 additions and 114 deletions
@@ -85,6 +85,7 @@ classes = [
operator.RemoveIfcFile, operator.RemoveIfcFile,
operator.ConfigureVisibility, operator.ConfigureVisibility,
prop.StrProperty, prop.StrProperty,
prop.ObjProperty,
prop.Attribute, prop.Attribute,
prop.ModuleVisibility, prop.ModuleVisibility,
prop.BIMProperties, prop.BIMProperties,
@@ -20,28 +20,25 @@ import bpy
from . import ui, prop, operator from . import ui, prop, operator
classes = ( classes = (
operator.ActivateIfcTypeFilter,
operator.ColourByAttribute,
operator.ColourByClass,
operator.ColourByPset,
operator.ResetObjectColours,
operator.SelectAttribute,
operator.SelectGlobalId, operator.SelectGlobalId,
operator.SelectIfcClass, operator.SelectIfcClass,
operator.SelectAttribute,
operator.SelectPset, operator.SelectPset,
operator.ColourByAttribute, prop.BIMFilterClasses,
operator.ColourByPset,
operator.ColourByClass,
operator.ResetObjectColours,
prop.BIMSearchProperties, prop.BIMSearchProperties,
ui.BIM_PT_search, ui.BIM_PT_search,
#ifcType Filter ui.BIM_UL_ifctype_filter,
operator.BIM_UL_ifctype_filter,
operator.BIM_OT_ifctype_filter,
prop.BIMIfcTypeFilterProperties
) )
def register(): def register():
bpy.types.Scene.BIMSearchProperties = bpy.props.PointerProperty(type=prop.BIMSearchProperties) bpy.types.Scene.BIMSearchProperties = bpy.props.PointerProperty(type=prop.BIMSearchProperties)
bpy.types.Scene.BIM_IfcTypeFilter_collprops = bpy.props.CollectionProperty(type=prop.BIMIfcTypeFilterProperties)
bpy.types.Scene.BIM_IfcTypeFilter_int = bpy.props.IntProperty()
def unregister(): def unregister():
del bpy.types.Scene.BIMSearchProperties del bpy.types.Scene.BIMSearchProperties
del bpy.types.Scene.BIM_IfcTypeFilter_collprops
del bpy.types.Scene.BIM_IfcTypeFilter_int
@@ -20,6 +20,7 @@ import re
import bpy import bpy
import ifcopenshell import ifcopenshell
import ifcopenshell.util.element import ifcopenshell.util.element
import blenderbim.tool as tool
from blenderbim.bim.ifc import IfcStore from blenderbim.bim.ifc import IfcStore
from itertools import cycle from itertools import cycle
@@ -321,105 +322,40 @@ class ResetObjectColours(bpy.types.Operator):
obj.color = (1, 1, 1, 1) obj.color = (1, 1, 1, 1)
return {"FINISHED"} return {"FINISHED"}
# -------------------------------------------------------------------
# IfcType Filter
# -------------------------------------------------------------------
def BIM_ifctypefilterupdate(self, context): #Trigger action
typename = self.typename
typebool = self.typebool
typenum = self.typenum
if typebool == False:
action = "deselecting"
else:
action = "selecting"
print(f"{action} {typenum} {typename} ")
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"
for ele,ifctype in elementsDict.items():
if typename == ifctype:
if typebool == False:
ele.select_set(False)
else:
ele.select_set(True)
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"
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):
#layout.prop(self, "use_filter_linked", text="", icon="ADD")
#layout.prop(item, "name", text="",emboss=False,toggle=True, icon="CON_ROTLIKE")
#split = layout.split(factor=0.1)
split= layout
split.use_property_split = True
split.use_property_decorate = False
#split.label(text=a[0])
#split.label(text=item.name)
split.prop(item, 'typebool', text="",icon="ADD")
split.prop(item, 'typename', text="",emboss=False, slider=True)
split = split.column()
split.scale_x=0.5
split.prop(item, 'typenum', text="",emboss=False)
class BIM_OT_ifctype_filter(bpy.types.Operator):
"Click to activate IfcType Filter. It helps you to filter out IfcType with current selection"
bl_idname = "bim.ifctype_filter"
bl_label = "IfcType Filter"
def invoke(self, context, event): def invoke(self, context, event):
print(f"{self.bl_label} Activated") bpy.context.scene.BIMSearchProperties.filter_classes.clear()
#clear collection property data
try:
bpy.context.scene.BIM_IfcTypeFilter_collprops.clear()
except:
pass
self.importedIfcFile = IfcStore.get_file()
#Preparing IFC infomation ifc_types = {}
elements = bpy.context.selected_objects #Get selected objects for obj in context.selected_objects:
eleIfcTypeList = [] element = tool.Ifc.get_entity(obj)
for ele in elements: #Get elements IfcType if not element:
eleAttr = self.importedIfcFile.by_id(ele.BIMObjectProperties.ifc_definition_id) continue
eleIfcTypeList.append(eleAttr.get_info()["type"]) ifc_types.setdefault(element.is_a(), 0)
ifc_types[element.is_a()] += 1
#use global to let BIM_ifctypefilterupdate function grabs the user selection for name, total in ifc_types.items():
global elementsDict new = context.scene.BIMSearchProperties.filter_classes.add()
elementsDict={} new.name = name
for ele, type in zip(elements, eleIfcTypeList): new.total = total
elementsDict[ele] = type
#use global to let draw function grabs the user selection return context.window_manager.invoke_props_dialog(self, width=250)
global ifcTypeUniqueList
ifcTypeUniqueList =sorted(list(set((eleIfcTypeList))))
ifcTypeUniqueCount = []
for type in ifcTypeUniqueList:
ifcTypeUniqueCount.append(eleIfcTypeList.count(type))
#adding IfcType name into collection property
for type,count in zip(ifcTypeUniqueList,ifcTypeUniqueCount):
BIM_IfcTypeFilter_item = bpy.context.scene.BIM_IfcTypeFilter_collprops.add()
BIM_IfcTypeFilter_item.typename = type
BIM_IfcTypeFilter_item.typenum = str(count)
return context.window_manager.invoke_props_dialog(self, width = 250)
def execute(self, context): #This def will execute after clicking OK def execute(self, context):
print(f"{self.bl_label} Closed") bpy.context.scene.BIMSearchProperties.filter_classes.clear()
bpy.context.scene.BIM_IfcTypeFilter_collprops.clear() return {"FINISHED"}
return {'FINISHED'}
def draw(self, context): def draw(self, context):
layout = self.layout self.layout.template_list(
scn = context.scene
if len(ifcTypeUniqueList) > 20:
rowsNum = 20
else:
rowsNum = len(ifcTypeUniqueList)
layout.template_list(
"BIM_UL_ifctype_filter", "BIM_UL_ifctype_filter",
"", "",
scn, context.scene.BIMSearchProperties,
"BIM_IfcTypeFilter_collprops", "filter_classes",
scn, context.scene.BIMSearchProperties,
"BIM_IfcTypeFilter_int", "filter_classes_index",
rows = rowsNum )
)
@@ -17,6 +17,8 @@
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>. # along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
import bpy import bpy
import blenderbim.tool as tool
from blenderbim.bim.prop import ObjProperty
from bpy.types import PropertyGroup from bpy.types import PropertyGroup
from . import ui, prop, operator from . import ui, prop, operator
from bpy.props import ( from bpy.props import (
@@ -31,6 +33,27 @@ from bpy.props import (
) )
def update_is_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:
element = tool.Ifc.get_entity(obj)
if element and element.is_a() == 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)
total: IntProperty(name="Total")
unselected_objects: CollectionProperty(type=ObjProperty, name="Unfiltered Objects")
class BIMSearchProperties(PropertyGroup): class BIMSearchProperties(PropertyGroup):
should_use_regex: BoolProperty(name="Search With Regex", default=False) should_use_regex: BoolProperty(name="Search With Regex", default=False)
should_ignorecase: BoolProperty(name="Search Ignoring Case", default=True) should_ignorecase: BoolProperty(name="Search Ignoring Case", default=True)
@@ -41,11 +64,5 @@ 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_classes: CollectionProperty(type=BIMFilterClasses, name="Filter Classes")
# ------------------------------------------------------------------- filter_classes_index: IntProperty(name="Filter Classes Index")
# IfcType Filter
# -------------------------------------------------------------------
class BIMIfcTypeFilterProperties(PropertyGroup):
typename: StringProperty()
typebool: BoolProperty(default=True, update=operator.BIM_ifctypefilterupdate)
typenum: StringProperty()
@@ -66,6 +66,20 @@ class BIM_PT_search(Panel):
row.operator("bim.select_pset", text="", icon="VIEWZOOM") row.operator("bim.select_pset", text="", icon="VIEWZOOM")
row.operator("bim.colour_by_pset", text="", icon="BRUSH_DATA") row.operator("bim.colour_by_pset", text="", icon="BRUSH_DATA")
#IfcType Filter
row = self.layout.row(align=True) row = self.layout.row(align=True)
row.operator("bim.ifctype_filter",icon = "FILTER") row.operator("bim.activate_ifc_type_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"
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="", icon="ADD" if item.is_selected else "REMOVE")
split.prop(item, "name", text="", emboss=False, slider=True)
split = split.column()
split.scale_x = 0.5
split.prop(item, "total", text="", emboss=False)
+4
View File
@@ -123,6 +123,10 @@ class StrProperty(PropertyGroup):
pass pass
class ObjProperty(PropertyGroup):
obj: bpy.props.PointerProperty(type=bpy.types.Object)
def updateAttributeValue(self, context): def updateAttributeValue(self, context):
value_name = self.get_value_name() value_name = self.get_value_name()
if value_name: if value_name: