closes #3340: right click on section/elevation tag to open corresponding drawing.

video: https://github.com/IfcOpenShell/IfcOpenShell/issues/3340#issuecomment-3650097896
This commit is contained in:
Ryan Schultz
2025-12-13 20:45:48 -06:00
parent a2a5780d59
commit 6ab7acfa57
2 changed files with 75 additions and 0 deletions
@@ -18,10 +18,12 @@
import bpy
from . import ui, prop, operator, handler, gizmos, workspace
import bonsai.tool as tool
classes = (
operator.ActivateDrawing,
operator.ActivateDrawingFromSheet,
operator.ActivateDrawingByAnnotation,
operator.ActivateDrawingStyle,
operator.ActivateModel,
operator.AddAnnotation,
@@ -134,6 +136,13 @@ classes = (
)
def menu_func(self, context):
active_obj = context.active_object
if active_obj:
element = tool.Ifc.get_entity(active_obj)
if element and element.is_a("IfcAnnotation") and element.ObjectType in ["SECTION", "ELEVATION"]:
self.layout.operator("bim.activate_drawing_by_annotation", text="Go to Drawing")
def register():
if not bpy.app.background:
bpy.utils.register_tool(workspace.AnnotationTool, after={"bim.bim_tool"}, separator=True, group=False)
@@ -146,6 +155,7 @@ def register():
bpy.app.handlers.load_post.append(handler.load_post)
bpy.app.handlers.depsgraph_update_pre.append(handler.depsgraph_update_pre_handler)
bpy.types.VIEW3D_MT_image_add.append(ui.add_object_button)
bpy.types.VIEW3D_MT_object_context_menu.append(menu_func)
def unregister():
@@ -160,3 +170,4 @@ def unregister():
bpy.app.handlers.load_post.remove(handler.load_post)
bpy.app.handlers.depsgraph_update_pre.remove(handler.depsgraph_update_pre_handler)
bpy.types.VIEW3D_MT_image_add.remove(ui.add_object_button)
bpy.types.VIEW3D_MT_object_context_menu.remove(menu_func)
@@ -3876,3 +3876,67 @@ class ExcludeAnnotation(bpy.types.Operator, tool.Ifc.Operator):
if referenced_element := tool.Drawing.get_annotation_element(element):
tool.Drawing.exclude_annotation_from_drawing(referenced_element, drawing)
core.sync_references(tool.Ifc, tool.Collector, tool.Drawing, drawing=drawing)
class ActivateDrawingByAnnotation(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.activate_drawing_by_annotation"
bl_label = "Activate Drawing"
bl_description = "Activate the drawing corresponding to the selected annotation"
bl_options = {"REGISTER", "UNDO"}
@classmethod
def poll(cls, context):
# Check if an annotation object is selected
if not context.selected_objects:
cls.poll_message_set("No object selected")
return False
active_obj = context.active_object
if not active_obj:
cls.poll_message_set("No active object")
return False
element = tool.Ifc.get_entity(active_obj)
if not element:
cls.poll_message_set("Selected object is not an IFC element")
return False
# Check if it's an IfcAnnotation with ObjectType = "SECTION" or "ELEVATION"
if not element.is_a("IfcAnnotation") or element.ObjectType not in ["SECTION", "ELEVATION"]:
cls.poll_message_set("Selected object is not a drawing annotation")
return False
return True
def _execute(self, context):
active_obj = context.active_object
element = tool.Ifc.get_entity(active_obj)
if not element or not element.is_a("IfcAnnotation") or element.ObjectType not in ["SECTION", "ELEVATION"]:
self.report({"ERROR"}, "Selected object is not a drawing annotation")
return {"CANCELLED"}
# Find the drawing/camera element that this annotation references
drawing_element = self.find_drawing_from_annotation(element)
if not drawing_element:
self.report({"ERROR"}, "Could not find drawing element for this annotation")
return {"CANCELLED"}
# Use the existing ActivateDrawing operator with the drawing element's ID
bpy.ops.bim.activate_drawing(drawing=drawing_element.id())
return {"FINISHED"}
def find_drawing_from_annotation(self, annotation_element):
"""Find the drawing/camera element that this annotation references."""
ifc = tool.Ifc.get()
# Check IfcRelAssignsToProduct relationships
for rel in ifc.get_inverse(annotation_element):
if rel.is_a("IfcRelAssignsToProduct") and rel.RelatingProduct:
if rel.RelatingProduct.is_a("IfcAnnotation"):
# Found the drawing element!
return rel.RelatingProduct
return None