mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-20 06:58:56 +00:00
Add features for handling newly created objects in aggregate mode
- Highlight new objects in red when in aggregate mode - Introduce an operator to add new objects to the current aggregate, accessible via a button in the header menu
This commit is contained in:
committed by
Bruno Perdigão
parent
3bccc993b7
commit
87fee0b850
@@ -32,6 +32,7 @@ classes = (
|
|||||||
operator.BIM_OT_select_linked_aggregates,
|
operator.BIM_OT_select_linked_aggregates,
|
||||||
operator.BIM_OT_disable_aggregate_mode,
|
operator.BIM_OT_disable_aggregate_mode,
|
||||||
operator.BIM_OT_toggle_aggregate_mode_local_view,
|
operator.BIM_OT_toggle_aggregate_mode_local_view,
|
||||||
|
operator.BIM_OT_aggregate_assing_new_objects_in_aggregate_mode,
|
||||||
prop.BIMObjectAggregateProperties,
|
prop.BIMObjectAggregateProperties,
|
||||||
prop.Objects,
|
prop.Objects,
|
||||||
prop.BIMAggregateProperties,
|
prop.BIMAggregateProperties,
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ from bpy.types import SpaceView3D
|
|||||||
from bpy_extras import view3d_utils
|
from bpy_extras import view3d_utils
|
||||||
from gpu_extras.batch import batch_for_shader
|
from gpu_extras.batch import batch_for_shader
|
||||||
from mathutils import Vector
|
from mathutils import Vector
|
||||||
|
from bonsai.bim.module.geometry.decorator import ItemDecorator
|
||||||
|
|
||||||
|
|
||||||
def transparent_color(color, alpha=0.1):
|
def transparent_color(color, alpha=0.1):
|
||||||
@@ -85,7 +86,6 @@ class AggregateDecorator:
|
|||||||
cls.uninstall()
|
cls.uninstall()
|
||||||
handler = cls()
|
handler = cls()
|
||||||
cls.handlers.append(SpaceView3D.draw_handler_add(handler.draw_aggregate, (context,), "WINDOW", "POST_VIEW"))
|
cls.handlers.append(SpaceView3D.draw_handler_add(handler.draw_aggregate, (context,), "WINDOW", "POST_VIEW"))
|
||||||
cls.handlers.append(SpaceView3D.draw_handler_add(handler.lock_objects, (context,), "WINDOW", "POST_VIEW"))
|
|
||||||
cls.is_installed = True
|
cls.is_installed = True
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@@ -227,6 +227,9 @@ class AggregateModeDecorator:
|
|||||||
cls.handlers.append(
|
cls.handlers.append(
|
||||||
SpaceView3D.draw_handler_add(handler.draw_aggregate_empty, (context,), "WINDOW", "POST_VIEW")
|
SpaceView3D.draw_handler_add(handler.draw_aggregate_empty, (context,), "WINDOW", "POST_VIEW")
|
||||||
)
|
)
|
||||||
|
cls.handlers.append(
|
||||||
|
SpaceView3D.draw_handler_add(handler.draw_new_objects, (context,), "WINDOW", "POST_VIEW")
|
||||||
|
)
|
||||||
cls.is_installed = True
|
cls.is_installed = True
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@@ -248,7 +251,9 @@ class AggregateModeDecorator:
|
|||||||
region = context.region
|
region = context.region
|
||||||
rv3d = region.data
|
rv3d = region.data
|
||||||
props = context.scene.BIMAggregateProperties
|
props = context.scene.BIMAggregateProperties
|
||||||
if aggregate_obj := props.editing_aggregate:
|
|
||||||
|
aggregate_obj = props.editing_aggregate
|
||||||
|
if not aggregate_obj:
|
||||||
return
|
return
|
||||||
self.addon_prefs = tool.Blender.get_addon_preferences()
|
self.addon_prefs = tool.Blender.get_addon_preferences()
|
||||||
self.font_id = 0
|
self.font_id = 0
|
||||||
@@ -273,7 +278,8 @@ class AggregateModeDecorator:
|
|||||||
|
|
||||||
def draw_aggregate_empty(self, context):
|
def draw_aggregate_empty(self, context):
|
||||||
props = context.scene.BIMAggregateProperties
|
props = context.scene.BIMAggregateProperties
|
||||||
if aggregate_obj := props.editing_aggregate:
|
aggregate_obj = props.editing_aggregate
|
||||||
|
if not aggregate_obj:
|
||||||
return
|
return
|
||||||
self.addon_prefs = tool.Blender.get_addon_preferences()
|
self.addon_prefs = tool.Blender.get_addon_preferences()
|
||||||
self.line_shader = gpu.shader.from_builtin("POLYLINE_UNIFORM_COLOR")
|
self.line_shader = gpu.shader.from_builtin("POLYLINE_UNIFORM_COLOR")
|
||||||
@@ -294,8 +300,8 @@ class AggregateModeDecorator:
|
|||||||
parts = ifcopenshell.util.element.get_parts(tool.Ifc.get_entity(aggregate_obj))
|
parts = ifcopenshell.util.element.get_parts(tool.Ifc.get_entity(aggregate_obj))
|
||||||
if parts:
|
if parts:
|
||||||
for part in parts:
|
for part in parts:
|
||||||
|
part_obj = tool.Ifc.get_object(part)
|
||||||
if part.is_a("IfcElementAssembly"):
|
if part.is_a("IfcElementAssembly"):
|
||||||
part_obj = tool.Ifc.get_object(part)
|
|
||||||
self.line_shader.uniform_float("lineWidth", 1.0)
|
self.line_shader.uniform_float("lineWidth", 1.0)
|
||||||
size = part_obj.empty_display_size
|
size = part_obj.empty_display_size
|
||||||
location = part_obj.location
|
location = part_obj.location
|
||||||
@@ -315,3 +321,30 @@ class AggregateModeDecorator:
|
|||||||
indices, edges = create_bounding_box(parts_objs)
|
indices, edges = create_bounding_box(parts_objs)
|
||||||
self.line_shader.uniform_float("lineWidth", 0.5)
|
self.line_shader.uniform_float("lineWidth", 0.5)
|
||||||
self.draw_batch("LINES", indices, color, edges)
|
self.draw_batch("LINES", indices, color, edges)
|
||||||
|
|
||||||
|
def draw_new_objects(self, context):
|
||||||
|
self.addon_prefs = tool.Blender.get_addon_preferences()
|
||||||
|
self.line_shader = gpu.shader.from_builtin("POLYLINE_UNIFORM_COLOR")
|
||||||
|
self.line_shader.bind()
|
||||||
|
self.line_shader.uniform_float("viewportSize", (context.region.width, context.region.height))
|
||||||
|
self.line_shader.uniform_float("lineWidth", 2.0)
|
||||||
|
color = self.addon_prefs.decorator_color_unselected
|
||||||
|
props = context.scene.BIMAggregateProperties
|
||||||
|
editing_objects = set([o.obj for o in props.editing_objects])
|
||||||
|
not_editing_objects = set([o.obj for o in props.not_editing_objects])
|
||||||
|
objs = []
|
||||||
|
visible_objects = tool.Raycast.get_visible_objects(context)
|
||||||
|
for obj in visible_objects:
|
||||||
|
if obj.visible_in_viewport_get(context.space_data):
|
||||||
|
objs.append(obj.original)
|
||||||
|
new_objs = set(objs) - not_editing_objects - editing_objects
|
||||||
|
new_objs = [o for o in new_objs if o.data]
|
||||||
|
for obj in new_objs:
|
||||||
|
element = tool.Ifc.get_entity(obj)
|
||||||
|
if element and element.is_a("IfcElement"):
|
||||||
|
data = ItemDecorator.get_obj_data(obj)
|
||||||
|
if data:
|
||||||
|
self.draw_batch(
|
||||||
|
"TRIS", data["verts"], transparent_color((1, 0, 0, 1)), data["tris"]
|
||||||
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -68,6 +68,10 @@ class BIM_OT_aggregate_assign_object(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
related_obj=obj,
|
related_obj=obj,
|
||||||
)
|
)
|
||||||
tool.Aggregate.constrain_parts_to_aggregate(relating_obj)
|
tool.Aggregate.constrain_parts_to_aggregate(relating_obj)
|
||||||
|
props = context.scene.BIMAggregateProperties
|
||||||
|
if relating_obj == props.editing_aggregate and props.in_aggregate_mode:
|
||||||
|
new_editing_obj = props.editing_objects.add()
|
||||||
|
new_editing_obj.obj = obj
|
||||||
except core.IncompatibleAggregateError:
|
except core.IncompatibleAggregateError:
|
||||||
self.report({"ERROR"}, f"Cannot aggregate {obj.name} to {relating_obj.name}")
|
self.report({"ERROR"}, f"Cannot aggregate {obj.name} to {relating_obj.name}")
|
||||||
except core.AggregateRepresentationError:
|
except core.AggregateRepresentationError:
|
||||||
@@ -399,3 +403,35 @@ class BIM_OT_toggle_aggregate_mode_local_view(bpy.types.Operator):
|
|||||||
|
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
class BIM_OT_aggregate_assing_new_objects_in_aggregate_mode(bpy.types.Operator):
|
||||||
|
bl_idname = "bim.aggregate_assing_new_objects_in_aggregate_mode"
|
||||||
|
bl_label = "Aggregate Assing New Objects In Aggregate Mode"
|
||||||
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
|
relating_object: bpy.props.IntProperty()
|
||||||
|
related_object: bpy.props.IntProperty()
|
||||||
|
|
||||||
|
def execute(self, context):
|
||||||
|
bpy.ops.object.select_all(action="DESELECT")
|
||||||
|
props = context.scene.BIMAggregateProperties
|
||||||
|
editing_objects = set([o.obj for o in props.editing_objects])
|
||||||
|
not_editing_objects = set([o.obj for o in props.not_editing_objects])
|
||||||
|
objs = []
|
||||||
|
visible_objects = tool.Raycast.get_visible_objects(context)
|
||||||
|
for obj in visible_objects:
|
||||||
|
if obj.visible_in_viewport_get(context.space_data):
|
||||||
|
objs.append(obj.original)
|
||||||
|
new_objs = set(objs) - not_editing_objects - editing_objects
|
||||||
|
new_objs = [o for o in new_objs if o.data]
|
||||||
|
for obj in new_objs:
|
||||||
|
element = tool.Ifc.get_entity(obj)
|
||||||
|
if element and element.is_a("IfcElement"):
|
||||||
|
obj.select_set(True)
|
||||||
|
editing_obj = props.editing_objects.add()
|
||||||
|
editing_obj.obj = obj
|
||||||
|
props.editing_aggregate.select_set(True)
|
||||||
|
self.relating_object = tool.Ifc.get_entity(props.editing_aggregate).id()
|
||||||
|
self.related_object = tool.Ifc.get_entity(obj).id()
|
||||||
|
BIM_OT_aggregate_assign_object._execute(self, context)
|
||||||
|
|
||||||
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|||||||
@@ -594,6 +594,7 @@ class EditObjectUI:
|
|||||||
row = cls.layout.row(align=True)
|
row = cls.layout.row(align=True)
|
||||||
op = row.operator("bim.disable_aggregate_mode", text="", icon="X")
|
op = row.operator("bim.disable_aggregate_mode", text="", icon="X")
|
||||||
op = row.operator("bim.toggle_aggregate_mode_local_view", text="", icon="ZOOM_SELECTED")
|
op = row.operator("bim.toggle_aggregate_mode_local_view", text="", icon="ZOOM_SELECTED")
|
||||||
|
op = row.operator("bim.aggregate_assing_new_objects_in_aggregate_mode", text="", icon="CUBE")
|
||||||
|
|
||||||
text = format_ifc_camel_case(AuthoringData.data["active_class"])
|
text = format_ifc_camel_case(AuthoringData.data["active_class"])
|
||||||
layout.label(text=f"{text} Edit Tools:", icon="RESTRICT_SELECT_OFF")
|
layout.label(text=f"{text} Edit Tools:", icon="RESTRICT_SELECT_OFF")
|
||||||
|
|||||||
Reference in New Issue
Block a user