Fix #6392: when duplicating a window/door/etc, the associated IfcOpenElement duplicates as well.

Also when `bim.append_library_element` it copies the IfcOpenElement, as well.
This commit is contained in:
Ryan Schultz
2025-12-13 09:37:56 -06:00
parent 276c9c9833
commit a2a5780d59
3 changed files with 199 additions and 31 deletions
@@ -611,6 +611,8 @@ class AppendLibraryElement(bpy.types.Operator, tool.Ifc.Operator):
if not element:
return {"FINISHED"}
if element.is_a("IfcTypeProduct"):
# Store opening template from library if it exists
self.store_opening_template_from_library(element, library_file)
self.import_type_from_ifc(element, context)
elif element.is_a("IfcProduct"):
# NOTE: Non-types are not exposed in UI directly
@@ -712,6 +714,56 @@ class AppendLibraryElement(bpy.types.Operator, tool.Ifc.Operator):
ifc_importer.create_style(element)
def store_opening_template_from_library(
self,
element: ifcopenshell.entity_instance,
library_file: ifcopenshell.file
) -> None:
"""
Find an opening representation in the library and copy it to the current file
as a template. Store the template ID on the type for later retrieval.
"""
try:
library_element = library_file.by_guid(element.GlobalId)
except:
return
# Find occurrences with openings in the library
library_occurrences = ifcopenshell.util.element.get_types(library_element)
for occurrence in library_occurrences:
if not getattr(occurrence, "FillsVoids", None):
continue
library_opening = occurrence.FillsVoids[0].RelatingOpeningElement
library_opening_rep = ifcopenshell.util.representation.get_representation(
library_opening, "Model", "Body", "MODEL_VIEW"
)
if not library_opening_rep:
continue
# Check if mapped representation
if (library_opening_rep.RepresentationType == 'MappedRepresentation' and
len(library_opening_rep.Items) == 1 and
library_opening_rep.Items[0].is_a("IfcMappedItem")):
mapped_rep = library_opening_rep.Items[0].MappingSource.MappedRepresentation
# Store ALL representation types (Tessellation, SweptSolid, etc.)
template_rep = ifcopenshell.util.element.copy_deep(
self.file,
mapped_rep,
exclude=["IfcGeometricRepresentationContext"]
)
# Store reference in type's Description
current_desc = element.Description or ""
element.Description = f"{current_desc}||BonsaiOpeningTemplate:{template_rep.id()}"
return
break
class EditProjectLibrary(bpy.types.Operator):
bl_idname = "bim.edit_project_library"
bl_label = "Edit Project Library"