Fix #3253. Bug where duplicating elements with fillings incorrectly recreated fillings at the cursor (i.e. the cursor was used as a target destination).

Now, instead of trying to be clever and regenerating filling locations and opening types, we simply copy the existing scenario. This also means it'll be more stable for weird fillings coming from proprietary apps.
This commit is contained in:
Dion Moult
2023-08-13 20:07:33 +10:00
parent 782e38b561
commit 34c8e80cf0
2 changed files with 66 additions and 4 deletions
@@ -637,6 +637,11 @@ class OverrideDuplicateMove(bpy.types.Operator):
element = tool.Ifc.get_entity(obj) element = tool.Ifc.get_entity(obj)
if element and element.is_a("IfcAnnotation") and element.ObjectType == "DRAWING": if element and element.is_a("IfcAnnotation") and element.ObjectType == "DRAWING":
continue # For now, don't copy drawings until we stabilise a bit more. It's tricky. continue # For now, don't copy drawings until we stabilise a bit more. It's tricky.
# Prior to duplicating, sync the object placement to make decomposition recreation more stable.
if tool.Ifc.is_moved(obj):
blenderbim.core.geometry.edit_object_placement(tool.Ifc, tool.Geometry, tool.Surveyor, obj=obj)
new_obj = obj.copy() new_obj = obj.copy()
if obj.data: if obj.data:
new_obj.data = obj.data.copy() new_obj.data = obj.data.copy()
@@ -705,6 +710,10 @@ class OverrideDuplicateMoveLinked(bpy.types.Operator):
relationships = tool.Root.get_decomposition_relationships(context.selected_objects) relationships = tool.Root.get_decomposition_relationships(context.selected_objects)
old_to_new = {} old_to_new = {}
for obj in context.selected_objects: for obj in context.selected_objects:
# Prior to duplicating, sync the object placement to make decomposition recreation more stable.
if tool.Ifc.is_moved(obj):
blenderbim.core.geometry.edit_object_placement(tool.Ifc, tool.Geometry, tool.Surveyor, obj=obj)
new_obj = obj.copy() new_obj = obj.copy()
if obj.data: if obj.data:
new_obj.data = obj.data.copy() new_obj.data = obj.data.copy()
+57 -4
View File
@@ -23,6 +23,7 @@ import blenderbim.core.tool
import blenderbim.core.geometry import blenderbim.core.geometry
import blenderbim.tool as tool import blenderbim.tool as tool
from mathutils import Vector from mathutils import Vector
from blenderbim.bim.module.model.opening import FilledOpeningGenerator
class Root(blenderbim.core.tool.Root): class Root(blenderbim.core.tool.Root):
@@ -57,7 +58,10 @@ class Root(blenderbim.core.tool.Root):
if not source.Representation: if not source.Representation:
return return
dest.Representation = ifcopenshell.util.element.copy_deep( dest.Representation = ifcopenshell.util.element.copy_deep(
tool.Ifc.get(), source.Representation, exclude=["IfcGeometricRepresentationContext"], exclude_callback=exclude_callback tool.Ifc.get(),
source.Representation,
exclude=["IfcGeometricRepresentationContext"],
exclude_callback=exclude_callback,
) )
elif dest.is_a("IfcTypeProduct"): elif dest.is_a("IfcTypeProduct"):
if not source.RepresentationMaps: if not source.RepresentationMaps:
@@ -140,9 +144,58 @@ class Root(blenderbim.core.tool.Root):
for i, new_subelement in enumerate(new_subelements): for i, new_subelement in enumerate(new_subelements):
new_element = new_elements[i] new_element = new_elements[i]
if data["type"] == "fill": if data["type"] == "fill":
obj1 = tool.Ifc.get_object(new_element) element = new_element
obj2 = tool.Ifc.get_object(new_subelement) filling = new_subelement
bpy.ops.bim.add_filled_opening(voided_obj=obj1.name, filling_obj=obj2.name) voided_obj = tool.Ifc.get_object(new_element)
filling_obj = tool.Ifc.get_object(new_subelement)
existing_opening_occurrence = subelement.FillsVoids[0].RelatingOpeningElement
opening = ifcopenshell.api.run(
"root.copy_class", tool.Ifc.get(), product=existing_opening_occurrence
)
ifcopenshell.api.run(
"geometry.edit_object_placement",
tool.Ifc.get(),
product=opening,
matrix=ifcopenshell.util.placement.get_local_placement(opening.ObjectPlacement),
is_si=False,
)
representation = ifcopenshell.util.representation.get_representation(
existing_opening_occurrence, "Model", "Body", "MODEL_VIEW"
)
representation = ifcopenshell.util.representation.resolve_representation(representation)
mapped_representation = ifcopenshell.api.run(
"geometry.map_representation", tool.Ifc.get(), representation=representation
)
ifcopenshell.api.run(
"geometry.assign_representation",
tool.Ifc.get(),
product=opening,
representation=mapped_representation,
)
ifcopenshell.api.run("void.add_opening", tool.Ifc.get(), opening=opening, element=element)
ifcopenshell.api.run("void.add_filling", tool.Ifc.get(), opening=opening, element=filling)
voided_objs = [voided_obj]
# Openings affect all subelements of an aggregate
for subelement in ifcopenshell.util.element.get_decomposition(element):
subobj = tool.Ifc.get_object(subelement)
if subobj:
voided_objs.append(subobj)
for voided_obj in voided_objs:
if voided_obj.data:
representation = tool.Ifc.get().by_id(voided_obj.data.BIMMeshProperties.ifc_definition_id)
blenderbim.core.geometry.switch_representation(
tool.Ifc,
tool.Geometry,
obj=voided_obj,
representation=representation,
should_reload=True,
is_global=True,
should_sync_changes_first=False,
)
@classmethod @classmethod
def run_geometry_add_representation( def run_geometry_add_representation(