Compare commits

...

15 Commits

Author SHA1 Message Date
Ryan Schultz 7e3a9e4a75 Derive materials from selected objects in select_by_material
Previously only the explicit material prop was used. Now all
selected objects' materials are collected, with layer set usages
resolved to the specific layer index matching the clicked material.
Results are joined with " + " in the clipboard query.

Generated with the assistance of an AI coding tool.
2026-04-19 06:53:46 -05:00
Ryan Schultz 2a91d212b3 Deduplicate aggregates in select_aggregate clipboard query
All selected objects sharing the same aggregate would produce
duplicate entries in the clipboard query. Aggregates are now
collected into a dict keyed by id before selection and query
generation.

Generated with the assistance of an AI coding tool.
2026-04-19 06:53:46 -05:00
Ryan Schultz a14b02d32f Select from multiple containers in select_similar_container
Previously only the active object's container was used.
Now all selected objects' containers are collected and their
decomposed elements selected, with the query copied to the
clipboard as location = "A" + location = "B".

Generated with the assistance of an AI coding tool.
2026-04-19 06:53:46 -05:00
Ryan Schultz 20aa3ff94e Fix select_ifc_class clipboard query output
Previously the clipboard was set inside the class loop,
overwriting on each iteration and reporting multiple times.
Now all classes are joined with " + " and the clipboard is
set once after selection completes.

Generated with the assistance of an AI coding tool.
2026-04-19 06:53:46 -05:00
Ryan Schultz a2ec575618 Concatenate all selected values in select_similar
When multiple objects are selected, _generate_clipboard_query
previously only used the first reference value. Now all values
are joined with " + " so the clipboard query reflects every
selected object (e.g. GlobalId = "A" + GlobalId = "B").

Generated with the assistance of an AI coding tool.
2026-04-19 06:53:46 -05:00
Ryan Schultz f0d8a6f4f4 Add ALT+Click unhide to select_aggregate
When ALT is held, BIM_OT_select_aggregate now clears
hide_viewport and hide_set on matched objects before
selecting, consistent with the pattern used across other
selection operators on this branch.

Generated with the assistance of an AI coding tool.
2026-04-19 06:49:12 -05:00
Ryan Schultz 2ad30a00d7 Add container tools to spatial decomposition panel
- Add bim.select_similar_container button to the spatial
  decomposition panel, gated behind the new
  show_container_tools preference (renamed from
  container_hide_show_isolate)
- Fix select_similar_container to resolve container from
  the active list item rather than the active object
- Unhide individual objects when showing container
  visibility (set_container_visibility SHOW/ISOLATE)

Generated with the assistance of an AI coding tool.
2026-03-20 20:06:53 -05:00
Ryan Schultz e3d5e1d1fe Unhide objects when showing container visibility
When mode is SHOW or ISOLATE, also unhide individual
objects (hide_viewport and hide_set) within each
container, not just the collection-level visibility.

Generated with the assistance of an AI coding tool.
2026-03-20 19:38:57 -05:00
Ryan Schultz 15228ac8b5 Add ALT+Click unhide to select_decomposed_elements
Moves "select all listed elements" from ALT to SHIFT,
freeing ALT+Click to unhide hidden objects (viewport
and local hide) before selecting.

Generated with the assistance of an AI coding tool.
2026-03-20 19:20:43 -05:00
Ryan Schultz 011fb6660a Add ALT+Click unhide to select_linked_aggregates
ALT+Click now unhides hidden objects (viewport and local
hide) before selecting, matching the behavior added to
other select operators.

Generated with the assistance of an AI coding tool.
2026-03-20 19:06:04 -05:00
Ryan Schultz cd458780e6 Add ALT+Click unhide to select_by_material
ALT+Click now unhides hidden objects (viewport and local
hide) before selecting, matching the behavior added to
other select operators.

