mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-22 04:11:00 +00:00
Allow bulk annotation product assignment
Closes #7787: Previously bim.assign_selected_as_product required exactly 2 objects. With multiple annotations referencing the same product, users had to repeat the operation once per annotation. Now any number of IfcAnnotations can be selected alongside a single product object and all are assigned in one operation and one undo step. Generated with the assistance of an AI coding tool.
This commit is contained in:
@@ -3364,57 +3364,55 @@ class OrderTextLiteralDown(bpy.types.Operator):
|
|||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
# Ifc Operator is unnecessary, because suboperator is handling IFC changes.
|
class AssignSelectedObjectAsProduct(bpy.types.Operator, tool.Ifc.Operator):
|
||||||
class AssignSelectedObjectAsProduct(bpy.types.Operator):
|
|
||||||
bl_idname = "bim.assign_selected_as_product"
|
bl_idname = "bim.assign_selected_as_product"
|
||||||
bl_label = "Assign Selected Object As Product"
|
bl_label = "Assign Selected Object As Product"
|
||||||
bl_options = {"REGISTER", "UNDO"}
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def poll(cls, context):
|
def poll(cls, context):
|
||||||
if len(context.selected_objects) != 2:
|
if len(context.selected_objects) < 2:
|
||||||
cls.poll_message_set("2 objects need to be selected")
|
cls.poll_message_set("At least 2 objects need to be selected")
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def execute(self, context):
|
def _execute(self, context):
|
||||||
assert bpy.context.view_layer
|
|
||||||
objs = context.selected_objects[:]
|
objs = context.selected_objects[:]
|
||||||
obj1, obj2 = objs
|
ifc_objs = [(o, tool.Ifc.get_entity(o)) for o in objs if tool.Ifc.get_entity(o)]
|
||||||
element1 = tool.Ifc.get_entity(obj1)
|
|
||||||
element2 = tool.Ifc.get_entity(obj2)
|
|
||||||
assert element1 and element2
|
|
||||||
|
|
||||||
# Check if at least one object is an IfcAnnotation
|
annotations = [(o, e) for o, e in ifc_objs if e.is_a("IfcAnnotation")]
|
||||||
is_annotation1 = element1.is_a("IfcAnnotation")
|
non_annotations = [(o, e) for o, e in ifc_objs if not e.is_a("IfcAnnotation")]
|
||||||
is_annotation2 = element2.is_a("IfcAnnotation")
|
|
||||||
|
|
||||||
if not (is_annotation1 or is_annotation2):
|
if not annotations:
|
||||||
self.report({"ERROR"}, "At least one of the selected objects must be IfcAnnotation.")
|
self.report({"ERROR"}, "At least one selected object must be an IfcAnnotation.")
|
||||||
return {"CANCELLED"}
|
return {"CANCELLED"}
|
||||||
|
|
||||||
# If both are annotations, use the currently active object as relating product
|
if len(non_annotations) == 1:
|
||||||
if is_annotation1 and is_annotation2:
|
# One product, one or more annotations — assign all annotations to the product.
|
||||||
|
product = non_annotations[0][1]
|
||||||
|
elif len(non_annotations) == 0 and len(annotations) == 2:
|
||||||
|
# Both objects are annotations — use the non-active one as the relating product.
|
||||||
active_obj = context.active_object
|
active_obj = context.active_object
|
||||||
if active_obj == obj1:
|
if annotations[0][0] == active_obj:
|
||||||
other_selected_object = obj1
|
annotation_obj, annotation = annotations[0]
|
||||||
bpy.context.view_layer.objects.active = obj2
|
product = annotations[1][1]
|
||||||
else:
|
else:
|
||||||
other_selected_object = obj2
|
annotation_obj, annotation = annotations[1]
|
||||||
bpy.context.view_layer.objects.active = obj1
|
product = annotations[0][1]
|
||||||
# If only one is an annotation, make it the active object
|
core.edit_assigned_product(tool.Ifc, tool.Drawing, obj=annotation_obj, product=product)
|
||||||
elif is_annotation1:
|
tool.Blender.update_viewport()
|
||||||
other_selected_object = obj2
|
return
|
||||||
bpy.context.view_layer.objects.active = obj1
|
|
||||||
else:
|
else:
|
||||||
other_selected_object = obj1
|
self.report(
|
||||||
bpy.context.view_layer.objects.active = obj2
|
{"ERROR"},
|
||||||
|
"Select exactly one product object and one or more IfcAnnotation objects.",
|
||||||
|
)
|
||||||
|
return {"CANCELLED"}
|
||||||
|
|
||||||
assert (active_obj := context.active_object)
|
for annotation_obj, _ in annotations:
|
||||||
props = tool.Drawing.get_object_assigned_product_props(active_obj)
|
core.edit_assigned_product(tool.Ifc, tool.Drawing, obj=annotation_obj, product=product)
|
||||||
props.relating_product = other_selected_object
|
|
||||||
bpy.ops.bim.edit_assigned_product()
|
tool.Blender.update_viewport()
|
||||||
return {"FINISHED"}
|
|
||||||
|
|
||||||
|
|
||||||
class EditAssignedProduct(bpy.types.Operator, tool.Ifc.Operator):
|
class EditAssignedProduct(bpy.types.Operator, tool.Ifc.Operator):
|
||||||
|
|||||||
Reference in New Issue
Block a user