mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-24 21:00:01 +00:00
Support adding duplicated existing boolean
Example - https://imgur.com/a/rRQz9dx
This commit is contained in:
@@ -36,6 +36,7 @@ import ifcopenshell.util.unit
|
|||||||
import bonsai.tool as tool
|
import bonsai.tool as tool
|
||||||
import bonsai.core.geometry
|
import bonsai.core.geometry
|
||||||
import bonsai.bim.import_ifc as import_ifc
|
import bonsai.bim.import_ifc as import_ifc
|
||||||
|
from collections import defaultdict
|
||||||
from bonsai.bim.ifc import IfcStore
|
from bonsai.bim.ifc import IfcStore
|
||||||
from math import pi, radians
|
from math import pi, radians
|
||||||
from mathutils import Vector, Matrix
|
from mathutils import Vector, Matrix
|
||||||
@@ -737,27 +738,43 @@ class HideBooleans(Operator, tool.Ifc.Operator):
|
|||||||
set_active_obj, set_selected_objs = None, None
|
set_active_obj, set_selected_objs = None, None
|
||||||
boolean_objs: list[bpy.types.Object]
|
boolean_objs: list[bpy.types.Object]
|
||||||
selected_objects = tool.Blender.get_selected_objects()
|
selected_objects = tool.Blender.get_selected_objects()
|
||||||
selected_booleans_objs = [obj for obj in selected_objects if tool.Model.is_boolean_obj(obj)]
|
selected_booleans_objs = [
|
||||||
|
obj for obj in selected_objects if tool.Model.get_tracked_opening_type(obj) == "BOOLEAN"
|
||||||
|
]
|
||||||
|
|
||||||
|
# Hide currently selected booleans, otherwise hide all booleans.
|
||||||
if selected_booleans_objs:
|
if selected_booleans_objs:
|
||||||
boolean_objs = selected_booleans_objs
|
boolean_objs = selected_booleans_objs
|
||||||
if (active_object := context.active_object) in selected_booleans_objs:
|
if (active_object := context.active_object) in selected_booleans_objs:
|
||||||
active_obj_source = active_object
|
active_obj_source = active_object
|
||||||
else:
|
else:
|
||||||
active_obj_source = selected_booleans_objs[0]
|
active_obj_source = selected_booleans_objs[0]
|
||||||
set_active_obj = active_obj_source.data.BIMMeshProperties.obj
|
set_active_obj = tool.Model.get_booleaned_obj(active_obj_source)
|
||||||
set_selected_objs = [tool.Model.get_booleaned_obj(obj) for obj in boolean_objs]
|
assert set_active_obj
|
||||||
|
set_selected_objs = [
|
||||||
|
bool_obj for obj in selected_booleans_objs if (bool_obj := tool.Model.get_booleaned_obj(obj))
|
||||||
|
]
|
||||||
else:
|
else:
|
||||||
props = bpy.context.scene.BIMModelProperties
|
props = bpy.context.scene.BIMModelProperties
|
||||||
boolean_objs = [obj for o in props.openings if (obj := o.obj)]
|
boolean_objs = [obj for o in props.openings if (obj := o.obj) and o.name == "BOOLEAN"]
|
||||||
|
|
||||||
|
objects_to_remove: set[bpy.types.Object] = set()
|
||||||
|
booleans_to_add: dict[bpy.types.Object, list[bpy.types.Object]] = defaultdict(list)
|
||||||
|
|
||||||
objects_to_remove = set()
|
|
||||||
for obj in boolean_objs:
|
for obj in boolean_objs:
|
||||||
ifc_boolean_id = obj.data.BIMMeshProperties.ifc_boolean_id
|
main_obj = tool.Model.get_booleaned_obj(obj)
|
||||||
boolean = tool.Ifc.get_entity_by_id(ifc_boolean_id)
|
if not main_obj:
|
||||||
|
continue
|
||||||
|
|
||||||
# Update boolean transform.
|
# Update boolean transform.
|
||||||
if boolean:
|
if main_obj:
|
||||||
main_obj = cast(bpy.types.Object, obj.data.BIMMeshProperties.obj)
|
ifc_boolean_id = obj.data.BIMMeshProperties.ifc_boolean_id
|
||||||
|
boolean = tool.Ifc.get_entity_by_id(ifc_boolean_id)
|
||||||
|
|
||||||
|
if boolean is None:
|
||||||
|
booleans_to_add[main_obj].append(obj)
|
||||||
|
continue
|
||||||
|
|
||||||
if boolean.is_a("IfcHalfSpaceSolid"):
|
if boolean.is_a("IfcHalfSpaceSolid"):
|
||||||
surface = boolean.BaseSurface
|
surface = boolean.BaseSurface
|
||||||
|
|
||||||
@@ -781,6 +798,11 @@ class HideBooleans(Operator, tool.Ifc.Operator):
|
|||||||
tool.Blender.remove_data_blocks(objects_to_remove, remove_unused_data=True)
|
tool.Blender.remove_data_blocks(objects_to_remove, remove_unused_data=True)
|
||||||
tool.Model.purge_scene_openings()
|
tool.Model.purge_scene_openings()
|
||||||
|
|
||||||
|
if booleans_to_add:
|
||||||
|
for obj, boolean_objs in booleans_to_add.items():
|
||||||
|
with context.temp_override(selected_objects=boolean_objs + [obj]):
|
||||||
|
bpy.ops.bim.add_boolean()
|
||||||
|
|
||||||
if set_active_obj and set_selected_objs is not None:
|
if set_active_obj and set_selected_objs is not None:
|
||||||
tool.Blender.set_objects_selection(context, set_active_obj, set_selected_objs)
|
tool.Blender.set_objects_selection(context, set_active_obj, set_selected_objs)
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|||||||
@@ -104,6 +104,9 @@ class BIM_PT_booleans(Panel):
|
|||||||
if not BooleansData.is_loaded:
|
if not BooleansData.is_loaded:
|
||||||
BooleansData.load()
|
BooleansData.load()
|
||||||
|
|
||||||
|
obj = context.active_object
|
||||||
|
assert obj
|
||||||
|
|
||||||
if not context.active_object.data:
|
if not context.active_object.data:
|
||||||
return
|
return
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
@@ -126,8 +129,7 @@ class BIM_PT_booleans(Panel):
|
|||||||
)
|
)
|
||||||
op.mark_as_manual = not booleans_are_manual
|
op.mark_as_manual = not booleans_are_manual
|
||||||
|
|
||||||
elif context.active_object.data.BIMMeshProperties.ifc_boolean_id:
|
elif upsteam_obj := obj.data.BIMMeshProperties.obj:
|
||||||
upsteam_obj = context.active_object.data.BIMMeshProperties.obj
|
|
||||||
upstream_obj_ifc_id = upsteam_obj.BIMObjectProperties.ifc_definition_id
|
upstream_obj_ifc_id = upsteam_obj.BIMObjectProperties.ifc_definition_id
|
||||||
|
|
||||||
row = layout.row(align=True)
|
row = layout.row(align=True)
|
||||||
|
|||||||
@@ -2007,12 +2007,12 @@ class Model(bonsai.core.tool.Model):
|
|||||||
return {"ifc_file": tmp, "curves": curves}
|
return {"ifc_file": tmp, "curves": curves}
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def is_boolean_obj(cls, obj: bpy.types.Object) -> bool:
|
def get_booleaned_obj(cls, obj: bpy.types.Object) -> Union[bpy.types.Object, None]:
|
||||||
return obj.type == "MESH" and obj.data.BIMMeshProperties.ifc_boolean_id
|
"""Get boolean obj, return `None` if either it's not a tracked boolean
|
||||||
|
or it's not referring to an object (e.g. potential boolean object)."""
|
||||||
@classmethod
|
if obj.type != "MESH":
|
||||||
def get_booleaned_obj(cls, boolean_obj: bpy.types.Object) -> bpy.types.Object:
|
return
|
||||||
return boolean_obj.data.BIMMeshProperties.obj
|
return obj.data.BIMMeshProperties.obj
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_tracked_opening_type(cls, obj: bpy.types.Object) -> Union[Literal["OPENING", "BOOLEAN"], None]:
|
def get_tracked_opening_type(cls, obj: bpy.types.Object) -> Union[Literal["OPENING", "BOOLEAN"], None]:
|
||||||
|
|||||||
Reference in New Issue
Block a user