Bonsai: skip out-of-view-layer spaces in toggle_hide_spaces (#5309)

Toggling space visibility crashed with
`RuntimeError: Object 'IfcSpace/...' cannot be hidden because it is not in
View Layer 'ViewLayer'!` when a space object lived in a collection excluded
from the active view layer. tool.Spatial.toggle_hide_spaces called
hide_get/hide_set unconditionally; Blender raises for any object not in the
active view layer. The rest of spatial.py already guards these calls via
view_layer.objects.get(obj.name); this method was the outlier.

Filter the spaces to objects present in the active view layer, derive the
toggle direction from the first surviving object, and apply hide_set only
to those. Objects not in the view layer are skipped (they cannot be hidden
anyway). Also returns cleanly when nothing is toggleable.

Verified live in headless Blender: with one space in an excluded
collection, the old code raised the reported RuntimeError; the fix
completes, hides the in-view-layer space, and skips the excluded one. Core
test_spatial.py: 12 passed.

Generated with the assistance of an AI coding tool.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Petru Conduraru
2026-07-12 09:14:04 +03:00
parent 0b7e25a3ef
commit 4d38c8ad18
+12 -11
View File
@@ -1258,19 +1258,20 @@ class Spatial(bonsai.core.tool.Spatial):
@classmethod
def toggle_hide_spaces(cls, spaces: list[ifcopenshell.entity_instance]) -> None:
first_obj = tool.Ifc.get_object(spaces[0])
assert isinstance(first_obj, bpy.types.Object)
obj: bpy.types.Object
if first_obj.hide_get() == False:
for space in spaces:
obj = tool.Ifc.get_object(space)
obj.hide_set(True)
# `hide_get`/`hide_set` raise for objects that are not in the active view
# layer (e.g. spaces living in an excluded collection), so skip those.
view_layer = bpy.context.view_layer
objs = [
obj
for space in spaces
if isinstance(obj := tool.Ifc.get_object(space), bpy.types.Object) and view_layer.objects.get(obj.name)
]
if not objs:
return
elif first_obj.hide_get() == True:
for space in spaces:
obj = tool.Ifc.get_object(space)
obj.hide_set(False)
should_hide = objs[0].hide_get() == False
for obj in objs:
obj.hide_set(should_hide)
@classmethod
def set_default_container(cls, container: ifcopenshell.entity_instance) -> None: