mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-09 09:21:46 +00:00
See #5972. You can now load a hierarchy to visualise the boolean result tree.
This commit is contained in:
@@ -22,19 +22,26 @@ from . import ui, prop, operator
|
||||
classes = (
|
||||
operator.AddFilling,
|
||||
operator.AddOpening,
|
||||
operator.BooleansMarkAsManual,
|
||||
operator.DisableEditingBooleans,
|
||||
operator.EnableEditingBooleans,
|
||||
operator.RemoveFilling,
|
||||
operator.RemoveOpening,
|
||||
operator.SelectDecomposition,
|
||||
operator.BooleansMarkAsManual,
|
||||
prop.Boolean,
|
||||
prop.VoidProperties,
|
||||
prop.BIMBooleanProperties,
|
||||
ui.BIM_PT_voids,
|
||||
ui.BIM_PT_booleans,
|
||||
ui.BIM_UL_booleans,
|
||||
)
|
||||
|
||||
|
||||
def register():
|
||||
bpy.types.Scene.VoidProperties = bpy.props.PointerProperty(type=prop.VoidProperties)
|
||||
bpy.types.Scene.BIMBooleanProperties = bpy.props.PointerProperty(type=prop.BIMBooleanProperties)
|
||||
|
||||
|
||||
def unregister():
|
||||
del bpy.types.Scene.VoidProperties
|
||||
del bpy.types.Scene.BIMBooleanProperties
|
||||
|
||||
@@ -80,7 +80,7 @@ class BooleansData:
|
||||
|
||||
@classmethod
|
||||
def booleans(cls):
|
||||
obj = bpy.context.active_object
|
||||
obj = bpy.context.scene.BIMGeometryProperties.representation_obj or bpy.context.active_object
|
||||
if (
|
||||
not obj.data
|
||||
or not hasattr(obj.data, "BIMMeshProperties")
|
||||
@@ -93,7 +93,7 @@ class BooleansData:
|
||||
|
||||
@classmethod
|
||||
def manual_booleans(cls):
|
||||
obj = bpy.context.active_object
|
||||
obj = bpy.context.scene.BIMGeometryProperties.representation_obj or bpy.context.active_object
|
||||
if (
|
||||
not obj.data
|
||||
or not hasattr(obj.data, "BIMMeshProperties")
|
||||
|
||||
@@ -295,4 +295,50 @@ class BooleansMarkAsManual(bpy.types.Operator, tool.Ifc.Operator):
|
||||
{"INFO"}, f"{len(booleans)} booleans were marked as {'manual' if self.mark_as_manual else 'automatic'}"
|
||||
)
|
||||
bonsai.bim.handler.refresh_ui_data()
|
||||
|
||||
|
||||
class EnableEditingBooleans(bpy.types.Operator):
|
||||
bl_idname = "bim.enable_editing_booleans"
|
||||
bl_label = "Enable Editing Booleans"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
bl_description = "Manage a hierarchy of boolean operations"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return bpy.context.scene.BIMGeometryProperties.representation_obj
|
||||
|
||||
def execute(self, context):
|
||||
props = context.scene.BIMBooleanProperties
|
||||
rep_obj = bpy.context.scene.BIMGeometryProperties.representation_obj
|
||||
representation = tool.Geometry.get_active_representation(rep_obj)
|
||||
representation = ifcopenshell.util.representation.resolve_representation(representation)
|
||||
props.booleans.clear()
|
||||
|
||||
def load_boolean(item, level=0):
|
||||
new = props.booleans.add()
|
||||
new.name = f"{item.is_a()}/{item.id()}"
|
||||
new.ifc_definition_id = item.id()
|
||||
new.level = level
|
||||
if item.is_a("IfcBooleanResult"):
|
||||
new.name += f"/{item.Operator}"
|
||||
new.operator = item.Operator
|
||||
load_boolean(item.FirstOperand, level + 1)
|
||||
load_boolean(item.SecondOperand, level + 1)
|
||||
|
||||
for item in representation.Items:
|
||||
if item.is_a("IfcBooleanResult"):
|
||||
load_boolean(item)
|
||||
|
||||
props.is_editing = True
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class DisableEditingBooleans(bpy.types.Operator):
|
||||
bl_idname = "bim.disable_editing_booleans"
|
||||
bl_label = "Disable Editing Booleans"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def execute(self, context):
|
||||
props = context.scene.BIMBooleanProperties
|
||||
props.is_editing = False
|
||||
return {"FINISHED"}
|
||||
|
||||
@@ -18,8 +18,21 @@
|
||||
|
||||
import bpy
|
||||
from bpy.types import PropertyGroup
|
||||
from bpy.props import PointerProperty
|
||||
from bpy.props import PointerProperty, StringProperty, IntProperty, BoolProperty, CollectionProperty
|
||||
|
||||
|
||||
class Boolean(PropertyGroup):
|
||||
name: StringProperty(name="Name")
|
||||
operator: StringProperty(name="Operator")
|
||||
ifc_definition_id: IntProperty(name="IFC Definition ID")
|
||||
level: IntProperty(name="Level")
|
||||
|
||||
|
||||
class VoidProperties(PropertyGroup):
|
||||
desired_opening: PointerProperty(name="Desired Opening To Fill", type=bpy.types.Object)
|
||||
|
||||
|
||||
class BIMBooleanProperties(PropertyGroup):
|
||||
is_editing: BoolProperty(name="Is Editing", default=False)
|
||||
booleans: CollectionProperty(name="Booleans", type=Boolean)
|
||||
active_boolean_index: IntProperty(name="Active Boolean Index")
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
import bpy
|
||||
import bonsai.tool as tool
|
||||
from bpy.types import Panel
|
||||
from bpy.types import Panel, UIList
|
||||
from bonsai.bim.module.void.data import BooleansData, VoidsData
|
||||
|
||||
|
||||
@@ -110,19 +110,18 @@ class BIM_PT_booleans(Panel):
|
||||
if not context.active_object.data:
|
||||
return
|
||||
layout = self.layout
|
||||
props = context.active_object.data.BIMMeshProperties
|
||||
props = context.scene.BIMBooleanProperties
|
||||
|
||||
if context.active_object.data.BIMMeshProperties.ifc_definition_id:
|
||||
row = layout.row(align=True)
|
||||
total_booleans = BooleansData.data["total_booleans"]
|
||||
manual_booleans = BooleansData.data["manual_booleans"]
|
||||
row.label(text=f"{len(total_booleans)} Booleans Found ({len(manual_booleans)} Manual)")
|
||||
if props.is_editing:
|
||||
row.operator("bim.disable_editing_booleans", icon="CANCEL", text="")
|
||||
else:
|
||||
row.operator("bim.enable_editing_booleans", icon="IMPORT", text="")
|
||||
row.operator("bim.add_boolean", text="", icon="ADD")
|
||||
show_boolean_button = row.row(align=True)
|
||||
show_boolean_button.operator("bim.show_booleans", text="", icon="HIDE_OFF")
|
||||
show_boolean_button.enabled = len(total_booleans) > 0
|
||||
row.operator("bim.hide_booleans", text="", icon="HIDE_ON")
|
||||
|
||||
booleans_are_manual = len(manual_booleans) == len(total_booleans)
|
||||
op = row.operator(
|
||||
"bim.booleans_mark_as_manual", text="", icon="PINNED" if booleans_are_manual else "UNPINNED"
|
||||
@@ -136,6 +135,26 @@ class BIM_PT_booleans(Panel):
|
||||
row.label(text=upsteam_obj.name)
|
||||
row.operator("bim.select_entity", text="", icon="RESTRICT_SELECT_OFF").ifc_id = upstream_obj_ifc_id
|
||||
|
||||
if not props.is_editing:
|
||||
return
|
||||
|
||||
self.layout.template_list("BIM_UL_booleans", "", props, "booleans", props, "active_boolean_index")
|
||||
|
||||
|
||||
class BIM_UL_booleans(UIList):
|
||||
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
|
||||
if item:
|
||||
if item.operator == "DIFFERENCE":
|
||||
icon = "SELECT_DIFFERENCE"
|
||||
elif item.operator == "INTERSECTION":
|
||||
icon = "SELECT_INTERSECT"
|
||||
elif item.operator == "UNION":
|
||||
icon = "SELECT_EXTEND"
|
||||
elif "IfcHalfSpaceSolid" in item.name:
|
||||
icon = "NORMALS_FACE"
|
||||
else:
|
||||
icon = "MESH_DATA"
|
||||
row = layout.row(align=True)
|
||||
row.operator("bim.hide_booleans", text="Hide Boolean")
|
||||
row.operator("bim.remove_booleans", text="Remove Boolean", icon="X")
|
||||
for i in range(0, item.level):
|
||||
row.label(text="", icon="BLANK1")
|
||||
row.label(text=item.name, icon=icon)
|
||||
|
||||
Reference in New Issue
Block a user