mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-10 09:48:32 +00:00
Annotation rotation when doing bulk tags (#7049)
* first attempt to do annotation rotation when dong bulk tags * Enhance annotation rotation handling based on camera orientation * handle properly S_G * black . * reorder property in UI * cleanup imports
This commit is contained in:
@@ -864,6 +864,19 @@ class BIMAnnotationProperties(PropertyGroup):
|
||||
)
|
||||
is_adding_type: bpy.props.BoolProperty(default=False)
|
||||
type_name: bpy.props.StringProperty(name="Name", default="TYPEX")
|
||||
tag_rotation_mode: bpy.props.EnumProperty(
|
||||
name="Tag Rotation Mode",
|
||||
description="How to orient the tag relative to the tagged object",
|
||||
items=[
|
||||
("NONE", "No Rotation", "Keep tag in default orientation"),
|
||||
("LOCAL_X", "Local X Axis", "Align tag with object's local X axis"),
|
||||
("LOCAL_Y", "Local Y Axis", "Align tag with object's local Y axis"),
|
||||
("LOCAL_Z", "Local Z Axis", "Align tag with object's local Z axis"),
|
||||
("CAMERA_Horizontal", "Camera Horizontal", "Align tag with camera X axis"),
|
||||
("CAMERA_Vertical", "Camera Vertical", "Align tag with camera Y axis"),
|
||||
],
|
||||
default="NONE",
|
||||
)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
object_type: str
|
||||
|
||||
@@ -228,7 +228,6 @@ class AnnotationToolUI:
|
||||
def draw_type_selection_interface(cls):
|
||||
# shared by both sidebar and header
|
||||
object_type = cls.props.object_type
|
||||
|
||||
row = cls.layout.row(align=True)
|
||||
row.label(text="", icon="FILE_VOLUME")
|
||||
prop_with_search(row, cls.props, "object_type", text="")
|
||||
@@ -248,6 +247,9 @@ class AnnotationToolUI:
|
||||
add_layout_hotkey_operator(cls.layout, "Add", "S_A", "Create a new annotation")
|
||||
|
||||
if object_type in tool.Drawing.ANNOTATION_TYPES_SUPPORT_SETUP:
|
||||
row = cls.layout.row(align=True)
|
||||
row.label(text="", icon="DRIVER_ROTATIONAL_DIFFERENCE")
|
||||
row.prop(cls.props, "tag_rotation_mode", text="")
|
||||
add_layout_hotkey_operator(
|
||||
cls.layout,
|
||||
"Bulk Tag",
|
||||
@@ -313,7 +315,7 @@ class Hotkey(bpy.types.Operator, tool.Ifc.Operator):
|
||||
),
|
||||
enable_editing=False,
|
||||
)
|
||||
tool.Drawing.setup_annotation_object(obj, object_type, related_object)
|
||||
tool.Drawing.setup_annotation_object(obj, object_type, related_object, props.tag_rotation_mode)
|
||||
created_objects.append(obj)
|
||||
|
||||
# Select the created annotation objects
|
||||
@@ -323,6 +325,7 @@ class Hotkey(bpy.types.Operator, tool.Ifc.Operator):
|
||||
if created_objects:
|
||||
bpy.context.view_layer.objects.active = created_objects[-1]
|
||||
|
||||
|
||||
def hotkey_S_A(self):
|
||||
if bpy.ops.bim.add_annotation.poll():
|
||||
bpy.ops.bim.add_annotation()
|
||||
@@ -351,4 +354,5 @@ class Hotkey(bpy.types.Operator, tool.Ifc.Operator):
|
||||
continue
|
||||
related_object = tool.Ifc.get_object(related_product)
|
||||
|
||||
tool.Drawing.setup_annotation_object(obj, annotation_type, related_object)
|
||||
rotation_mode = tool.Drawing.get_annotation_props().tag_rotation_mode
|
||||
tool.Drawing.setup_annotation_object(obj, annotation_type, related_object, rotation_mode)
|
||||
|
||||
@@ -251,7 +251,11 @@ class Drawing(bonsai.core.tool.Drawing):
|
||||
|
||||
@classmethod
|
||||
def setup_annotation_object(
|
||||
cls, obj: bpy.types.Object, object_type: str, related_object: Optional[bpy.types.Object] = None
|
||||
cls,
|
||||
obj: bpy.types.Object,
|
||||
object_type: str,
|
||||
related_object: Optional[bpy.types.Object] = None,
|
||||
rotation_mode: str = "NONE",
|
||||
) -> None:
|
||||
"""Finish object's adjustments after both object and entity are created"""
|
||||
|
||||
@@ -323,6 +327,55 @@ class Drawing(bonsai.core.tool.Drawing):
|
||||
ifc_file, relating_product=related_entity, related_object=obj_entity
|
||||
)
|
||||
|
||||
if rotation_mode != "NONE" and related_object:
|
||||
cls.apply_annotation_rotation(obj, related_object, rotation_mode)
|
||||
|
||||
@classmethod
|
||||
def apply_annotation_rotation(
|
||||
cls, tag_obj: bpy.types.Object, related_object: bpy.types.Object, rotation_mode: str
|
||||
) -> None:
|
||||
"""Apply rotation to annotation based on the selected rotation mode"""
|
||||
camera = bpy.context.scene.camera
|
||||
camera_right = camera.matrix_world.to_3x3() @ mathutils.Vector((1, 0, 0))
|
||||
|
||||
if rotation_mode == "CAMERA_Horizontal":
|
||||
location = tag_obj.location.copy()
|
||||
camera_matrix = camera.matrix_world.copy()
|
||||
camera_matrix.translation = location
|
||||
tag_obj.matrix_world = camera_matrix
|
||||
|
||||
elif rotation_mode == "CAMERA_Vertical":
|
||||
location = tag_obj.location.copy()
|
||||
camera_matrix = camera.matrix_world.copy()
|
||||
camera_matrix.translation = location
|
||||
rotation_90z = mathutils.Matrix.Rotation(math.pi / 2, 4, "Z")
|
||||
camera_matrix = camera_matrix @ rotation_90z
|
||||
tag_obj.matrix_world = camera_matrix
|
||||
|
||||
elif rotation_mode == "LOCAL_X":
|
||||
local_x = related_object.matrix_world.to_3x3() @ mathutils.Vector((1, 0, 0))
|
||||
local_x = local_x.normalized()
|
||||
if local_x.dot(camera_right) < 0:
|
||||
local_x = -local_x
|
||||
|
||||
tag_obj.rotation_euler = local_x.to_track_quat("X", "Z").to_euler()
|
||||
|
||||
elif rotation_mode == "LOCAL_Y":
|
||||
local_y = related_object.matrix_world.to_3x3() @ mathutils.Vector((0, 1, 0))
|
||||
local_y = local_y.normalized()
|
||||
if local_y.dot(camera_right) < 0:
|
||||
local_y = -local_y
|
||||
|
||||
tag_obj.rotation_euler = local_y.to_track_quat("X", "Z").to_euler()
|
||||
|
||||
elif rotation_mode == "LOCAL_Z":
|
||||
local_z = related_object.matrix_world.to_3x3() @ mathutils.Vector((0, 0, 1))
|
||||
local_z = local_z.normalized()
|
||||
if local_z.dot(camera_right) < 0:
|
||||
local_z = -local_z
|
||||
|
||||
tag_obj.rotation_euler = local_z.to_track_quat("X", "Z").to_euler()
|
||||
|
||||
@classmethod
|
||||
def is_annotation_object_type(
|
||||
cls, element: ifcopenshell.entity_instance, object_types: Union[str, Sequence[str]]
|
||||
|
||||
Reference in New Issue
Block a user