Generated with the assistance of an AI coding tool.
2026-03-20 19:00:47 -05:00
Ryan Schultz 873f9f061f Add ALT+Click unhide to select_similar_container
ALT+Click now unhides hidden objects (viewport and local
hide) before selecting. Also fixes select_products to set
hide_viewport in addition to hide_set when unhiding.

Generated with the assistance of an AI coding tool.
2026-03-20 18:54:43 -05:00
Ryan Schultz ea27b4f3ae Add ALT+Click unhide to select_similar_type
ALT+Click now unhides hidden objects (viewport and local
hide) before selecting, matching the behavior added to
select_ifc_class and select_similar.

Generated with the assistance of an AI coding tool.
2026-03-20 12:33:51 -05:00
Ryan Schultz 1ce62c948c Add ALT+Click unhide to select_similar
ALT+Click now unhides hidden objects (viewport and local
hide) before selecting, matching the same behavior added
to select_ifc_class.

Generated with the assistance of an AI coding tool.
2026-03-20 12:30:11 -05:00
Ryan Schultz f327a999d0 Closes #7780 - Add ALT+Click unhide to select_ifc_class
Clear hide_viewport and hide_set on matched objects
when the operator is invoked with Alt held, so hidden
objects of the target IFC class are revealed and selected.

Generated with the assistance of an AI coding tool.
2026-03-20 12:20:15 -05:00
10 changed files with 229 additions and 62 deletions
@@ -266,33 +266,37 @@ class BIM_OT_select_aggregate(bpy.types.Operator):
one_level_deep: bpy.props.BoolProperty(
name="One Level Deep", description="Select only immediate children, not recursively", default=False
)
should_unhide: bpy.props.BoolProperty(default=False, options={"SKIP_SAVE"})
@classmethod
def description(cls, context, properties):
if properties.select_parts:
return "Select Aggregate and Parts.\n\nCtrl+click to select only one level deep"
return "Select Aggregate and Parts.\n\nCtrl+click to select only one level deep\nALT+Click to also unhide hidden objects (viewport and local hide)"
else:
return "Select Aggregate"
return "Select Aggregate\n\nALT+Click to also unhide hidden objects (viewport and local hide)"
def invoke(self, context, event):
if event.type == "LEFTMOUSE" and event.ctrl:
self.one_level_deep = True
self.should_unhide = event.alt
return self.execute(context)
def execute(self, context):
all_parts = []
aggregates = {}
for obj in context.selected_objects:
element = tool.Ifc.get_entity(obj)
if element:
aggregate = ifcopenshell.util.element.get_aggregate(element)
if aggregate:
all_parts.append(aggregate)
aggregates[aggregate.id()] = aggregate
obj.select_set(False)
else:
pass
if not element:
obj.select_set(False)
all_parts = list(aggregates.values())
if self.select_parts:
selected_parts = []
@@ -317,12 +321,18 @@ class BIM_OT_select_aggregate(bpy.types.Operator):
for element in set(selected_parts + all_parts):
obj = tool.Ifc.get_object(element)
if obj:
if self.should_unhide:
obj.hide_viewport = False
obj.hide_set(False)
obj.select_set(True)
else:
for aggregate_element in all_parts:
aggregate_obj = tool.Ifc.get_object(aggregate_element)
if aggregate_obj:
if self.should_unhide:
aggregate_obj.hide_viewport = False
aggregate_obj.hide_set(False)
aggregate_obj.select_set(True)
bpy.context.view_layer.objects.active = aggregate_obj
@@ -407,13 +417,18 @@ class BIM_OT_select_linked_aggregates(bpy.types.Operator):
bl_label = "Select linked aggregates"
bl_options = {"REGISTER", "UNDO"}
select_parts: bpy.props.BoolProperty(default=False)
should_unhide: bpy.props.BoolProperty(default=False, options={"SKIP_SAVE"})
@classmethod
def description(cls, context, properties):
if properties.select_parts:
return "Select all aggregates, subaggregates and all their parts"
return "Select all aggregates, subaggregates and all their parts\n\nALT+Click to also unhide hidden objects (viewport and local hide)"
else:
return "Select all aggregates"
return "Select all aggregates\n\nALT+Click to also unhide hidden objects (viewport and local hide)"
def invoke(self, context, event):
self.should_unhide = event.alt
return self.execute(context)
def execute(self, context):
for obj in context.selected_objects:
@@ -446,11 +461,18 @@ class BIM_OT_select_linked_aggregates(bpy.types.Operator):
for element in parts_objs:
obj = tool.Ifc.get_object(element)
if obj:
if self.should_unhide:
obj.hide_viewport = False
obj.hide_set(False)
obj.select_set(True)
else:
for element in parts:
obj = tool.Ifc.get_object(element)
obj.select_set(True)
if obj:
if self.should_unhide:
obj.hide_viewport = False
obj.hide_set(False)
obj.select_set(True)
return {"FINISHED"}
@@ -61,25 +61,108 @@ class DisableEditingMaterials(bpy.types.Operator):
class SelectByMaterial(bpy.types.Operator):
bl_idname = "bim.select_by_material"
bl_label = "Select By Material"
bl_description = "Select objects using the provided material"
bl_description = "Select objects using the provided material\n\nALT+Click to also unhide hidden objects (viewport and local hide)"
bl_options = {"REGISTER", "UNDO"}
material: bpy.props.IntProperty()
should_unhide: bpy.props.BoolProperty(default=False, options={"SKIP_SAVE"})
def invoke(self, context, event):
self.should_unhide = event.alt
return self.execute(context)
def execute(self, context):
material = tool.Ifc.get().by_id(self.material)
core.select_by_material(tool.Material, tool.Spatial, material=material)
# Determine the layer index hint from the explicit material prop, if any.
# When the user clicks a specific layer in the UI, self.material is that
# layer's IfcMaterial. We find its index so we can pull the same layer
# from every other selected object's layer set.
layer_index = None
if self.material:
ref_mat = tool.Ifc.get().by_id(self.material)
layer_index = self._get_layer_index(ref_mat)
# copy selection query to clipboard
if material.is_a("IfcMaterialLayerSet"):
material_name = material.LayerSetName
else:
material_name = material.Name
result = f'material="{material_name}"'
materials = {}
for obj in context.selected_objects:
element = tool.Ifc.get_entity(obj)
if not element:
continue
mat = ifcopenshell.util.element.get_material(element)
if not mat:
continue
resolved = self._resolve_material(mat, layer_index)
if resolved:
materials[resolved.id()] = resolved
# Fall back to the explicit material prop if selection yields nothing
if not materials and self.material:
materials = {self.material: tool.Ifc.get().by_id(self.material)}
if not materials:
return {"FINISHED"}
for mat in materials.values():
core.select_by_material(tool.Material, tool.Spatial, material=mat, should_unhide=self.should_unhide)
result = " + ".join(f'material = "{self._get_name(m)}"' for m in materials.values())
bpy.context.window_manager.clipboard = result
self.report({"INFO"}, f"({result}) was copied to the clipboard.")
return {"FINISHED"}
def _get_layer_index(self, material):
"""Return the 0-based layer index if material is an IfcMaterial inside a layer set."""
if not material.is_a("IfcMaterial"):
return None
ifc = tool.Ifc.get()
for layer in ifc.get_inverse(material):
if not layer.is_a("IfcMaterialLayer"):
continue
for layer_set in ifc.get_inverse(layer):
if not layer_set.is_a("IfcMaterialLayerSet"):
continue
layers = list(layer_set.MaterialLayers)
if layer in layers:
return layers.index(layer)
return None
def _resolve_material(self, mat, layer_index):
"""Resolve an assigned material to the specific entity to select/name by.
When layer_index is set, drills into the layer set and returns the
IfcMaterial at that index (or None if the set has fewer layers).
Otherwise returns the layer set / profile set / constituent set itself.
"""
if mat.is_a("IfcMaterialLayerSetUsage"):
mat = mat.ForLayerSet
elif mat.is_a("IfcMaterialProfileSetUsage"):
mat = mat.ForProfileSet
if layer_index is not None and mat.is_a("IfcMaterialLayerSet"):
layers = list(mat.MaterialLayers)
if layer_index < len(layers):
return layers[layer_index].Material
return None
return mat
def _get_name(self, material):
if material.is_a("IfcMaterialLayerSet"):
if material.LayerSetName:
return material.LayerSetName
names = [l.Material.Name for l in (material.MaterialLayers or []) if l.Material and l.Material.Name]
return ", ".join(names) if names else material.is_a()
if material.is_a("IfcMaterialProfileSet"):
if material.Name:
return material.Name
names = [p.Material.Name for p in (material.MaterialProfiles or []) if p.Material and p.Material.Name]
return ", ".join(names) if names else material.is_a()
if material.is_a("IfcMaterialConstituentSet"):
if material.Name:
return material.Name
names = [c.Material.Name for c in (material.MaterialConstituents or []) if c.Material and c.Material.Name]
return ", ".join(names) if names else material.is_a()
return getattr(material, "Name", None) or material.is_a()
class EnableEditingMaterial(bpy.types.Operator):
bl_idname = "bim.enable_editing_material"
+33 -21
View File
@@ -1264,15 +1264,17 @@ class SelectGlobalId(Operator):
class SelectIfcClass(Operator):
"""Click to select all objects that match with the given IFC class\nSHIFT + Click to also match Predefined Type"""
"""Click to select all objects that match with the given IFC class\nSHIFT + Click to also match Predefined Type\nALT + Click to also unhide hidden objects (viewport and local hide)"""
bl_idname = "bim.select_ifc_class"
bl_label = "Select IFC Class"
bl_options = {"REGISTER", "UNDO"}
should_filter_predefined_type: BoolProperty(default=False)
should_unhide: BoolProperty(default=False)
def invoke(self, context, event):
self.should_filter_predefined_type = event.shift
self.should_unhide = event.alt
return self.execute(context)
def execute(self, context):
@@ -1283,7 +1285,6 @@ class SelectIfcClass(Operator):
if element := tool.Ifc.get_entity(obj):
classes.add(element.is_a())
predefined_types.add(ifcopenshell.util.element.get_predefined_type(element))
result = ""
for cls in classes:
for element in tool.Ifc.get().by_type(cls):
if (
@@ -1292,15 +1293,15 @@ class SelectIfcClass(Operator):
):
continue
if obj := tool.Ifc.get_object(element):
if self.should_unhide:
obj.hide_viewport = False
obj.hide_set(False)
tool.Blender.select_object(obj)
# copy selection query to clipboard
if not result:
result = f"{cls}"
else:
result += f", {cls}"
bpy.context.window_manager.clipboard = result
self.report({"INFO"}, f"({result}) was copied to the clipboard.")
# copy selection query to clipboard
result = " + ".join(classes)
bpy.context.window_manager.clipboard = result
self.report({"INFO"}, f"({result}) was copied to the clipboard.")
return {"FINISHED"}
@@ -1451,10 +1452,11 @@ class SelectSimilar(Operator):
)
calculated_sum: bpy.props.FloatProperty(name="Calculated Sum", default=0.0)
remove_from_selection: bpy.props.BoolProperty(default=False, options={"SKIP_SAVE"})
should_unhide: bpy.props.BoolProperty(default=False, options={"SKIP_SAVE"})
@classmethod
def description(cls, context, properties):
base = "Select objects with a similar value\n\n" "SHIFT+CLICK remove from selection set."
base = "Select objects with a similar value\n\nSHIFT+CLICK remove from selection set.\nALT+CLICK also unhide hidden objects (viewport and local hide)."
key = getattr(properties, "key", None)
active = context.active_object
@@ -1481,6 +1483,7 @@ class SelectSimilar(Operator):
def invoke(self, context, event):
self.calculate_sum = event.ctrl and event.type == "LEFTMOUSE"
self.remove_from_selection = event.shift and event.type == "LEFTMOUSE"
self.should_unhide = event.alt
return self.execute(context)
def execute(self, context):
@@ -1512,7 +1515,7 @@ class SelectSimilar(Operator):
f"{verb} all objects that share the same ({self.key}) value(s) from {len(reference_values)} reference object(s).",
)
self._generate_clipboard_query(reference_values[0] if reference_values else None, key)
self._generate_clipboard_query(reference_values, key)
return {"FINISHED"}
@@ -1538,11 +1541,15 @@ class SelectSimilar(Operator):
def _select_objects(self, context, key, reference_values, tolerance):
count = 0
for obj in context.visible_objects:
objects = context.scene.objects if self.should_unhide else context.visible_objects
for obj in objects:
obj_value = self._get_value(obj, key)
if obj_value is None:
continue
if any(self._compare_values(obj_value, ref_value, tolerance) for ref_value in reference_values):
if self.should_unhide:
obj.hide_viewport = False
obj.hide_set(False)
obj.select_set(not self.remove_from_selection)
count += 1
return count
@@ -1557,17 +1564,22 @@ class SelectSimilar(Operator):
bpy.context.window_manager.clipboard = str(total)
self.report({"INFO"}, f"({total}) was copied to the clipboard.")
def _generate_clipboard_query(self, value, key):
def _generate_clipboard_query(self, values, key):
key = "PredefinedType" if key == "predefined_type" else key
if value is True:
value = "TRUE"
elif value is False:
value = "FALSE"
if not values:
return
if isinstance(value, list) and value:
result = ", ".join(f'{key} = "{item}"' for item in value)
else:
result = f'{key} = "{value}"'
def format_value(value):
if value is True:
return f'{key} = "TRUE"'
elif value is False:
return f'{key} = "FALSE"'
elif isinstance(value, list) and value:
return ", ".join(f'{key} = "{item}"' for item in value)
else:
return f'{key} = "{value}"'
result = " + ".join(format_value(v) for v in values)
bpy.context.window_manager.clipboard = result
self.report({"INFO"}, f"({result}) was copied to the clipboard.")
@@ -284,23 +284,48 @@ class SelectContainer(bpy.types.Operator):
class SelectSimilarContainer(bpy.types.Operator):
bl_idname = "bim.select_similar_container"
bl_label = "Select Similar Container"
bl_description = "Recurvisevly selects all objects in the container.\n\nCtrl+click to select only one level deep"
bl_description = "Recursively selects all objects in the container.\n\nCtrl+click to select only one level deep\nAlt+click to also unhide hidden objects (viewport and local hide)"
bl_options = {"REGISTER", "UNDO"}
container: bpy.props.IntProperty(default=0)
is_recursive: bpy.props.BoolProperty(default=True)
should_unhide: bpy.props.BoolProperty(default=False, options={"SKIP_SAVE"})
def invoke(self, context, event):
if event.type == "LEFTMOUSE" and event.ctrl:
self.is_recursive = False
self.should_unhide = event.alt
return self.execute(context)
def execute(self, context):
core.select_similar_container(
tool.Ifc,
tool.Spatial,
obj=context.active_object,
is_recursive=self.is_recursive,
)
if self.container:
# Called from container manager panel with explicit container
ifc_container = tool.Ifc.get().by_id(self.container)
containers = {ifc_container.id(): ifc_container} if ifc_container else {}
else:
# Called from 3D viewport — derive containers from all selected objects
containers = {}
for obj in context.selected_objects or [context.active_object]:
element = tool.Ifc.get_entity(obj)
if not element:
continue
container = tool.Spatial.get_container(element)
if container:
containers[container.id()] = container
if not containers:
return {"CANCELLED"}
for container in containers.values():
tool.Spatial.select_products(
tool.Spatial.get_decomposed_elements(container, self.is_recursive),
unhide=self.should_unhide,
)
result = " + ".join(f'location = "{c.Name}"' for c in containers.values())
bpy.context.window_manager.clipboard = result
self.report({"INFO"}, f"({result}) was copied to the clipboard.")
self.is_recursive = True # <-- forcibly reset
return {"FINISHED"}
@@ -425,24 +450,29 @@ class SelectDecomposedElements(bpy.types.Operator):
should_filter: bpy.props.BoolProperty(name="Should Filter", default=True, options={"SKIP_SAVE"})
container: bpy.props.IntProperty()
is_recursive: bpy.props.BoolProperty(default=True, options={"SKIP_SAVE"})
should_unhide: bpy.props.BoolProperty(default=False, options={"SKIP_SAVE"})
@classmethod
def description(cls, context, operator):
return (
"Select the active item"
+ "\nALT+CLICK to select all listed elements.\nCTRL + CLICK to select only one level deep"
+ "\nSHIFT+CLICK to select all listed elements.\nCTRL+CLICK to select only one level deep"
+ "\nALT+CLICK to also unhide hidden objects (viewport and local hide)"
)
def invoke(self, context, event):
if event.type == "LEFTMOUSE":
if event.alt:
if event.shift:
self.should_filter = False
if event.ctrl:
self.is_recursive = False
self.should_unhide = event.alt
return self.execute(context)
def execute(self, context):
tool.Spatial.select_products(tool.Spatial.get_filtered_elements(self.should_filter, self.is_recursive))
tool.Spatial.select_products(
tool.Spatial.get_filtered_elements(self.should_filter, self.is_recursive), unhide=self.should_unhide
)
# Make selected active element in list, the active object
props = tool.Spatial.get_spatial_props()
@@ -525,6 +555,11 @@ class SetContainerVisibility(bpy.types.Operator):
if obj := tool.Ifc.get_object(container):
if collection := tool.Blender.get_object_bim_props(obj).collection:
collection.hide_viewport = should_hide
if not should_hide:
for element in tool.Spatial.get_decomposed_elements(container, is_recursive=False):
if element_obj := tool.Ifc.get_object(element):
element_obj.hide_viewport = False
element_obj.hide_set(False)
if self.should_include_children:
queue.extend(ifcopenshell.util.element.get_parts(container))
return {"FINISHED"}
+5 -2
View File
@@ -139,7 +139,7 @@ class BIM_PT_spatial_decomposition(Panel):
op = col.operator("bim.set_default_container", icon="OUTLINER_COLLECTION", text="Set Default")
op.container = ifc_definition_id
if tool.Blender.get_addon_preferences().container_hide_show_isolate:
if tool.Blender.get_addon_preferences().show_container_tools:
op = row.operator("bim.set_container_visibility", icon="FULLSCREEN_EXIT", text="")
op.mode = "ISOLATE"
op.container = ifc_definition_id
@@ -152,7 +152,10 @@ class BIM_PT_spatial_decomposition(Panel):
# The only operator that's enabled for IfcProject.
col = row.column(align=True)
col.operator("bim.select_container", icon="OBJECT_DATA", text="").container = ifc_definition_id
row_ = col.row(align=True)
row_.operator("bim.select_container", icon="OBJECT_DATA", text="").container = ifc_definition_id
if tool.Blender.get_addon_preferences().show_container_tools:
row_.operator("bim.select_similar_container", icon="RESTRICT_SELECT_OFF", text="").container = ifc_definition_id
col = row.column(align=True)
op = col.operator("bim.delete_container", icon="X", text="")
+11 -1
View File
@@ -221,10 +221,17 @@ class SelectType(bpy.types.Operator):
class SelectSimilarType(bpy.types.Operator):
"""Select Similar Type\nALT+Click to also unhide hidden objects (viewport and local hide)"""
bl_idname = "bim.select_similar_type"
bl_label = "Select Similar Type"
bl_options = {"REGISTER", "UNDO"}
related_object: bpy.props.StringProperty()
should_unhide: bpy.props.BoolProperty(default=False, options={"SKIP_SAVE"})
def invoke(self, context, event):
self.should_unhide = event.alt
return self.execute(context)
def execute(self, context):
self.file = tool.Ifc.get()
@@ -246,7 +253,10 @@ class SelectSimilarType(bpy.types.Operator):
for element in related_objects:
obj = tool.Ifc.get_object(element)
if obj and obj in context.visible_objects:
if obj and (self.should_unhide or obj in context.visible_objects):
if self.should_unhide:
obj.hide_viewport = False
obj.hide_set(False)
obj.select_set(True)
# copy selection query to clipboard
+5 -5
View File
@@ -714,9 +714,9 @@ class BIM_ADDON_preferences(bpy.types.AddonPreferences):
description="Default parameters for BIM elements",
)
container_hide_show_isolate: BoolProperty(
name="Container hide/show/isolate",
description="Enable container hide/show/isolate feature in the UI",
show_container_tools: BoolProperty(
name="Show Container Tools (Select, Hide, Show, Isolate)",
description="Enable container select, hide/show/isolate tools in the UI",
default=False,
)
@@ -786,7 +786,7 @@ class BIM_ADDON_preferences(bpy.types.AddonPreferences):
pset_dir: str
doc: DocPreferences
default_parameters: DefaultParameters
container_hide_show_isolate: bool
show_container_tools: bool
chain_filter_with_set_operations: bool
save_metadata_blend_file: bool
metadata_blend_file_suffix: str
@@ -984,7 +984,7 @@ class BIM_ADDON_preferences(bpy.types.AddonPreferences):
layout.prop(self, "bsdd_baseurl")
def draw_extras_settings(self, layout: bpy.types.UILayout, context: bpy.types.Context) -> None:
layout.prop(self, "container_hide_show_isolate")
layout.prop(self, "show_container_tools")
row = layout.row(align=True)
row.prop(self, "chain_filter_with_set_operations")
row.operator("bim.open_uri", text="", icon="HELP").uri = "https://community.osarch.org/discussion/3270"
+5 -2
View File
@@ -82,9 +82,12 @@ def disable_editing_materials(material: type[tool.Material]) -> None:
def select_by_material(
material_tool: type[tool.Material], spatial: type[tool.Spatial], material: ifcopenshell.entity_instance
material_tool: type[tool.Material],
spatial: type[tool.Spatial],
material: ifcopenshell.entity_instance,
should_unhide: bool = False,
) -> None:
spatial.select_products(material_tool.get_elements_by_material(material))
spatial.select_products(material_tool.get_elements_by_material(material), unhide=should_unhide)
def enable_editing_material(material_tool: type[tool.Material], material: ifcopenshell.entity_instance) -> None:
+3 -5
View File
@@ -120,14 +120,12 @@ def select_container(
def select_similar_container(
ifc: type[tool.Ifc],
spatial: type[tool.Spatial],
obj: bpy.types.Object,
container: ifcopenshell.entity_instance,
is_recursive: bool = True,
should_unhide: bool = False,
) -> None:
element = ifc.get_entity(obj)
if element:
spatial.select_products(spatial.get_decomposed_elements(spatial.get_container(element), is_recursive))
spatial.select_products(spatial.get_decomposed_elements(container, is_recursive), unhide=should_unhide)
def select_product(spatial: type[tool.Spatial], product: ifcopenshell.entity_instance) -> None:
+1
View File
@@ -200,6 +200,7 @@ class Spatial(bonsai.core.tool.Spatial):
obj = tool.Ifc.get_object(product)
if obj and view_layer.objects.get(obj.name):
if unhide:
obj.hide_viewport = False
obj.hide_set(False)
obj.select_set(True)