Fixed text annotation rotation in viewport #3017

Fixed text annotation rotation in viewport for the views rotated by multipel axis.
Changed text direction calculation to be the same in both viewport and svg.
This commit is contained in:
Andrej730
2023-04-18 14:55:45 +05:00
parent 8f8862d23d
commit 4fee8744d6
5 changed files with 22 additions and 21 deletions
@@ -113,9 +113,7 @@ class Annotator:
camera = tool.Ifc.get_object(drawing) camera = tool.Ifc.get_object(drawing)
co1, _, _, _ = Annotator.get_placeholder_coords(camera) co1, _, _, _ = Annotator.get_placeholder_coords(camera)
matrix_world = camera.matrix_world.copy() matrix_world = camera.matrix_world.copy()
matrix_world[0][3] = co1.x matrix_world.translation = co1
matrix_world[1][3] = co1.y
matrix_world[2][3] = co1.z
collection = camera.users_collection[0] collection = camera.users_collection[0]
if object_type == "TEXT": if object_type == "TEXT":
@@ -422,11 +422,14 @@ class BaseDecorator:
region = context.region region = context.region
region3d = context.region_data region3d = context.region_data
camera = context.scene.camera
text_dir = Vector((1, 0)) def get_basis_vector(matrix, i=0):
text_dir_world = region3d.perspective_matrix.inverted().to_quaternion() @ text_dir.to_3d() """returns basis vector for i in world space, unaffected by object scale"""
text_dir_world_rotated = obj.matrix_world.to_quaternion() @ text_dir_world return matrix.inverted()[i].to_3d().normalized()
text_dir = (region3d.perspective_matrix.to_quaternion() @ text_dir_world_rotated).to_2d().normalized()
text_dir_world_x_axis = get_basis_vector(obj.matrix_world)
text_dir = (camera.matrix_world.inverted().to_quaternion() @ text_dir_world_x_axis).to_2d().normalized()
pos = location_3d_to_region_2d(region, region3d, text_world_position) pos = location_3d_to_region_2d(region, region3d, text_world_position)
props = obj.BIMTextProperties props = obj.BIMTextProperties
@@ -553,7 +553,9 @@ class CreateDrawing(bpy.types.Operator):
value = ifcopenshell.util.selector.get_element_value(element, key) value = ifcopenshell.util.selector.get_element_value(element, key)
if value: if value:
classes.append( classes.append(
tool.Drawing.canonicalise_class_name(key) + "-" + tool.Drawing.canonicalise_class_name(str(value)) tool.Drawing.canonicalise_class_name(key)
+ "-"
+ tool.Drawing.canonicalise_class_name(str(value))
) )
el.set("class", (el.get("class", "") + " " + " ".join(classes)).strip()) el.set("class", (el.get("class", "") + " " + " ".join(classes)).strip())
@@ -626,7 +628,6 @@ class CreateDrawing(bpy.types.Operator):
self.svg_writer.metadata = self.metadata self.svg_writer.metadata = self.metadata
self.svg_writer.create_blank_svg(svg_path).draw_annotations(annotations, precision, decimal_places).save() self.svg_writer.create_blank_svg(svg_path).draw_annotations(annotations, precision, decimal_places).save()
return svg_path return svg_path
def get_scale(self): def get_scale(self):
@@ -707,8 +708,7 @@ class AddAnnotation(bpy.types.Operator, Operator):
if not drawing: if not drawing:
self.report({"WARNING"}, "Not a BIM camera") self.report({"WARNING"}, "Not a BIM camera")
return return
# TODO: support adding multiple annotations if there are multiple selected objects
# that can be used as annotations references
r = core.add_annotation(tool.Ifc, tool.Collector, tool.Drawing, drawing=drawing, object_type=self.object_type) r = core.add_annotation(tool.Ifc, tool.Collector, tool.Drawing, drawing=drawing, object_type=self.object_type)
if isinstance(r, str): if isinstance(r, str):
self.report({"WARNING"}, r) self.report({"WARNING"}, r)
@@ -1024,7 +1024,6 @@ class ActivateModel(bpy.types.Operator):
return {"FINISHED"} return {"FINISHED"}
class ActivateDrawing(bpy.types.Operator): class ActivateDrawing(bpy.types.Operator):
""" """
Activates the selected drawing view Activates the selected drawing view
@@ -665,13 +665,13 @@ class SvgWriter:
text_position = Vector(((x_offset + text_position.x), (y_offset - text_position.y))) text_position = Vector(((x_offset + text_position.x), (y_offset - text_position.y)))
text_position_svg = text_position * self.svg_scale text_position_svg = text_position * self.svg_scale
local_x_axis = text_obj.matrix_world.to_quaternion() @ Vector((1, 0, 0)) def get_basis_vector(matrix, i=0):
projected_x_axis = self.project_point_onto_camera(position + local_x_axis) """returns basis vector for i in world space, unaffected by object scale"""
angle = math.degrees( return matrix.inverted()[i].to_3d().normalized()
(Vector((x_offset + projected_x_axis.x, y_offset - projected_x_axis.y)) - text_position).angle_signed(
Vector((1, 0)) text_dir_world_x_axis = get_basis_vector(text_obj.matrix_world)
) text_dir = (self.camera.matrix_world.inverted().to_quaternion() @ text_dir_world_x_axis).to_2d().normalized()
) angle = math.degrees(-text_dir.angle_signed(Vector((1, 0))))
transform = "rotate({}, {}, {})".format(angle, *text_position_svg) transform = "rotate({}, {}, {})".format(angle, *text_position_svg)
classes = self.get_attribute_classes(text_obj) classes = self.get_attribute_classes(text_obj)
+3 -2
View File
@@ -310,9 +310,10 @@ def update_drawing_name(ifc, drawing_tool, drawing=None, name=None):
def add_annotation(ifc, collector, drawing_tool, drawing=None, object_type=None): def add_annotation(ifc, collector, drawing_tool, drawing=None, object_type=None):
context = drawing_tool.get_annotation_context(drawing_tool.get_drawing_target_view(drawing)) context = drawing_tool.get_annotation_context(target_view := drawing_tool.get_drawing_target_view(drawing))
if not context: if not context:
return "No annotation context for drawing" return f"No annotation context Annotation/{target_view} for drawing"
drawing_tool.show_decorations() drawing_tool.show_decorations()
obj = drawing_tool.create_annotation_object(drawing, object_type) obj = drawing_tool.create_annotation_object(drawing, object_type)
element = ifc.get_entity(obj) element = ifc.get_entity(obj)