mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-28 03:05:33 +00:00
black .
This commit is contained in:
@@ -302,10 +302,9 @@ class CreateDrawing(bpy.types.Operator):
|
|||||||
# Force Blender to process all pending operations
|
# Force Blender to process all pending operations
|
||||||
for area in context.screen.areas:
|
for area in context.screen.areas:
|
||||||
area.tag_redraw()
|
area.tag_redraw()
|
||||||
|
|
||||||
# Process events to let Blender finish internal cleanup
|
# Process events to let Blender finish internal cleanup
|
||||||
bpy.ops.wm.redraw_timer(type='DRAW_WIN_SWAP', iterations=1)
|
bpy.ops.wm.redraw_timer(type="DRAW_WIN_SWAP", iterations=1)
|
||||||
|
|
||||||
|
|
||||||
self.camera = context.scene.camera
|
self.camera = context.scene.camera
|
||||||
assert (camera_element := tool.Ifc.get_entity(self.camera))
|
assert (camera_element := tool.Ifc.get_entity(self.camera))
|
||||||
@@ -3713,16 +3712,16 @@ class EditElementFilter(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
assert element
|
assert element
|
||||||
pset = tool.Pset.get_element_pset(element, "EPset_Drawing")
|
pset = tool.Pset.get_element_pset(element, "EPset_Drawing")
|
||||||
assert pset
|
assert pset
|
||||||
|
|
||||||
if self.filter_mode == "INCLUDE":
|
if self.filter_mode == "INCLUDE":
|
||||||
filter_groups = props.include_filter_groups
|
filter_groups = props.include_filter_groups
|
||||||
elif self.filter_mode == "EXCLUDE":
|
elif self.filter_mode == "EXCLUDE":
|
||||||
filter_groups = props.exclude_filter_groups
|
filter_groups = props.exclude_filter_groups
|
||||||
else:
|
else:
|
||||||
return
|
return
|
||||||
|
|
||||||
query = tool.Search.export_filter_query(filter_groups) or None
|
query = tool.Search.export_filter_query(filter_groups) or None
|
||||||
|
|
||||||
if tool.Blender.get_addon_preferences().chain_filter_with_set_operations and query:
|
if tool.Blender.get_addon_preferences().chain_filter_with_set_operations and query:
|
||||||
filter_structure = []
|
filter_structure = []
|
||||||
for filter_group in filter_groups:
|
for filter_group in filter_groups:
|
||||||
@@ -3738,20 +3737,16 @@ class EditElementFilter(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
}
|
}
|
||||||
group_data.append(filter_data)
|
group_data.append(filter_data)
|
||||||
filter_structure.append(group_data)
|
filter_structure.append(group_data)
|
||||||
|
|
||||||
value = json.dumps({
|
value = json.dumps({"type": "BBIM_Search", "query": query, "filter_structure": filter_structure})
|
||||||
"type": "BBIM_Search",
|
|
||||||
"query": query,
|
|
||||||
"filter_structure": filter_structure
|
|
||||||
})
|
|
||||||
else:
|
else:
|
||||||
value = query
|
value = query
|
||||||
|
|
||||||
if self.filter_mode == "INCLUDE":
|
if self.filter_mode == "INCLUDE":
|
||||||
ifcopenshell.api.pset.edit_pset(tool.Ifc.get(), pset=pset, properties={"Include": value})
|
ifcopenshell.api.pset.edit_pset(tool.Ifc.get(), pset=pset, properties={"Include": value})
|
||||||
elif self.filter_mode == "EXCLUDE":
|
elif self.filter_mode == "EXCLUDE":
|
||||||
ifcopenshell.api.pset.edit_pset(tool.Ifc.get(), pset=pset, properties={"Exclude": value})
|
ifcopenshell.api.pset.edit_pset(tool.Ifc.get(), pset=pset, properties={"Exclude": value})
|
||||||
|
|
||||||
props.filter_mode = "NONE"
|
props.filter_mode = "NONE"
|
||||||
bpy.ops.bim.activate_drawing(drawing=element.id(), should_view_from_camera=False)
|
bpy.ops.bim.activate_drawing(drawing=element.id(), should_view_from_camera=False)
|
||||||
|
|
||||||
|
|||||||
@@ -484,7 +484,7 @@ class BIM_PT_sheets(Panel):
|
|||||||
for annotation in ifc_file.by_type("IfcAnnotation"):
|
for annotation in ifc_file.by_type("IfcAnnotation"):
|
||||||
if annotation.ObjectType != "DRAWING":
|
if annotation.ObjectType != "DRAWING":
|
||||||
continue
|
continue
|
||||||
|
|
||||||
Annotation_Name = annotation.Name.replace(",", "") # Remove commas
|
Annotation_Name = annotation.Name.replace(",", "") # Remove commas
|
||||||
if Annotation_Name == drawingname:
|
if Annotation_Name == drawingname:
|
||||||
drawingid = annotation.id()
|
drawingid = annotation.id()
|
||||||
|
|||||||
@@ -54,18 +54,18 @@ def draw_text_editor_header(self, context):
|
|||||||
def update_filter_search_value(self: "FilterValueSuggestions", context: bpy.types.Context) -> None:
|
def update_filter_search_value(self: "FilterValueSuggestions", context: bpy.types.Context) -> None:
|
||||||
filter_groups = tool.Search.get_filter_groups(self.module)
|
filter_groups = tool.Search.get_filter_groups(self.module)
|
||||||
ifc_filter = filter_groups[self.group_index].filters[self.filter_index]
|
ifc_filter = filter_groups[self.group_index].filters[self.filter_index]
|
||||||
|
|
||||||
value = self.search_value
|
value = self.search_value
|
||||||
|
|
||||||
if " < " in value:
|
if " < " in value:
|
||||||
value = value.split(" < ")[-1]
|
value = value.split(" < ")[-1]
|
||||||
|
|
||||||
if ifc_filter.type == "entity":
|
if ifc_filter.type == "entity":
|
||||||
if " (superclass)" in value:
|
if " (superclass)" in value:
|
||||||
value = value.replace(" (superclass)", "")
|
value = value.replace(" (superclass)", "")
|
||||||
if " > " in value:
|
if " > " in value:
|
||||||
value = value.split(" > ")[-1]
|
value = value.split(" > ")[-1]
|
||||||
|
|
||||||
elif ifc_filter.type == "instance":
|
elif ifc_filter.type == "instance":
|
||||||
if ": " in value:
|
if ": " in value:
|
||||||
value = value.split(": ")[-1]
|
value = value.split(": ")[-1]
|
||||||
@@ -73,23 +73,23 @@ def update_filter_search_value(self: "FilterValueSuggestions", context: bpy.type
|
|||||||
hierarchy_class = value.split(" (")
|
hierarchy_class = value.split(" (")
|
||||||
element_class = hierarchy_class[-1].rstrip(")")
|
element_class = hierarchy_class[-1].rstrip(")")
|
||||||
element_name = hierarchy_class[0] if len(hierarchy_class) > 1 else None
|
element_name = hierarchy_class[0] if len(hierarchy_class) > 1 else None
|
||||||
|
|
||||||
ifc_file = tool.Ifc.get()
|
ifc_file = tool.Ifc.get()
|
||||||
if ifc_file:
|
if ifc_file:
|
||||||
for element_id in IfcStore.id_map.keys():
|
for element_id in IfcStore.id_map.keys():
|
||||||
try:
|
try:
|
||||||
element = ifc_file.by_id(element_id)
|
element = ifc_file.by_id(element_id)
|
||||||
if element.is_a() == element_class:
|
if element.is_a() == element_class:
|
||||||
if element_name is None or (hasattr(element, 'Name') and element.Name == element_name):
|
if element_name is None or (hasattr(element, "Name") and element.Name == element_name):
|
||||||
value = element.GlobalId
|
value = element.GlobalId
|
||||||
break
|
break
|
||||||
except:
|
except:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
elif ifc_filter.type == "parent":
|
elif ifc_filter.type == "parent":
|
||||||
if " (" in value:
|
if " (" in value:
|
||||||
value = value.split(" (")[0]
|
value = value.split(" (")[0]
|
||||||
|
|
||||||
if ifc_filter.type == "property":
|
if ifc_filter.type == "property":
|
||||||
if self.suggestion_type == "pset":
|
if self.suggestion_type == "pset":
|
||||||
ifc_filter.pset = value
|
ifc_filter.pset = value
|
||||||
@@ -104,7 +104,7 @@ def update_filter_search_value(self: "FilterValueSuggestions", context: bpy.type
|
|||||||
ifc_filter.value = value
|
ifc_filter.value = value
|
||||||
else:
|
else:
|
||||||
ifc_filter.value = value
|
ifc_filter.value = value
|
||||||
|
|
||||||
if self.first_launch:
|
if self.first_launch:
|
||||||
self.first_launch = False
|
self.first_launch = False
|
||||||
else:
|
else:
|
||||||
@@ -122,7 +122,7 @@ class FilterValueSuggestions(Operator):
|
|||||||
module: StringProperty(default="search")
|
module: StringProperty(default="search")
|
||||||
filter_type: StringProperty()
|
filter_type: StringProperty()
|
||||||
suggestion_type: StringProperty(default="value")
|
suggestion_type: StringProperty(default="value")
|
||||||
|
|
||||||
first_launch: BoolProperty(default=True, options={"SKIP_SAVE"})
|
first_launch: BoolProperty(default=True, options={"SKIP_SAVE"})
|
||||||
search_value: StringProperty(
|
search_value: StringProperty(
|
||||||
name="Search",
|
name="Search",
|
||||||
@@ -158,10 +158,10 @@ class FilterValueSuggestions(Operator):
|
|||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
|
|
||||||
filter_groups = tool.Search.get_filter_groups(self.module)
|
filter_groups = tool.Search.get_filter_groups(self.module)
|
||||||
ifc_filter = filter_groups[self.group_index].filters[self.filter_index]
|
ifc_filter = filter_groups[self.group_index].filters[self.filter_index]
|
||||||
|
|
||||||
label_map = {
|
label_map = {
|
||||||
"entity": "Select Class",
|
"entity": "Select Class",
|
||||||
"type": "Select Type",
|
"type": "Select Type",
|
||||||
@@ -172,7 +172,7 @@ class FilterValueSuggestions(Operator):
|
|||||||
"parent": "Select Parent",
|
"parent": "Select Parent",
|
||||||
"instance": "Select GlobalId",
|
"instance": "Select GlobalId",
|
||||||
}
|
}
|
||||||
|
|
||||||
if ifc_filter.type == "attribute":
|
if ifc_filter.type == "attribute":
|
||||||
if self.suggestion_type == "attribute_value":
|
if self.suggestion_type == "attribute_value":
|
||||||
label = f"Select Value for {ifc_filter.name}"
|
label = f"Select Value for {ifc_filter.name}"
|
||||||
@@ -187,7 +187,7 @@ class FilterValueSuggestions(Operator):
|
|||||||
label = "Select Property Set"
|
label = "Select Property Set"
|
||||||
else:
|
else:
|
||||||
label = label_map.get(ifc_filter.type, "Select Value")
|
label = label_map.get(ifc_filter.type, "Select Value")
|
||||||
|
|
||||||
row = layout.row()
|
row = layout.row()
|
||||||
row.label(text=label)
|
row.label(text=label)
|
||||||
row = layout.row()
|
row = layout.row()
|
||||||
@@ -202,7 +202,7 @@ class FilterValueSuggestions(Operator):
|
|||||||
|
|
||||||
def get_suggestions(self, ifc_file, ifc_filter):
|
def get_suggestions(self, ifc_file, ifc_filter):
|
||||||
suggestions = set()
|
suggestions = set()
|
||||||
|
|
||||||
if ifc_filter.type == "entity":
|
if ifc_filter.type == "entity":
|
||||||
suggestions = self.get_entity_suggestions(ifc_file)
|
suggestions = self.get_entity_suggestions(ifc_file)
|
||||||
elif ifc_filter.type == "type":
|
elif ifc_filter.type == "type":
|
||||||
@@ -231,58 +231,58 @@ class FilterValueSuggestions(Operator):
|
|||||||
suggestions = self.get_property_names(ifc_file, ifc_filter.pset)
|
suggestions = self.get_property_names(ifc_file, ifc_filter.pset)
|
||||||
else:
|
else:
|
||||||
suggestions = self.get_property_values(ifc_file, ifc_filter.pset, ifc_filter.name)
|
suggestions = self.get_property_values(ifc_file, ifc_filter.pset, ifc_filter.name)
|
||||||
|
|
||||||
return suggestions
|
return suggestions
|
||||||
|
|
||||||
def build_hierarchy_path(self, element):
|
def build_hierarchy_path(self, element):
|
||||||
path = []
|
path = []
|
||||||
current = element
|
current = element
|
||||||
|
|
||||||
while current:
|
while current:
|
||||||
if hasattr(current, 'Name') and current.Name:
|
if hasattr(current, "Name") and current.Name:
|
||||||
path.insert(0, current.Name)
|
path.insert(0, current.Name)
|
||||||
|
|
||||||
parent = None
|
parent = None
|
||||||
|
|
||||||
if hasattr(current, 'Decomposes') and current.Decomposes:
|
if hasattr(current, "Decomposes") and current.Decomposes:
|
||||||
for rel in current.Decomposes:
|
for rel in current.Decomposes:
|
||||||
if hasattr(rel, 'RelatingObject'):
|
if hasattr(rel, "RelatingObject"):
|
||||||
parent = rel.RelatingObject
|
parent = rel.RelatingObject
|
||||||
break
|
break
|
||||||
|
|
||||||
if not parent and hasattr(current, 'ContainedInStructure') and current.ContainedInStructure:
|
if not parent and hasattr(current, "ContainedInStructure") and current.ContainedInStructure:
|
||||||
for rel in current.ContainedInStructure:
|
for rel in current.ContainedInStructure:
|
||||||
if hasattr(rel, 'RelatingStructure'):
|
if hasattr(rel, "RelatingStructure"):
|
||||||
parent = rel.RelatingStructure
|
parent = rel.RelatingStructure
|
||||||
break
|
break
|
||||||
|
|
||||||
current = parent
|
current = parent
|
||||||
|
|
||||||
return path
|
return path
|
||||||
|
|
||||||
def get_entity_suggestions(self, ifc_file):
|
def get_entity_suggestions(self, ifc_file):
|
||||||
all_classes = set()
|
all_classes = set()
|
||||||
schema = tool.Ifc.schema()
|
schema = tool.Ifc.schema()
|
||||||
|
|
||||||
for element_id in IfcStore.id_map.keys():
|
for element_id in IfcStore.id_map.keys():
|
||||||
try:
|
try:
|
||||||
element = ifc_file.by_id(element_id)
|
element = ifc_file.by_id(element_id)
|
||||||
class_name = element.is_a()
|
class_name = element.is_a()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
entity = schema.declaration_by_name(class_name).as_entity()
|
entity = schema.declaration_by_name(class_name).as_entity()
|
||||||
current = entity
|
current = entity
|
||||||
|
|
||||||
chain_names = [class_name]
|
chain_names = [class_name]
|
||||||
while current.supertype():
|
while current.supertype():
|
||||||
supertype = current.supertype()
|
supertype = current.supertype()
|
||||||
chain_names.insert(0, supertype.name())
|
chain_names.insert(0, supertype.name())
|
||||||
current = supertype
|
current = supertype
|
||||||
|
|
||||||
if len(chain_names) > 1:
|
if len(chain_names) > 1:
|
||||||
all_classes.add(" > ".join(chain_names))
|
all_classes.add(" > ".join(chain_names))
|
||||||
for i in range(len(chain_names) - 1):
|
for i in range(len(chain_names) - 1):
|
||||||
superclass_chain = " > ".join(chain_names[:i+1])
|
superclass_chain = " > ".join(chain_names[: i + 1])
|
||||||
all_classes.add(f"{superclass_chain} (superclass)")
|
all_classes.add(f"{superclass_chain} (superclass)")
|
||||||
else:
|
else:
|
||||||
all_classes.add(class_name)
|
all_classes.add(class_name)
|
||||||
@@ -290,7 +290,7 @@ class FilterValueSuggestions(Operator):
|
|||||||
all_classes.add(class_name)
|
all_classes.add(class_name)
|
||||||
except:
|
except:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
return all_classes
|
return all_classes
|
||||||
|
|
||||||
def get_type_suggestions(self, ifc_file):
|
def get_type_suggestions(self, ifc_file):
|
||||||
@@ -346,60 +346,60 @@ class FilterValueSuggestions(Operator):
|
|||||||
try:
|
try:
|
||||||
element = ifc_file.by_id(element_id)
|
element = ifc_file.by_id(element_id)
|
||||||
has_children = False
|
has_children = False
|
||||||
|
|
||||||
if hasattr(element, 'IsDecomposedBy') and element.IsDecomposedBy:
|
if hasattr(element, "IsDecomposedBy") and element.IsDecomposedBy:
|
||||||
has_children = True
|
has_children = True
|
||||||
elif hasattr(element, 'ContainsElements') and element.ContainsElements:
|
elif hasattr(element, "ContainsElements") and element.ContainsElements:
|
||||||
has_children = True
|
has_children = True
|
||||||
elif hasattr(element, 'HasOpenings') and element.HasOpenings:
|
elif hasattr(element, "HasOpenings") and element.HasOpenings:
|
||||||
has_children = True
|
has_children = True
|
||||||
|
|
||||||
if has_children:
|
if has_children:
|
||||||
hierarchy_path = self.build_hierarchy_path(element)
|
hierarchy_path = self.build_hierarchy_path(element)
|
||||||
element_class = element.is_a()
|
element_class = element.is_a()
|
||||||
|
|
||||||
if len(hierarchy_path) > 0:
|
if len(hierarchy_path) > 0:
|
||||||
hierarchy_str = " < ".join(hierarchy_path)
|
hierarchy_str = " < ".join(hierarchy_path)
|
||||||
suggestions.add(f"{hierarchy_str} ({element_class})")
|
suggestions.add(f"{hierarchy_str} ({element_class})")
|
||||||
else:
|
else:
|
||||||
element_name = element.Name if hasattr(element, 'Name') and element.Name else element_class
|
element_name = element.Name if hasattr(element, "Name") and element.Name else element_class
|
||||||
suggestions.add(f"{element_name} ({element_class})")
|
suggestions.add(f"{element_name} ({element_class})")
|
||||||
except:
|
except:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
return suggestions
|
return suggestions
|
||||||
|
|
||||||
def get_instance_suggestions(self, ifc_file):
|
def get_instance_suggestions(self, ifc_file):
|
||||||
suggestions = set()
|
suggestions = set()
|
||||||
element_data = []
|
element_data = []
|
||||||
|
|
||||||
for element_id in IfcStore.id_map.keys():
|
for element_id in IfcStore.id_map.keys():
|
||||||
try:
|
try:
|
||||||
element = ifc_file.by_id(element_id)
|
element = ifc_file.by_id(element_id)
|
||||||
if hasattr(element, 'GlobalId') and element.GlobalId:
|
if hasattr(element, "GlobalId") and element.GlobalId:
|
||||||
hierarchy_path = self.build_hierarchy_path(element)
|
hierarchy_path = self.build_hierarchy_path(element)
|
||||||
element_class = element.is_a()
|
element_class = element.is_a()
|
||||||
|
|
||||||
if len(hierarchy_path) > 0:
|
if len(hierarchy_path) > 0:
|
||||||
hierarchy_str = " < ".join(hierarchy_path)
|
hierarchy_str = " < ".join(hierarchy_path)
|
||||||
display_str = f"{hierarchy_str} ({element_class})"
|
display_str = f"{hierarchy_str} ({element_class})"
|
||||||
else:
|
else:
|
||||||
display_str = f"({element_class})"
|
display_str = f"({element_class})"
|
||||||
|
|
||||||
element_data.append((display_str, element.GlobalId))
|
element_data.append((display_str, element.GlobalId))
|
||||||
except:
|
except:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
display_counts = {}
|
display_counts = {}
|
||||||
for display_str, global_id in element_data:
|
for display_str, global_id in element_data:
|
||||||
display_counts[display_str] = display_counts.get(display_str, 0) + 1
|
display_counts[display_str] = display_counts.get(display_str, 0) + 1
|
||||||
|
|
||||||
for display_str, global_id in element_data:
|
for display_str, global_id in element_data:
|
||||||
if display_counts[display_str] > 1:
|
if display_counts[display_str] > 1:
|
||||||
suggestions.add(f"{display_str}: {global_id}")
|
suggestions.add(f"{display_str}: {global_id}")
|
||||||
else:
|
else:
|
||||||
suggestions.add(display_str)
|
suggestions.add(display_str)
|
||||||
|
|
||||||
return suggestions
|
return suggestions
|
||||||
|
|
||||||
def get_property_sets(self, ifc_file):
|
def get_property_sets(self, ifc_file):
|
||||||
@@ -407,8 +407,8 @@ class FilterValueSuggestions(Operator):
|
|||||||
for element_id in IfcStore.id_map.keys():
|
for element_id in IfcStore.id_map.keys():
|
||||||
try:
|
try:
|
||||||
element = ifc_file.by_id(element_id)
|
element = ifc_file.by_id(element_id)
|
||||||
for definition in getattr(element, 'IsDefinedBy', []):
|
for definition in getattr(element, "IsDefinedBy", []):
|
||||||
if definition.is_a('IfcRelDefinesByProperties'):
|
if definition.is_a("IfcRelDefinesByProperties"):
|
||||||
pset = definition.RelatingPropertyDefinition
|
pset = definition.RelatingPropertyDefinition
|
||||||
if pset.is_a("IfcPropertySet") and pset.Name:
|
if pset.is_a("IfcPropertySet") and pset.Name:
|
||||||
psets.add(pset.Name)
|
psets.add(pset.Name)
|
||||||
@@ -421,8 +421,8 @@ class FilterValueSuggestions(Operator):
|
|||||||
for element_id in IfcStore.id_map.keys():
|
for element_id in IfcStore.id_map.keys():
|
||||||
try:
|
try:
|
||||||
element = ifc_file.by_id(element_id)
|
element = ifc_file.by_id(element_id)
|
||||||
for definition in getattr(element, 'IsDefinedBy', []):
|
for definition in getattr(element, "IsDefinedBy", []):
|
||||||
if definition.is_a('IfcRelDefinesByProperties'):
|
if definition.is_a("IfcRelDefinesByProperties"):
|
||||||
pset = definition.RelatingPropertyDefinition
|
pset = definition.RelatingPropertyDefinition
|
||||||
if pset.is_a("IfcPropertySet") and pset.Name == pset_name:
|
if pset.is_a("IfcPropertySet") and pset.Name == pset_name:
|
||||||
if pset.HasProperties:
|
if pset.HasProperties:
|
||||||
@@ -438,8 +438,8 @@ class FilterValueSuggestions(Operator):
|
|||||||
for element_id in IfcStore.id_map.keys():
|
for element_id in IfcStore.id_map.keys():
|
||||||
try:
|
try:
|
||||||
element = ifc_file.by_id(element_id)
|
element = ifc_file.by_id(element_id)
|
||||||
for definition in getattr(element, 'IsDefinedBy', []):
|
for definition in getattr(element, "IsDefinedBy", []):
|
||||||
if definition.is_a('IfcRelDefinesByProperties'):
|
if definition.is_a("IfcRelDefinesByProperties"):
|
||||||
pset = definition.RelatingPropertyDefinition
|
pset = definition.RelatingPropertyDefinition
|
||||||
if pset.is_a("IfcPropertySet") and pset.Name == pset_name:
|
if pset.is_a("IfcPropertySet") and pset.Name == pset_name:
|
||||||
if pset.HasProperties:
|
if pset.HasProperties:
|
||||||
@@ -449,9 +449,13 @@ class FilterValueSuggestions(Operator):
|
|||||||
try:
|
try:
|
||||||
value = prop.NominalValue.wrappedValue
|
value = prop.NominalValue.wrappedValue
|
||||||
if value is not None and value != "":
|
if value is not None and value != "":
|
||||||
if not hasattr(value, 'is_a') and not isinstance(value, (tuple, list)):
|
if not hasattr(value, "is_a") and not isinstance(
|
||||||
|
value, (tuple, list)
|
||||||
|
):
|
||||||
str_value = str(value)
|
str_value = str(value)
|
||||||
if not str_value.startswith("#") and not str_value.startswith("("):
|
if not str_value.startswith("#") and not str_value.startswith(
|
||||||
|
"("
|
||||||
|
):
|
||||||
property_values.add(str_value)
|
property_values.add(str_value)
|
||||||
except:
|
except:
|
||||||
continue
|
continue
|
||||||
@@ -462,7 +466,7 @@ class FilterValueSuggestions(Operator):
|
|||||||
def get_attribute_names(self, ifc_file):
|
def get_attribute_names(self, ifc_file):
|
||||||
attribute_names = set()
|
attribute_names = set()
|
||||||
schema = tool.Ifc.schema()
|
schema = tool.Ifc.schema()
|
||||||
|
|
||||||
ifc_classes = set()
|
ifc_classes = set()
|
||||||
for element_id in IfcStore.id_map.keys():
|
for element_id in IfcStore.id_map.keys():
|
||||||
try:
|
try:
|
||||||
@@ -470,7 +474,7 @@ class FilterValueSuggestions(Operator):
|
|||||||
ifc_classes.add(element.is_a())
|
ifc_classes.add(element.is_a())
|
||||||
except:
|
except:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
for ifc_class in ifc_classes:
|
for ifc_class in ifc_classes:
|
||||||
try:
|
try:
|
||||||
entity = schema.declaration_by_name(ifc_class).as_entity()
|
entity = schema.declaration_by_name(ifc_class).as_entity()
|
||||||
@@ -479,30 +483,30 @@ class FilterValueSuggestions(Operator):
|
|||||||
attribute_names.add(attr.name())
|
attribute_names.add(attr.name())
|
||||||
except:
|
except:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
return attribute_names
|
return attribute_names
|
||||||
|
|
||||||
def get_attribute_values(self, ifc_file, attribute_name):
|
def get_attribute_values(self, ifc_file, attribute_name):
|
||||||
attribute_values = set()
|
attribute_values = set()
|
||||||
|
|
||||||
for element_id in IfcStore.id_map.keys():
|
for element_id in IfcStore.id_map.keys():
|
||||||
try:
|
try:
|
||||||
element = ifc_file.by_id(element_id)
|
element = ifc_file.by_id(element_id)
|
||||||
|
|
||||||
if element.is_a("IfcRelationship") or element.is_a("IfcTypeObject"):
|
if element.is_a("IfcRelationship") or element.is_a("IfcTypeObject"):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if hasattr(element, attribute_name):
|
if hasattr(element, attribute_name):
|
||||||
value = getattr(element, attribute_name, None)
|
value = getattr(element, attribute_name, None)
|
||||||
|
|
||||||
if value is not None and value != "":
|
if value is not None and value != "":
|
||||||
if not hasattr(value, 'is_a') and not isinstance(value, (tuple, list)):
|
if not hasattr(value, "is_a") and not isinstance(value, (tuple, list)):
|
||||||
str_value = str(value)
|
str_value = str(value)
|
||||||
if not str_value.startswith("#") and not str_value.startswith("("):
|
if not str_value.startswith("#") and not str_value.startswith("("):
|
||||||
attribute_values.add(str_value)
|
attribute_values.add(str_value)
|
||||||
except:
|
except:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
return attribute_values
|
return attribute_values
|
||||||
|
|
||||||
|
|
||||||
@@ -580,14 +584,14 @@ class ToggleFilterInclusion(Operator):
|
|||||||
filter_groups = tool.Search.get_filter_groups(self.module)
|
filter_groups = tool.Search.get_filter_groups(self.module)
|
||||||
filter_group = filter_groups[self.group_index]
|
filter_group = filter_groups[self.group_index]
|
||||||
ifc_filter = filter_group.filters[self.filter_index]
|
ifc_filter = filter_group.filters[self.filter_index]
|
||||||
|
|
||||||
if ifc_filter.filter_mode == "ADD":
|
if ifc_filter.filter_mode == "ADD":
|
||||||
ifc_filter.filter_mode = "SUBTRACT"
|
ifc_filter.filter_mode = "SUBTRACT"
|
||||||
elif ifc_filter.filter_mode == "SUBTRACT":
|
elif ifc_filter.filter_mode == "SUBTRACT":
|
||||||
ifc_filter.filter_mode = "FILTER"
|
ifc_filter.filter_mode = "FILTER"
|
||||||
else:
|
else:
|
||||||
ifc_filter.filter_mode = "ADD"
|
ifc_filter.filter_mode = "ADD"
|
||||||
|
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
@@ -615,40 +619,40 @@ class ApplyFilterFromText(Operator, tool.Ifc.Operator):
|
|||||||
bl_label = "Apply Filter Configuration"
|
bl_label = "Apply Filter Configuration"
|
||||||
bl_description = "Apply the JSON filter configuration from the current text block"
|
bl_description = "Apply the JSON filter configuration from the current text block"
|
||||||
bl_options = {"REGISTER", "UNDO"}
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def poll(cls, context):
|
def poll(cls, context):
|
||||||
if context.area and context.area.type == 'TEXT_EDITOR':
|
if context.area and context.area.type == "TEXT_EDITOR":
|
||||||
space = context.space_data
|
space = context.space_data
|
||||||
if space.text and space.text.name.startswith("FilterQuery_"):
|
if space.text and space.text.name.startswith("FilterQuery_"):
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
space = context.space_data
|
space = context.space_data
|
||||||
text = space.text
|
text = space.text
|
||||||
|
|
||||||
if not text or not text.name.startswith("FilterQuery_"):
|
if not text or not text.name.startswith("FilterQuery_"):
|
||||||
self.report({"ERROR"}, "No valid filter configuration text block")
|
self.report({"ERROR"}, "No valid filter configuration text block")
|
||||||
return {'CANCELLED'}
|
return {"CANCELLED"}
|
||||||
|
|
||||||
module = text.name.replace("FilterQuery_", "")
|
module = text.name.replace("FilterQuery_", "")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
json_data = json.loads(text.as_string())
|
json_data = json.loads(text.as_string())
|
||||||
filter_structure = json_data.get("filter_structure", [])
|
filter_structure = json_data.get("filter_structure", [])
|
||||||
filter_groups = tool.Search.get_filter_groups(module)
|
filter_groups = tool.Search.get_filter_groups(module)
|
||||||
tool.Search.import_filter_structure(filter_structure, filter_groups)
|
tool.Search.import_filter_structure(filter_structure, filter_groups)
|
||||||
self.report({"INFO"}, "Filter configuration applied successfully")
|
self.report({"INFO"}, "Filter configuration applied successfully")
|
||||||
|
|
||||||
if len(context.window_manager.windows) > 1:
|
if len(context.window_manager.windows) > 1:
|
||||||
bpy.ops.wm.window_close()
|
bpy.ops.wm.window_close()
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.report({"ERROR"}, f"Invalid JSON: {str(e)}")
|
self.report({"ERROR"}, f"Invalid JSON: {str(e)}")
|
||||||
return {'CANCELLED'}
|
return {"CANCELLED"}
|
||||||
|
|
||||||
return {'FINISHED'}
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
class EditFilterQuery(Operator, tool.Ifc.Operator):
|
class EditFilterQuery(Operator, tool.Ifc.Operator):
|
||||||
@@ -662,7 +666,7 @@ class EditFilterQuery(Operator, tool.Ifc.Operator):
|
|||||||
|
|
||||||
def _execute(self, context):
|
def _execute(self, context):
|
||||||
module = getattr(self, "module", "search")
|
module = getattr(self, "module", "search")
|
||||||
|
|
||||||
if not tool.Blender.get_addon_preferences().chain_filter_with_set_operations:
|
if not tool.Blender.get_addon_preferences().chain_filter_with_set_operations:
|
||||||
if self.query == self.old_query:
|
if self.query == self.old_query:
|
||||||
return
|
return
|
||||||
@@ -674,7 +678,7 @@ class EditFilterQuery(Operator, tool.Ifc.Operator):
|
|||||||
return
|
return
|
||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
|
|
||||||
if not tool.Blender.get_addon_preferences().chain_filter_with_set_operations:
|
if not tool.Blender.get_addon_preferences().chain_filter_with_set_operations:
|
||||||
row = self.layout.row()
|
row = self.layout.row()
|
||||||
row.prop(self, "query", text="")
|
row.prop(self, "query", text="")
|
||||||
@@ -698,39 +702,37 @@ class EditFilterQuery(Operator, tool.Ifc.Operator):
|
|||||||
}
|
}
|
||||||
group_data.append(filter_data)
|
group_data.append(filter_data)
|
||||||
filter_structure.append(group_data)
|
filter_structure.append(group_data)
|
||||||
|
|
||||||
query = tool.Search.export_filter_query(filter_groups)
|
query = tool.Search.export_filter_query(filter_groups)
|
||||||
json_data = {
|
json_data = {"type": "BBIM_Search", "query": query, "filter_structure": filter_structure}
|
||||||
"type": "BBIM_Search",
|
|
||||||
"query": query,
|
|
||||||
"filter_structure": filter_structure
|
|
||||||
}
|
|
||||||
|
|
||||||
text_block_name = f"FilterQuery_{module}"
|
text_block_name = f"FilterQuery_{module}"
|
||||||
text = bpy.data.texts.get(text_block_name)
|
text = bpy.data.texts.get(text_block_name)
|
||||||
if not text:
|
if not text:
|
||||||
text = bpy.data.texts.new(text_block_name)
|
text = bpy.data.texts.new(text_block_name)
|
||||||
|
|
||||||
text.clear()
|
text.clear()
|
||||||
text.write(json.dumps(json_data, indent=2))
|
text.write(json.dumps(json_data, indent=2))
|
||||||
|
|
||||||
bpy.ops.wm.window_new()
|
bpy.ops.wm.window_new()
|
||||||
new_window = context.window_manager.windows[-1]
|
new_window = context.window_manager.windows[-1]
|
||||||
|
|
||||||
new_area = new_window.screen.areas[0]
|
new_area = new_window.screen.areas[0]
|
||||||
new_area.type = 'TEXT_EDITOR'
|
new_area.type = "TEXT_EDITOR"
|
||||||
|
|
||||||
text_space = None
|
text_space = None
|
||||||
for space in new_area.spaces:
|
for space in new_area.spaces:
|
||||||
if space.type == 'TEXT_EDITOR':
|
if space.type == "TEXT_EDITOR":
|
||||||
text_space = space
|
text_space = space
|
||||||
break
|
break
|
||||||
|
|
||||||
if text_space:
|
if text_space:
|
||||||
text_space.text = text
|
text_space.text = text
|
||||||
|
|
||||||
self.report({"INFO"}, "Compact text editor opened. Edit JSON and click 'Apply Filter Configuration' in header")
|
self.report(
|
||||||
return {'FINISHED'}
|
{"INFO"}, "Compact text editor opened. Edit JSON and click 'Apply Filter Configuration' in header"
|
||||||
|
)
|
||||||
|
return {"FINISHED"}
|
||||||
|
|
||||||
else:
|
else:
|
||||||
self.query = tool.Search.export_filter_query(filter_groups)
|
self.query = tool.Search.export_filter_query(filter_groups)
|
||||||
@@ -761,9 +763,12 @@ class Search(Operator):
|
|||||||
assert_never(self.property_group)
|
assert_never(self.property_group)
|
||||||
|
|
||||||
preferences = tool.Blender.get_addon_preferences()
|
preferences = tool.Blender.get_addon_preferences()
|
||||||
|
|
||||||
# Migrate old ! prefix filters to new filter_mode system when preferences are enabled
|
# Migrate old ! prefix filters to new filter_mode system when preferences are enabled
|
||||||
if preferences.chain_filter_with_set_operations or preferences.default_filter_with_set_operations_for_globalid_and_class:
|
if (
|
||||||
|
preferences.chain_filter_with_set_operations
|
||||||
|
or preferences.default_filter_with_set_operations_for_globalid_and_class
|
||||||
|
):
|
||||||
for filter_group in props.filter_groups:
|
for filter_group in props.filter_groups:
|
||||||
for ifc_filter in filter_group.filters:
|
for ifc_filter in filter_group.filters:
|
||||||
if ifc_filter.type not in ["entity", "instance"]:
|
if ifc_filter.type not in ["entity", "instance"]:
|
||||||
@@ -771,7 +776,7 @@ class Search(Operator):
|
|||||||
if ifc_filter.value.startswith("!"):
|
if ifc_filter.value.startswith("!"):
|
||||||
ifc_filter.value = ifc_filter.value[1:]
|
ifc_filter.value = ifc_filter.value[1:]
|
||||||
ifc_filter.filter_mode = "SUBTRACT"
|
ifc_filter.filter_mode = "SUBTRACT"
|
||||||
|
|
||||||
results = tool.Search.execute_filter_groups(props.filter_groups)
|
results = tool.Search.execute_filter_groups(props.filter_groups)
|
||||||
else:
|
else:
|
||||||
results = ifcopenshell.util.selector.filter_elements(
|
results = ifcopenshell.util.selector.filter_elements(
|
||||||
@@ -843,7 +848,7 @@ class SaveSearch(Operator, tool.Ifc.Operator):
|
|||||||
try:
|
try:
|
||||||
query = tool.Search.export_filter_query(filter_groups)
|
query = tool.Search.export_filter_query(filter_groups)
|
||||||
results = tool.Search.execute_filter_groups(filter_groups)
|
results = tool.Search.execute_filter_groups(filter_groups)
|
||||||
|
|
||||||
filter_structure = []
|
filter_structure = []
|
||||||
for filter_group in filter_groups:
|
for filter_group in filter_groups:
|
||||||
group_data = []
|
group_data = []
|
||||||
@@ -863,11 +868,7 @@ class SaveSearch(Operator, tool.Ifc.Operator):
|
|||||||
self.report({"ERROR"}, "Error occurred trying save search.")
|
self.report({"ERROR"}, "Error occurred trying save search.")
|
||||||
return
|
return
|
||||||
|
|
||||||
description = json.dumps({
|
description = json.dumps({"type": "BBIM_Search", "query": query, "filter_structure": filter_structure})
|
||||||
"type": "BBIM_Search",
|
|
||||||
"query": query,
|
|
||||||
"filter_structure": filter_structure
|
|
||||||
})
|
|
||||||
ifc_file = tool.Ifc.get()
|
ifc_file = tool.Ifc.get()
|
||||||
group = next(
|
group = next(
|
||||||
(
|
(
|
||||||
@@ -908,7 +909,7 @@ class LoadSearch(Operator, tool.Ifc.Operator):
|
|||||||
filter_groups = tool.Search.get_filter_groups(self.module)
|
filter_groups = tool.Search.get_filter_groups(self.module)
|
||||||
props = tool.Search.get_search_props()
|
props = tool.Search.get_search_props()
|
||||||
group = tool.Ifc.get().by_id(int(props.saved_searches))
|
group = tool.Ifc.get().by_id(int(props.saved_searches))
|
||||||
|
|
||||||
group_data = tool.Search.get_group_data(group)
|
group_data = tool.Search.get_group_data(group)
|
||||||
if group_data and "filter_structure" in group_data:
|
if group_data and "filter_structure" in group_data:
|
||||||
tool.Search.import_filter_structure(group_data["filter_structure"], filter_groups)
|
tool.Search.import_filter_structure(group_data["filter_structure"], filter_groups)
|
||||||
@@ -939,7 +940,7 @@ class RemoveSearch(Operator, tool.Ifc.Operator):
|
|||||||
if not group_id:
|
if not group_id:
|
||||||
self.report({"ERROR"}, "No search selected for removal")
|
self.report({"ERROR"}, "No search selected for removal")
|
||||||
return
|
return
|
||||||
|
|
||||||
group = tool.Ifc.get().by_id(int(group_id))
|
group = tool.Ifc.get().by_id(int(group_id))
|
||||||
group_name = group.Name or "Unnamed"
|
group_name = group.Name or "Unnamed"
|
||||||
ifcopenshell.api.group.remove_group(tool.Ifc.get(), group=group)
|
ifcopenshell.api.group.remove_group(tool.Ifc.get(), group=group)
|
||||||
@@ -955,6 +956,7 @@ class RemoveSearch(Operator, tool.Ifc.Operator):
|
|||||||
def invoke(self, context, event):
|
def invoke(self, context, event):
|
||||||
tool.Search.patch_search_ifcgroups()
|
tool.Search.patch_search_ifcgroups()
|
||||||
from bonsai.bim.module.search.data import SearchData
|
from bonsai.bim.module.search.data import SearchData
|
||||||
|
|
||||||
if not SearchData.is_loaded:
|
if not SearchData.is_loaded:
|
||||||
SearchData.load()
|
SearchData.load()
|
||||||
return context.window_manager.invoke_props_dialog(self)
|
return context.window_manager.invoke_props_dialog(self)
|
||||||
|
|||||||
@@ -2125,7 +2125,7 @@ class Drawing(bonsai.core.tool.Drawing):
|
|||||||
command = command.replace(variable, value)
|
command = command.replace(variable, value)
|
||||||
# Defensive: skip if command[2:-2] is None or 'None'
|
# Defensive: skip if command[2:-2] is None or 'None'
|
||||||
command_content = command[2:-2]
|
command_content = command[2:-2]
|
||||||
if command_content is None or str(command_content).strip().lower() == 'none':
|
if command_content is None or str(command_content).strip().lower() == "none":
|
||||||
text = text.replace(original_command, "")
|
text = text.replace(original_command, "")
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
|
|||||||
@@ -51,17 +51,17 @@ class Search(bonsai.core.tool.Search):
|
|||||||
cls, filter_structure: list, filter_groups: bpy.types.bpy_prop_collection_idprop[BIMFilterGroup]
|
cls, filter_structure: list, filter_groups: bpy.types.bpy_prop_collection_idprop[BIMFilterGroup]
|
||||||
) -> None:
|
) -> None:
|
||||||
filter_groups.clear()
|
filter_groups.clear()
|
||||||
|
|
||||||
for group_data in filter_structure:
|
for group_data in filter_structure:
|
||||||
if not isinstance(group_data, list):
|
if not isinstance(group_data, list):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
filter_group = filter_groups.add()
|
filter_group = filter_groups.add()
|
||||||
|
|
||||||
for filter_data in group_data:
|
for filter_data in group_data:
|
||||||
if not isinstance(filter_data, dict):
|
if not isinstance(filter_data, dict):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
ifc_filter = filter_group.filters.add()
|
ifc_filter = filter_group.filters.add()
|
||||||
ifc_filter.type = filter_data.get("type", "")
|
ifc_filter.type = filter_data.get("type", "")
|
||||||
ifc_filter.name = filter_data.get("name", "")
|
ifc_filter.name = filter_data.get("name", "")
|
||||||
@@ -112,11 +112,11 @@ class Search(bonsai.core.tool.Search):
|
|||||||
for ifc_filter in filter_group.filters:
|
for ifc_filter in filter_group.filters:
|
||||||
if not ifc_filter.value:
|
if not ifc_filter.value:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
query_part = cls._export_single_filter(ifc_filter)
|
query_part = cls._export_single_filter(ifc_filter)
|
||||||
if query_part:
|
if query_part:
|
||||||
filter_group_query.append(query_part)
|
filter_group_query.append(query_part)
|
||||||
|
|
||||||
if filter_group_query:
|
if filter_group_query:
|
||||||
query.append(", ".join(filter_group_query))
|
query.append(", ".join(filter_group_query))
|
||||||
return " + ".join(query)
|
return " + ".join(query)
|
||||||
@@ -124,24 +124,30 @@ class Search(bonsai.core.tool.Search):
|
|||||||
@classmethod
|
@classmethod
|
||||||
def _export_single_filter(cls, ifc_filter: BIMFacet) -> str:
|
def _export_single_filter(cls, ifc_filter: BIMFacet) -> str:
|
||||||
preferences = tool.Blender.get_addon_preferences()
|
preferences = tool.Blender.get_addon_preferences()
|
||||||
|
|
||||||
if ifc_filter.type == "instance":
|
if ifc_filter.type == "instance":
|
||||||
if "bpy.data.texts" in ifc_filter.value:
|
if "bpy.data.texts" in ifc_filter.value:
|
||||||
data_name = ifc_filter.value.split("bpy.data.texts")[1][2:-2]
|
data_name = ifc_filter.value.split("bpy.data.texts")[1][2:-2]
|
||||||
value = bpy.data.texts[data_name].as_string()
|
value = bpy.data.texts[data_name].as_string()
|
||||||
else:
|
else:
|
||||||
value = ifc_filter.value
|
value = ifc_filter.value
|
||||||
|
|
||||||
if preferences.chain_filter_with_set_operations or preferences.default_filter_with_set_operations_for_globalid_and_class:
|
if (
|
||||||
|
preferences.chain_filter_with_set_operations
|
||||||
|
or preferences.default_filter_with_set_operations_for_globalid_and_class
|
||||||
|
):
|
||||||
value = value.lstrip("!")
|
value = value.lstrip("!")
|
||||||
if ifc_filter.filter_mode == "SUBTRACT":
|
if ifc_filter.filter_mode == "SUBTRACT":
|
||||||
value = f"!{value}"
|
value = f"!{value}"
|
||||||
return value
|
return value
|
||||||
|
|
||||||
elif ifc_filter.type == "entity":
|
elif ifc_filter.type == "entity":
|
||||||
value = ifc_filter.value
|
value = ifc_filter.value
|
||||||
|
|
||||||
if preferences.chain_filter_with_set_operations or preferences.default_filter_with_set_operations_for_globalid_and_class:
|
if (
|
||||||
|
preferences.chain_filter_with_set_operations
|
||||||
|
or preferences.default_filter_with_set_operations_for_globalid_and_class
|
||||||
|
):
|
||||||
value = value.lstrip("!")
|
value = value.lstrip("!")
|
||||||
if ifc_filter.filter_mode == "SUBTRACT":
|
if ifc_filter.filter_mode == "SUBTRACT":
|
||||||
value = f"!{value}"
|
value = f"!{value}"
|
||||||
@@ -192,25 +198,28 @@ class Search(bonsai.core.tool.Search):
|
|||||||
Groups are combined with union (same as original " + " behavior).
|
Groups are combined with union (same as original " + " behavior).
|
||||||
"""
|
"""
|
||||||
preferences = tool.Blender.get_addon_preferences()
|
preferences = tool.Blender.get_addon_preferences()
|
||||||
|
|
||||||
all_group_results = []
|
all_group_results = []
|
||||||
|
|
||||||
for group_idx, filter_group in enumerate(filter_groups):
|
for group_idx, filter_group in enumerate(filter_groups):
|
||||||
group_results = set()
|
group_results = set()
|
||||||
|
|
||||||
for filter_index, ifc_filter in enumerate(filter_group.filters):
|
for filter_index, ifc_filter in enumerate(filter_group.filters):
|
||||||
if not ifc_filter.value:
|
if not ifc_filter.value:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
query = cls._export_single_filter(ifc_filter)
|
query = cls._export_single_filter(ifc_filter)
|
||||||
if not query:
|
if not query:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if filter_index == 0:
|
if filter_index == 0:
|
||||||
mode = "ADD"
|
mode = "ADD"
|
||||||
else:
|
else:
|
||||||
if ifc_filter.type in ["entity", "instance"]:
|
if ifc_filter.type in ["entity", "instance"]:
|
||||||
if preferences.chain_filter_with_set_operations or preferences.default_filter_with_set_operations_for_globalid_and_class:
|
if (
|
||||||
|
preferences.chain_filter_with_set_operations
|
||||||
|
or preferences.default_filter_with_set_operations_for_globalid_and_class
|
||||||
|
):
|
||||||
mode = ifc_filter.filter_mode
|
mode = ifc_filter.filter_mode
|
||||||
else:
|
else:
|
||||||
mode = "FILTER" if group_results else "ADD"
|
mode = "FILTER" if group_results else "ADD"
|
||||||
@@ -219,11 +228,11 @@ class Search(bonsai.core.tool.Search):
|
|||||||
mode = ifc_filter.filter_mode
|
mode = ifc_filter.filter_mode
|
||||||
else:
|
else:
|
||||||
mode = "FILTER" if group_results else "ADD"
|
mode = "FILTER" if group_results else "ADD"
|
||||||
|
|
||||||
if mode == "ADD":
|
if mode == "ADD":
|
||||||
results = ifcopenshell.util.selector.filter_elements(tool.Ifc.get(), query)
|
results = ifcopenshell.util.selector.filter_elements(tool.Ifc.get(), query)
|
||||||
group_results.update(results)
|
group_results.update(results)
|
||||||
|
|
||||||
elif mode == "SUBTRACT":
|
elif mode == "SUBTRACT":
|
||||||
if group_results:
|
if group_results:
|
||||||
query_without_prefix = query[1:] if query.startswith("!") else query
|
query_without_prefix = query[1:] if query.startswith("!") else query
|
||||||
@@ -234,7 +243,7 @@ class Search(bonsai.core.tool.Search):
|
|||||||
else:
|
else:
|
||||||
results = ifcopenshell.util.selector.filter_elements(tool.Ifc.get(), query)
|
results = ifcopenshell.util.selector.filter_elements(tool.Ifc.get(), query)
|
||||||
group_results.update(results)
|
group_results.update(results)
|
||||||
|
|
||||||
elif mode == "FILTER":
|
elif mode == "FILTER":
|
||||||
if group_results:
|
if group_results:
|
||||||
results = ifcopenshell.util.selector.filter_elements(
|
results = ifcopenshell.util.selector.filter_elements(
|
||||||
@@ -244,14 +253,14 @@ class Search(bonsai.core.tool.Search):
|
|||||||
else:
|
else:
|
||||||
results = ifcopenshell.util.selector.filter_elements(tool.Ifc.get(), query)
|
results = ifcopenshell.util.selector.filter_elements(tool.Ifc.get(), query)
|
||||||
group_results.update(results)
|
group_results.update(results)
|
||||||
|
|
||||||
if group_results:
|
if group_results:
|
||||||
all_group_results.append(group_results)
|
all_group_results.append(group_results)
|
||||||
|
|
||||||
final_results = set()
|
final_results = set()
|
||||||
for group_results in all_group_results:
|
for group_results in all_group_results:
|
||||||
final_results.update(group_results)
|
final_results.update(group_results)
|
||||||
|
|
||||||
return final_results
|
return final_results
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@@ -259,24 +268,24 @@ class Search(bonsai.core.tool.Search):
|
|||||||
cls, data: dict, ifc_file: ifcopenshell.file
|
cls, data: dict, ifc_file: ifcopenshell.file
|
||||||
) -> set[ifcopenshell.entity_instance]:
|
) -> set[ifcopenshell.entity_instance]:
|
||||||
"""Execute filter groups from JSON data with filter_structure
|
"""Execute filter groups from JSON data with filter_structure
|
||||||
|
|
||||||
This is used by drawing include/exclude to properly handle ADD/SUBTRACT/FILTER modes
|
This is used by drawing include/exclude to properly handle ADD/SUBTRACT/FILTER modes
|
||||||
without needing to instantiate Blender property groups.
|
without needing to instantiate Blender property groups.
|
||||||
"""
|
"""
|
||||||
filter_structure = data.get("filter_structure", [])
|
filter_structure = data.get("filter_structure", [])
|
||||||
|
|
||||||
all_group_results = []
|
all_group_results = []
|
||||||
for group_data in filter_structure:
|
for group_data in filter_structure:
|
||||||
group_results = set()
|
group_results = set()
|
||||||
|
|
||||||
for filter_data in group_data:
|
for filter_data in group_data:
|
||||||
filter_mode = filter_data.get("filter_mode", "ADD")
|
filter_mode = filter_data.get("filter_mode", "ADD")
|
||||||
filter_type = filter_data.get("type", "")
|
filter_type = filter_data.get("type", "")
|
||||||
value = filter_data.get("value", "")
|
value = filter_data.get("value", "")
|
||||||
|
|
||||||
if not filter_type or not value:
|
if not filter_type or not value:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
query_part = None
|
query_part = None
|
||||||
if filter_type == "entity":
|
if filter_type == "entity":
|
||||||
query_part = value
|
query_part = value
|
||||||
@@ -318,10 +327,10 @@ class Search(bonsai.core.tool.Search):
|
|||||||
query_part = f"query:{keys}{comparison}{wrapped_value}"
|
query_part = f"query:{keys}{comparison}{wrapped_value}"
|
||||||
elif filter_type == "instance":
|
elif filter_type == "instance":
|
||||||
query_part = value
|
query_part = value
|
||||||
|
|
||||||
if not query_part:
|
if not query_part:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if filter_mode == "FILTER" and group_results:
|
if filter_mode == "FILTER" and group_results:
|
||||||
results = ifcopenshell.util.selector.filter_elements(ifc_file, query_part, elements=group_results)
|
results = ifcopenshell.util.selector.filter_elements(ifc_file, query_part, elements=group_results)
|
||||||
group_results = results
|
group_results = results
|
||||||
@@ -331,14 +340,14 @@ class Search(bonsai.core.tool.Search):
|
|||||||
else: # ADD
|
else: # ADD
|
||||||
results = ifcopenshell.util.selector.filter_elements(ifc_file, query_part)
|
results = ifcopenshell.util.selector.filter_elements(ifc_file, query_part)
|
||||||
group_results.update(results)
|
group_results.update(results)
|
||||||
|
|
||||||
if group_results:
|
if group_results:
|
||||||
all_group_results.append(group_results)
|
all_group_results.append(group_results)
|
||||||
|
|
||||||
final_results = set()
|
final_results = set()
|
||||||
for group_results in all_group_results:
|
for group_results in all_group_results:
|
||||||
final_results.update(group_results)
|
final_results.update(group_results)
|
||||||
|
|
||||||
return final_results
|
return final_results
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|||||||
Reference in New Issue
Block a user