AnimAll: rename the "Animate" tab back to "Animation"
[blender-addons.git] / precision_drawing_tools / pdt_etof.py
blobedfc42e3ab373f2d0f0789f3341a5d3e6997e71c
1 # SPDX-FileCopyrightText: 2016-2022 Blender Foundation
3 # SPDX-License-Identifier: GPL-2.0-or-later
6 # ----------------------------------------------------------
7 # Author: Zeffii
8 # Modified by: Alan Odom (Clockmender) & Rune Morling (ermo)
9 # ----------------------------------------------------------
12 import bpy
13 import bmesh
14 from mathutils.geometry import intersect_line_plane
15 from .pdt_msg_strings import (
16 PDT_ERR_NOINT,
17 PDT_ERR_EDOB_MODE,
18 PDT_ERR_SEL_1_E_1_F,
20 from .pdt_functions import oops
23 def failure_message(context):
24 """Warn to the user to select 1 edge and 1 face.
26 Args:
27 context: Blender bpy.context instance.
29 Returns:
30 Nothing.
31 """
33 pg = context.scene.pdt_pg
34 pg.error = f"{PDT_ERR_SEL_1_E_1_F}"
35 context.window_manager.popup_menu(oops, title="Error", icon="ERROR")
38 def failure_message_on_plane(context):
39 """Report an informative error message in a popup.
41 Args:
42 context: Blender bpy.context instance.
44 Returns:
45 Nothing.
46 """
48 pg = context.scene.pdt_pg
49 pg.error = f"{PDT_ERR_NOINT}"
50 context.window_manager.popup_menu(oops, title="Error", icon="ERROR")
52 def extend_vertex(context):
53 """Computes Edge Extension to Face.
55 Args:
56 context: Blender bpy.context instance.
58 Returns:
59 Nothing.
60 """
62 obj = bpy.context.edit_object
63 pg = context.scene.pdt_pg
65 if all([bool(obj), obj.type == "MESH", obj.mode == "EDIT"]):
66 object_data = obj.data
67 bm = bmesh.from_edit_mesh(object_data)
68 verts = bm.verts
69 faces = bm.faces
71 planes = [f for f in faces if f.select]
72 if not len(planes) == 1:
73 failure_message(context)
74 return
76 plane = planes[0]
77 plane_vert_indices = plane.verts[:]
78 all_selected_vert_indices = [v for v in verts if v.select]
80 plane_verts = set(plane_vert_indices)
81 all_verts = set(all_selected_vert_indices)
82 diff_verts = all_verts.difference(plane_verts)
83 diff_verts = list(diff_verts)
85 if not len(diff_verts) == 2:
86 failure_message(context)
87 return
89 (v1_ref, v1), (v2_ref, v2) = [(i, i.co) for i in diff_verts]
91 plane_co = plane.calc_center_median()
92 plane_no = plane.normal
94 new_co = intersect_line_plane(v1, v2, plane_co, plane_no, False)
96 if new_co:
97 new_vertex = verts.new(new_co)
98 a_len = (v1 - new_co).length
99 b_len = (v2 - new_co).length
101 vertex_reference = v1_ref if (a_len < b_len) else v2_ref
102 bm.edges.new([vertex_reference, new_vertex])
103 bmesh.update_edit_mesh(object_data, loop_triangles=True)
105 else:
106 failure_message_on_plane(context)
107 else:
108 pg.error = f"{PDT_ERR_EDOB_MODE},{obj.mode})"
109 context.window_manager.popup_menu(oops, title="Error", icon="ERROR")
110 return
113 class PDT_OT_EdgeToFace(bpy.types.Operator):
114 """Extend Selected Edge to Projected Intersection with Selected Face"""
116 bl_idname = "pdt.edge_to_face"
117 bl_label = "Extend Edge to Face"
118 bl_options = {"REGISTER", "UNDO"}
120 @classmethod
121 def poll(cls, context):
122 """Only allow this to work if a mesh is selected in EDIT mode.
124 Args:
125 context: Blender bpy.context instance.
127 Returns:
128 Boolean.
131 obj = context.object
132 if obj is None:
133 return False
134 return all([bool(obj), obj.type == "MESH", obj.mode == "EDIT"])
136 def execute(self, context):
137 """Extends Disconnected Edge to Intersect with Face.
139 Args:
140 context: Blender bpy.context instance.
142 Returns:
143 Status Set.
146 pg = context.scene.pdt_pg
147 pg.command = f"etf"
148 return {"FINISHED"}