Fix #4175. Add new UI for managing IFC object and edit modes.

This commit is contained in:
Dion Moult
2024-01-09 12:57:18 +11:00
parent 0a09c2d8ea
commit 1c573aee32
4 changed files with 72 additions and 42 deletions
@@ -83,6 +83,7 @@ def register():
bpy.types.OUTLINER_MT_object.append(ui.outliner_menu) bpy.types.OUTLINER_MT_object.append(ui.outliner_menu)
bpy.types.VIEW3D_MT_object_context_menu.append(ui.object_menu) bpy.types.VIEW3D_MT_object_context_menu.append(ui.object_menu)
bpy.types.VIEW3D_MT_edit_mesh.append(ui.edit_mesh_menu) bpy.types.VIEW3D_MT_edit_mesh.append(ui.edit_mesh_menu)
bpy.types.VIEW3D_HT_header.append(ui.mode_menu)
wm = bpy.context.window_manager wm = bpy.context.window_manager
if wm.keyconfigs.addon: if wm.keyconfigs.addon:
km = wm.keyconfigs.addon.keymaps.new(name="Object Mode", space_type="EMPTY") km = wm.keyconfigs.addon.keymaps.new(name="Object Mode", space_type="EMPTY")
@@ -129,6 +130,7 @@ def unregister():
bpy.types.OUTLINER_MT_object.remove(ui.outliner_menu) bpy.types.OUTLINER_MT_object.remove(ui.outliner_menu)
bpy.types.VIEW3D_MT_object_context_menu.remove(ui.outliner_menu) bpy.types.VIEW3D_MT_object_context_menu.remove(ui.outliner_menu)
bpy.types.VIEW3D_MT_edit_mesh.remove(ui.edit_mesh_menu) bpy.types.VIEW3D_MT_edit_mesh.remove(ui.edit_mesh_menu)
bpy.types.VIEW3D_HT_header.remove(ui.mode_menu)
del bpy.types.Scene.BIMGeometryProperties del bpy.types.Scene.BIMGeometryProperties
del bpy.types.Object.BIMGeometryProperties del bpy.types.Object.BIMGeometryProperties
wm = bpy.context.window_manager wm = bpy.context.window_manager
@@ -870,7 +870,6 @@ class OverrideDuplicateMove(bpy.types.Operator):
return arrays_to_create, array_children return arrays_to_create, array_children
def remove_old_connections(old_to_new): def remove_old_connections(old_to_new):
for new in old_to_new.values(): for new in old_to_new.values():
for connection in new[0].ConnectedTo: for connection in new[0].ConnectedTo:
@@ -962,17 +961,13 @@ class DuplicateMoveLinkedAggregate(bpy.types.Operator):
return return
linked_aggregate_group = ifcopenshell.api.run("group.add_group", tool.Ifc.get(), Name=self.group_name) linked_aggregate_group = ifcopenshell.api.run("group.add_group", tool.Ifc.get(), Name=self.group_name)
ifcopenshell.api.run( ifcopenshell.api.run("group.assign_group", tool.Ifc.get(), products=[element], group=linked_aggregate_group)
"group.assign_group", tool.Ifc.get(), products=[element], group=linked_aggregate_group
)
def add_linked_aggregate_pset(part, index): def add_linked_aggregate_pset(part, index):
pset = ifcopenshell.util.element.get_pset(part, self.pset_name) pset = ifcopenshell.util.element.get_pset(part, self.pset_name)
if not pset: if not pset:
pset = ifcopenshell.api.run( pset = ifcopenshell.api.run("pset.add_pset", tool.Ifc.get(), product=part, name=self.pset_name)
"pset.add_pset", tool.Ifc.get(), product=part, name=self.pset_name
)
else: else:
pset = tool.Ifc.get().by_id(pset["id"]) pset = tool.Ifc.get().by_id(pset["id"])
@@ -985,7 +980,6 @@ class DuplicateMoveLinkedAggregate(bpy.types.Operator):
return index return index
if len(context.selected_objects) != 1: if len(context.selected_objects) != 1:
return {"FINISHED"} return {"FINISHED"}
@@ -1002,18 +996,15 @@ class DuplicateMoveLinkedAggregate(bpy.types.Operator):
self.report({"INFO"}, "Object is not part of a IfcElementAssembly.") self.report({"INFO"}, "Object is not part of a IfcElementAssembly.")
return {"FINISHED"} return {"FINISHED"}
select_objects_and_add_data(selected_element) select_objects_and_add_data(selected_element)
old_to_new = OverrideDuplicateMove.execute_ifc_duplicate_operator(self, context, linked=True) old_to_new = OverrideDuplicateMove.execute_ifc_duplicate_operator(self, context, linked=True)
# Recreate aggregate relationship # Recreate aggregate relationship
for old in old_to_new.keys(): for old in old_to_new.keys():
if old.is_a("IfcElementAssembly"): if old.is_a("IfcElementAssembly"):
tool.Root.recreate_aggregate(old_to_new) tool.Root.recreate_aggregate(old_to_new)
blenderbim.bim.handler.refresh_ui_data() blenderbim.bim.handler.refresh_ui_data()
return old_to_new return old_to_new
@@ -1038,7 +1029,7 @@ class RefreshLinkedAggregate(bpy.types.Operator):
def _execute(self, context): def _execute(self, context):
self.new_active_obj = None self.new_active_obj = None
self.group_name = 'BBIM_Linked_Aggregate' self.group_name = "BBIM_Linked_Aggregate"
self.pset_name = "BBIM_Linked_Aggregate" self.pset_name = "BBIM_Linked_Aggregate"
refresh_start_time = time() refresh_start_time = time()
old_to_new = {} old_to_new = {}
@@ -1113,7 +1104,10 @@ class RefreshLinkedAggregate(bpy.types.Operator):
if len(linked_aggregate_groups) > 1: if len(linked_aggregate_groups) > 1:
if len(selected_parents) != len(linked_aggregate_groups): if len(selected_parents) != len(linked_aggregate_groups):
self.report({"INFO"}, "Select only one object from each Linked Aggregate or multiple objects from the same Linked Aggregate.") self.report(
{"INFO"},
"Select only one object from each Linked Aggregate or multiple objects from the same Linked Aggregate.",
)
return {"FINISHED"} return {"FINISHED"}
for group in linked_aggregate_groups: for group in linked_aggregate_groups:
@@ -1161,12 +1155,12 @@ class RefreshLinkedAggregate(bpy.types.Operator):
if not new_aggregate: if not new_aggregate:
blenderbim.core.aggregate.assign_object( blenderbim.core.aggregate.assign_object(
tool.Ifc, tool.Ifc,
tool.Aggregate, tool.Aggregate,
tool.Collector, tool.Collector,
relating_obj=tool.Ifc.get_object(element_aggregate), relating_obj=tool.Ifc.get_object(element_aggregate),
related_obj=tool.Ifc.get_object(new[0]), related_obj=tool.Ifc.get_object(new[0]),
) )
blenderbim.bim.handler.refresh_ui_data() blenderbim.bim.handler.refresh_ui_data()
@@ -1393,7 +1387,12 @@ class OverrideModeSetEdit(bpy.types.Operator):
# The active object is non-mesh-like. Set a valid object (or None) as active # The active object is non-mesh-like. Set a valid object (or None) as active
context.view_layer.objects.active = context.selected_objects[0] if context.selected_objects else None context.view_layer.objects.active = context.selected_objects[0] if context.selected_objects else None
if context.active_object: if context.active_object:
return tool.Blender.toggle_edit_mode(context) tool.Blender.toggle_edit_mode(context)
context.scene.BIMGeometryProperties.is_changing_mode = True
if context.scene.BIMGeometryProperties.mode != "EDIT":
context.scene.BIMGeometryProperties.mode = "EDIT"
context.scene.BIMGeometryProperties.is_changing_mode = False
return {"FINISHED"}
# Restore the selection if nothing worked # Restore the selection if nothing worked
for obj in selected_objs: for obj in selected_objs:
@@ -1464,6 +1463,11 @@ class OverrideModeSetObject(bpy.types.Operator):
bpy.ops.object.mode_set(mode="EDIT", toggle=True) bpy.ops.object.mode_set(mode="EDIT", toggle=True)
context.scene.BIMGeometryProperties.is_changing_mode = True
if context.scene.BIMGeometryProperties.mode != "OBJECT":
context.scene.BIMGeometryProperties.mode = "OBJECT"
context.scene.BIMGeometryProperties.is_changing_mode = False
if not tool.Ifc.get(): if not tool.Ifc.get():
return {"FINISHED"} return {"FINISHED"}
@@ -38,6 +38,15 @@ def get_contexts(self, context):
return RepresentationsData.data["contexts"] return RepresentationsData.data["contexts"]
def update_mode(self, context):
if self.is_changing_mode:
return
if self.mode == "OBJECT":
bpy.ops.bim.override_mode_set_object("INVOKE_DEFAULT")
elif self.mode == "EDIT":
bpy.ops.bim.override_mode_set_edit("INVOKE_DEFAULT")
class RepresentationItem(PropertyGroup): class RepresentationItem(PropertyGroup):
name: StringProperty(name="Name") name: StringProperty(name="Name")
surface_style: StringProperty(name="Surface Style") surface_style: StringProperty(name="Surface Style")
@@ -59,3 +68,13 @@ class BIMGeometryProperties(PropertyGroup):
should_force_faceted_brep: BoolProperty(name="Force Faceted Breps", default=False) should_force_faceted_brep: BoolProperty(name="Force Faceted Breps", default=False)
# Navisworks workaround # Navisworks workaround
should_force_triangulation: BoolProperty(name="Force Triangulation", default=False) should_force_triangulation: BoolProperty(name="Force Triangulation", default=False)
is_changing_mode: BoolProperty(name="Is Changing Mode", default=False)
mode: EnumProperty(
default="OBJECT",
items=[
("OBJECT", "IFC Object Mode", "", "OBJECT_DATAMODE", 0),
("EDIT", "IFC Edit Mode", "", "EDITMODE_HLT", 1),
],
name="IFC Interaction Mode",
update=update_mode,
)
@@ -31,6 +31,11 @@ from blenderbim.bim.module.geometry.data import (
) )
def mode_menu(self, context):
row = self.layout.row(align=True)
row.prop(context.scene.BIMGeometryProperties, "mode", text="", icon_value=blenderbim.bim.icons["IFC"].icon_id)
def object_menu(self, context): def object_menu(self, context):
self.layout.separator() self.layout.separator()
self.layout.operator("bim.override_object_duplicate_move", icon="PLUGIN") self.layout.operator("bim.override_object_duplicate_move", icon="PLUGIN")