Fix #5897. Fix #5488. Fix #5498. Bug where you couldn't edit newly added annotation.

The annotation adding code was a bit of a mess, spread around
create_annotation, create_annotation_occurrence, and
bpy.ops.bim.add_annotation. I've now consolidated it all into
core.add_annotation and updated it to work with the new item editing
mode (basically new objects need to reload their representation to
populate item_ids). Things are still messy, but a bit less now.
This commit is contained in:
Dion Moult
2025-01-17 20:53:29 +11:00
parent c163b260cf
commit 24b3cfc067
4 changed files with 87 additions and 43 deletions
@@ -1423,27 +1423,33 @@ class AddAnnotation(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.add_annotation"
bl_label = "Add Annotation"
bl_options = {"REGISTER", "UNDO"}
object_type: bpy.props.StringProperty()
data_type: bpy.props.StringProperty()
description: bpy.props.StringProperty()
@classmethod
def poll(cls, context):
return IfcStore.get_file() and context.scene.camera
return tool.Ifc.get() and context.scene.camera
@classmethod
def description(cls, context, operator):
return operator.description or ""
def _execute(self, context):
drawing = tool.Ifc.get_entity(context.scene.camera)
if not drawing:
props = bpy.context.scene.BIMAnnotationProperties
if not (drawing := tool.Ifc.get_entity(context.scene.camera)):
self.report({"WARNING"}, "Not a BIM camera")
return
r = core.add_annotation(tool.Ifc, tool.Collector, tool.Drawing, drawing=drawing, object_type=self.object_type)
if isinstance(r, str):
self.report({"WARNING"}, r)
obj = core.add_annotation(
tool.Ifc,
tool.Collector,
tool.Drawing,
drawing=drawing,
object_type=props.object_type,
relating_type=tool.Ifc.get().by_id(int(props.relating_type_id)) if props.relating_type_id != "0" else None,
enable_editing=True,
)
if props.object_type == "IMAGE":
bpy.ops.bim.add_reference_image("INVOKE_DEFAULT", use_existing_object_by_name=obj.name)
class AddSheet(bpy.types.Operator, tool.Ifc.Operator):
@@ -20,7 +20,9 @@
import os
import bpy
import bonsai.core.type
import bonsai.core.drawing as core
import bonsai.tool as tool
import ifcopenshell.util.representation
from bonsai.bim.module.drawing.data import DecoratorData, AnnotationData
from bonsai.bim.helper import prop_with_search
from bpy.types import WorkSpaceTool
@@ -161,12 +163,12 @@ def create_annotation_occurrence(context):
obj = tool.Drawing.create_annotation_object(drawing, object_type)
obj.name = relating_type.Name
ifc_context = tool.Drawing.get_annotation_context(tool.Drawing.get_drawing_target_view(drawing), object_type)
relating_type_repr = tool.Drawing.get_annotation_representation(relating_type)
relating_type_rep = tool.Drawing.get_annotation_representation(relating_type)
element = tool.Drawing.run_root_assign_class(
obj=obj,
ifc_class="IfcAnnotation",
predefined_type=object_type,
should_add_representation=not bool(relating_type_repr),
should_add_representation=not relating_type_rep,
context=ifc_context,
ifc_representation_class=tool.Drawing.get_ifc_representation_class(object_type),
)
@@ -175,27 +177,23 @@ def create_annotation_occurrence(context):
tool.Ifc.run("group.assign_group", group=tool.Drawing.get_drawing_group(drawing), products=[element])
tool.Collector.assign(obj)
tool.Blender.select_and_activate_single_object(context, obj)
if relating_type_repr is None and props.object_type == "IMAGE":
if relating_type_rep is None and props.object_type == "IMAGE":
bpy.ops.bim.add_reference_image("INVOKE_DEFAULT", use_existing_object_by_name=obj.name)
def create_annotation():
props = bpy.context.scene.BIMAnnotationProperties
if props.relating_type_id != "0":
create_annotation_occurrence(bpy.context)
else:
object_type = props.object_type
if not bpy.ops.bim.add_annotation.poll():
return
bpy.ops.bim.add_annotation(
object_type=object_type, data_type=tool.Drawing.ANNOTATION_TYPES_DATA[object_type][-1]
if representation := ifcopenshell.util.representation.get_representation(element, ifc_context):
bonsai.core.geometry.switch_representation(
tool.Ifc,
tool.Geometry,
obj=obj,
representation=representation,
should_reload=True,
is_global=True,
should_sync_changes_first=False,
)
if props.object_type == "IMAGE":
bpy.ops.bim.add_reference_image(
"INVOKE_DEFAULT", use_existing_object_by_name=bpy.context.active_object.name
)
if obj.data and not relating_type_rep:
tool.Drawing.enable_editing(obj)
class AnnotationToolUI:
@@ -294,21 +292,28 @@ class Hotkey(bpy.types.Operator, tool.Ifc.Operator):
def hotkey_S_T(self):
props = bpy.context.scene.BIMAnnotationProperties
annotation_type = props.object_type
object_type = props.object_type
if annotation_type not in tool.Drawing.ANNOTATION_TYPES_SUPPORT_SETUP:
self.report({"ERROR"}, f"Annotation type {annotation_type} is not supported for tagging.")
if object_type not in tool.Drawing.ANNOTATION_TYPES_SUPPORT_SETUP:
self.report({"ERROR"}, f"Annotation type {object_type} is not supported for tagging.")
return
related_objects = bpy.context.selected_objects
for related_object in related_objects:
create_annotation()
obj = bpy.context.active_object
bpy.ops.object.mode_set(mode="OBJECT")
tool.Drawing.setup_annotation_object(obj, annotation_type, related_object)
obj = core.add_annotation(
tool.Ifc,
tool.Collector,
tool.Drawing,
drawing=tool.Ifc.get_entity(bpy.context.scene.camera),
object_type=object_type,
relating_type=tool.Ifc.get().by_id(int(props.relating_type_id)) if props.relating_type_id != "0" else None,
enable_editing=False,
)
tool.Drawing.setup_annotation_object(obj, object_type, related_object)
def hotkey_S_A(self):
create_annotation()
if bpy.ops.bim.add_annotation.poll():
bpy.ops.bim.add_annotation()
def hotkey_S_E(self):
if not bpy.context.active_object:
+12 -3
View File
@@ -406,7 +406,9 @@ def add_annotation(
drawing_tool: tool.Drawing,
drawing: ifcopenshell.entity_instance,
object_type: str,
) -> None:
relating_type: ifcopenshell.entity_instance,
enable_editing: bool = False,
) -> bpy.types.Object:
target_view = drawing_tool.get_drawing_target_view(drawing)
context = drawing_tool.get_annotation_context(target_view, object_type)
if not context:
@@ -416,17 +418,24 @@ def add_annotation(
obj = drawing_tool.create_annotation_object(drawing, object_type)
element = ifc.get_entity(obj)
if not element:
relating_type_rep = drawing_tool.get_annotation_representation(relating_type) if relating_type else None
element = drawing_tool.run_root_assign_class(
obj=obj,
ifc_class="IfcAnnotation",
predefined_type=object_type,
should_add_representation=True,
should_add_representation=not relating_type_rep,
context=context,
ifc_representation_class=drawing_tool.get_ifc_representation_class(object_type),
)
if relating_type:
drawing_tool.run_type_assign_type(element=element, relating_type=relating_type)
ifc.run("group.assign_group", group=drawing_tool.get_drawing_group(drawing), products=[element])
if representation := drawing_tool.get_representation(element, context):
drawing_tool.reload_representation(obj=obj, representation=representation)
collector.assign(obj, should_clean_users_collection=True)
drawing_tool.enable_editing(obj)
if not relating_type_rep and object_type != "IMAGE" and enable_editing:
drawing_tool.enable_editing(obj)
return obj
def build_schedule(drawing: tool.Drawing, schedule: ifcopenshell.entity_instance) -> None:
+29 -5
View File
@@ -348,11 +348,15 @@ class Drawing(bonsai.core.tool.Drawing):
@classmethod
def enable_editing(cls, obj: bpy.types.Object) -> None:
bpy.ops.object.select_all(action="DESELECT")
bpy.context.view_layer.objects.active = obj
obj.select_set(True)
if obj.data:
bpy.ops.object.mode_set(mode="EDIT")
from bonsai.bim.module.geometry.data import ViewportData
tool.Blender.select_and_activate_single_object(bpy.context, obj)
if not obj.data:
return
ViewportData.load() # Reload valid modes
bpy.ops.bim.override_mode_set_edit() # Enter item mode
ViewportData.load() # Reload valid modes
bpy.ops.bim.override_mode_set_edit() # Enter edit mode
@classmethod
def enable_editing_drawings(cls) -> None:
@@ -988,6 +992,26 @@ class Drawing(bonsai.core.tool.Drawing):
ifc_representation_class=ifc_representation_class,
)
@classmethod
def run_type_assign_type(cls, element: ifcopenshell.entity_instance, relating_type: ifcopenshell.entity_instance):
return bonsai.core.type.assign_type(tool.Ifc, tool.Type, element=element, type=relating_type)
@classmethod
def reload_representation(cls, obj: bpy.types.Object, representation: ifcopenshell.entity_instance):
return bonsai.core.geometry.switch_representation(
tool.Ifc,
tool.Geometry,
obj=obj,
representation=representation,
should_reload=True,
is_global=True,
should_sync_changes_first=False,
)
@classmethod
def get_representation(cls, element, context):
return ifcopenshell.util.representation.get_representation(element, context)
@classmethod
def set_drawing_collection_name(
cls, drawing: ifcopenshell.entity_instance, collection: bpy.types.Collection