This commit is contained in:
Andrej730
2025-12-19 17:34:09 +05:00
parent f2eb777b3b
commit 2c3281917a
5 changed files with 165 additions and 159 deletions
@@ -304,8 +304,7 @@ class CreateDrawing(bpy.types.Operator):
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))
@@ -3739,11 +3738,7 @@ 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
+42 -40
View File
@@ -80,7 +80,7 @@ def update_filter_search_value(self: "FilterValueSuggestions", context: bpy.type
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:
@@ -239,20 +239,20 @@ class FilterValueSuggestions(Operator):
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
@@ -282,7 +282,7 @@ class FilterValueSuggestions(Operator):
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)
@@ -347,11 +347,11 @@ class FilterValueSuggestions(Operator):
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:
@@ -362,7 +362,7 @@ class FilterValueSuggestions(Operator):
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
@@ -376,7 +376,7 @@ 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)
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()
@@ -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
@@ -496,7 +500,7 @@ class FilterValueSuggestions(Operator):
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)
@@ -618,7 +622,7 @@ class ApplyFilterFromText(Operator, tool.Ifc.Operator):
@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
@@ -630,7 +634,7 @@ class ApplyFilterFromText(Operator, tool.Ifc.Operator):
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_", "")
@@ -646,9 +650,9 @@ class ApplyFilterFromText(Operator, tool.Ifc.Operator):
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):
@@ -700,11 +704,7 @@ class EditFilterQuery(Operator, tool.Ifc.Operator):
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)
@@ -718,19 +718,21 @@ class EditFilterQuery(Operator, tool.Ifc.Operator):
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)
@@ -763,7 +765,10 @@ class Search(Operator):
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"]:
@@ -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(
( (
@@ -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)
+1 -1
View File
@@ -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:
+12 -3
View File
@@ -132,7 +132,10 @@ class Search(bonsai.core.tool.Search):
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}"
@@ -141,7 +144,10 @@ class Search(bonsai.core.tool.Search):
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}"
@@ -210,7 +216,10 @@ class Search(bonsai.core.tool.Search):
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"