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):
for ele,ifctype in elementsDict.items(): "It helps you to filter your selection by IFC class"
if typename == ifctype: bl_idname = "bim.activate_ifc_type_filter"
if typebool == False: bl_label = "Activate IfcType Filter"
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() ifc_types = {}
for obj in context.selected_objects:
element = tool.Ifc.get_entity(obj)
if not element:
continue
ifc_types.setdefault(element.is_a(), 0)
ifc_types[element.is_a()] += 1
#Preparing IFC infomation for name, total in ifc_types.items():
elements = bpy.context.selected_objects #Get selected objects new = context.scene.BIMSearchProperties.filter_classes.add()
eleIfcTypeList = [] new.name = name
for ele in elements: #Get elements IfcType new.total = total
eleAttr = self.importedIfcFile.by_id(ele.BIMObjectProperties.ifc_definition_id)
eleIfcTypeList.append(eleAttr.get_info()["type"])
#use global to let BIM_ifctypefilterupdate function grabs the user selection return context.window_manager.invoke_props_dialog(self, width=250)
global elementsDict
elementsDict={}
for ele, type in zip(elements, eleIfcTypeList):
elementsDict[ele] = type
#use global to let draw function grabs the user selection def execute(self, context):
global ifcTypeUniqueList bpy.context.scene.BIMSearchProperties.filter_classes.clear()
ifcTypeUniqueList =sorted(list(set((eleIfcTypeList)))) return {"FINISHED"}
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
print(f"{self.bl_label} Closed")
bpy.context.scene.BIM_IfcTypeFilter_collprops.clear()
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: