mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-26 02:07:36 +00:00
Code review for Ifc Type filter feature. See #1823.
This commit is contained in:
@@ -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)
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
Reference in New Issue
Block a user