From 99c370b75517924beabcbca86a82e5c5e01f45c4 Mon Sep 17 00:00:00 2001 From: Petru Conduraru Date: Mon, 13 Jul 2026 16:06:38 +0300 Subject: [PATCH] Bonsai: allow nesting element type objects together (#2283) can_nest() only permitted IfcElement-to-IfcElement pairs, so nesting two IfcElementType objects (e.g. an IfcElementAssemblyType nesting a component IfcDoorType) was silently rejected. IfcRelNests.RelatingObject/ RelatedObjects are typed as the general IfcObjectDefinition in the schema, so type-to-type nesting is schema legal, IfcOpenShell's core nest.assign_object API already handles it generically, and the Nest UI panel is driven purely by ifcopenshell.util.element.get_nest/ get_components (IFC data queries, not Blender collection structure), so once the relationship exists it displays correctly with no other changes needed. Extended is_compatible_class to also accept a same-kind IfcTypeProduct pair. Mixing an occurrence element with a type is intentionally still rejected, that isn't a real modeling pattern. Verified live in headless Blender: type-to-type nesting now creates a real IfcRelNests and the Nest panel's own data functions reflect it correctly; mixing an occurrence with a type is still rejected; existing element-to-element nesting is unaffected. Generated with the assistance of an AI coding tool. --- src/bonsai/bonsai/tool/nest.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/bonsai/bonsai/tool/nest.py b/src/bonsai/bonsai/tool/nest.py index 5a1b2c83b2..adfb35da21 100644 --- a/src/bonsai/bonsai/tool/nest.py +++ b/src/bonsai/bonsai/tool/nest.py @@ -47,7 +47,15 @@ class Nest(bonsai.core.tool.Nest): return False if relating_object == related_object: return False - is_compatible_class = relating_object.is_a("IfcElement") and related_object.is_a("IfcElement") + # IfcRelNests.RelatingObject/RelatedObjects are typed as the general + # IfcObjectDefinition, so nesting is schema-legal both between element + # occurrences (the common case, e.g. a faucet nested into a sink) and + # between element types (e.g. an assembly type nesting its component + # types). Mixing an occurrence with a type isn't a real modeling + # pattern, so only allow same-kind pairs. See #2283. + is_compatible_class = (relating_object.is_a("IfcElement") and related_object.is_a("IfcElement")) or ( + relating_object.is_a("IfcTypeProduct") and related_object.is_a("IfcTypeProduct") + ) if not is_compatible_class: return False # Prevent cyclic references: walk up the full hierarchy from the