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.
This commit is contained in:
Petru Conduraru
2026-07-13 16:06:38 +03:00
committed by Massimo Fabbro
parent f3cb7aea61
commit 99c370b755
+9 -1
View File
@@ -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