Support duplicating potential openings and potential/existing booleans

This commit is contained in:
Andrej730
2025-01-15 15:58:13 +05:00
parent cfb4cd8af9
commit d6da8a7ee1
6 changed files with 28 additions and 12 deletions
@@ -983,7 +983,9 @@ class OverrideDuplicateMove(bpy.types.Operator):
OverrideDuplicateMove.duplicate_item(self, obj)
continue
linked_non_ifc_object = linked and not element
tracked_opening_type = tool.Model.get_tracked_opening_type(obj)
is_tracked_opening = bool(tracked_opening_type)
keep_data_linked = linked and not element and not is_tracked_opening
# Prior to duplicating, sync the object placement to make decomposition recreation more stable.
if tool.Ifc.is_moved(obj):
@@ -1000,11 +1002,17 @@ class OverrideDuplicateMove(bpy.types.Operator):
if tool.Ifc.is_edited(obj, ignore_scale=True):
tool.Ifc.edit(new_obj)
if obj.data and not linked_non_ifc_object:
if obj.data and not keep_data_linked:
# assure root.copy_class won't replace the previous mesh globally
temp_data = obj.data.copy()
new_obj.data = temp_data
# Unlink from previous boolean element
# and keep object tracked for decorations.
if is_tracked_opening:
new_obj.data.BIMMeshProperties.ifc_boolean_id = 0
tool.Root.add_tracked_opening(new_obj, tracked_opening_type)
if obj == context.active_object:
self.new_active_obj = new_obj
for collection in obj.users_collection:
@@ -1012,7 +1020,7 @@ class OverrideDuplicateMove(bpy.types.Operator):
obj.select_set(False)
new_obj.select_set(True)
if linked_non_ifc_object:
if not element:
continue
# clear object's collection so it will be able to have it's own
@@ -489,7 +489,7 @@ class AddPotentialOpening(Operator, AddObjectHelper):
obj.matrix_world = new_matrix
tool.Model.purge_scene_openings()
tool.Root.add_tracked_opening(obj)
tool.Root.add_tracked_opening(obj, "OPENING")
DecorationsHandler.install(context)
return {"FINISHED"}
@@ -513,7 +513,7 @@ class AddPotentialHalfSpaceSolid(Operator, AddObjectHelper):
obj.name = "HalfSpaceSolid"
tool.Model.purge_scene_openings()
tool.Root.add_tracked_opening(obj)
tool.Root.add_tracked_opening(obj, "BOOLEAN")
DecorationsHandler.install(context)
return {"FINISHED"}
@@ -663,7 +663,7 @@ class ShowBooleans(Operator, tool.Ifc.Operator, AddObjectHelper):
objects_to_remove.add(existing_booleans[boolean_id])
boolean_obj.data.BIMMeshProperties.ifc_boolean_id = boolean_id
boolean_obj.data.BIMMeshProperties.obj = obj
tool.Root.add_tracked_opening(boolean_obj)
tool.Root.add_tracked_opening(boolean_obj, "BOOLEAN")
booleans_objs.append(boolean_obj)
tool.Blender.remove_data_blocks(objects_to_remove, remove_unused_data=True)
@@ -849,7 +849,7 @@ class ShowOpenings(Operator, tool.Ifc.Operator):
self.on_new_opening_obj(opening)
def on_new_opening_obj(self, opening_obj: bpy.types.Object) -> None:
tool.Root.add_tracked_opening(opening_obj)
tool.Root.add_tracked_opening(opening_obj, "OPENING")
opening_obj.display_type = "WIRE"
-2
View File
@@ -51,8 +51,6 @@ def copy_class(
geometry.rename_object(data, geometry.get_representation_name(ifc.get_entity(data)))
root.assign_body_styles(new, obj)
collector.assign(obj)
if root.is_element_a(new, "IfcOpeningElement"):
root.add_tracked_opening(obj)
return new
+8
View File
@@ -2014,6 +2014,14 @@ class Model(bonsai.core.tool.Model):
def get_booleaned_obj(cls, boolean_obj: bpy.types.Object) -> bpy.types.Object:
return boolean_obj.data.BIMMeshProperties.obj
@classmethod
def get_tracked_opening_type(cls, obj: bpy.types.Object) -> Union[Literal["OPENING", "BOOLEAN"], None]:
"""Get tracked opening type, return `None` if object is not a tracked opening."""
for opening in bpy.context.scene.BIMModelProperties.openings:
if opening.obj == obj:
return opening.name
return None
@classmethod
def bm_sort_out_geom(
cls, geom_data: list[Union[bmesh.types.BMVert, bmesh.types.BMEdge, bmesh.types.BMFace]]
+3 -2
View File
@@ -26,17 +26,18 @@ import bonsai.core.tool
import bonsai.core.aggregate
import bonsai.core.geometry
import bonsai.tool as tool
from typing import Union, Optional, Any
from typing import Union, Optional, Any, Literal
from bonsai.bim.module.spatial.decorator import GridDecorator
from bonsai.bim.module.geometry.decorator import ItemDecorator
class Root(bonsai.core.tool.Root):
@classmethod
def add_tracked_opening(cls, obj: bpy.types.Object) -> None:
def add_tracked_opening(cls, obj: bpy.types.Object, opening_type: Literal["OPENING", "BOOLEAN"]) -> None:
"""Add tracked opening or boolean object."""
new = bpy.context.scene.BIMModelProperties.openings.add()
new.obj = obj
new.name = opening_type
@classmethod
def assign_body_styles(cls, element: ifcopenshell.entity_instance, obj: bpy.types.Object) -> None:
+2 -1
View File
@@ -33,9 +33,10 @@ class TestImplementsTool(NewFile):
class TestAddTrackedOpening(NewFile):
def test_run(self):
obj = bpy.data.objects.new("Object", None)
subject.add_tracked_opening(obj)
subject.add_tracked_opening(obj, "OPENING")
props = bpy.context.scene.BIMModelProperties
assert props.openings[0].obj == obj
assert props.openings[0].name == "OPENING"
class TestCopyRepresentation(NewFile):