-
Alan Odom authored
Most of the recommendations from pylint are now done, I have not changed variables like v in expression [v for v in... as I consider these to be normal coding practice. Rename pdt_com_functions.py to pdt_command_functions.py Fix error in Intersect operation if selected vertices resulted in more than 2 edges being selected. Priority is given to two edges as a selection, then to 4 vertices, if the four vertices represent two edges, the intersection point is at the intersection of the two edges, which might not be the four vertices, if one of the vertices forms part of two edges that are also selected. Priority is 2 edges, then 4 vertices selected individually with the mouse.
Alan Odom authoredMost of the recommendations from pylint are now done, I have not changed variables like v in expression [v for v in... as I consider these to be normal coding practice. Rename pdt_com_functions.py to pdt_command_functions.py Fix error in Intersect operation if selected vertices resulted in more than 2 edges being selected. Priority is given to two edges as a selection, then to 4 vertices, if the four vertices represent two edges, the intersection point is at the intersection of the two edges, which might not be the four vertices, if one of the vertices forms part of two edges that are also selected. Priority is 2 edges, then 4 vertices selected individually with the mouse.
pdt_command.py 27.06 KiB
# ***** BEGIN GPL LICENSE BLOCK *****
#
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ***** END GPL LICENCE BLOCK *****
#
# -----------------------------------------------------------------------
# Author: Alan Odom (Clockmender), Rune Morling (ermo) Copyright (c) 2019
# -----------------------------------------------------------------------
#
import bpy
import bmesh
from bpy.types import Operator
from mathutils import Vector
from .pdt_functions import (
debug,
intersection,
obj_check,
oops,
update_sel,
)
from .pdt_command_functions import (
command_maths,
vector_build,
move_cursor_pivot,
join_two_vertices,
set_angle_distance_two,
set_angle_distance_three,
origin_to_cursor,
taper,
placement_normal,
placement_centre,
placement_intersect,
)
from .pdt_msg_strings import (
PDT_ERR_ADDVEDIT,
PDT_ERR_BAD3VALS,
PDT_ERR_BADFLETTER,
PDT_ERR_CHARS_NUM,
PDT_ERR_DUPEDIT,
PDT_ERR_EXTEDIT,
PDT_ERR_FACE_SEL,
PDT_ERR_FILEDIT,
PDT_ERR_NON_VALID,
PDT_ERR_NO_ACT_OBJ,
PDT_ERR_NO_SEL_GEOM,
PDT_ERR_SEL_1_EDGE,
PDT_ERR_SEL_1_EDGEM,
PDT_ERR_SEL_1_VERT,
PDT_ERR_SPLITEDIT
)
from .pdt_bix import add_line_to_bisection
from .pdt_etof import extend_vertex
from .pdt_xall import intersect_all
def pdt_help(self, context):
"""Display PDT Command Line help in a pop-up."""
label = self.layout.label
label(text="Primary Letters (Available Secondary Letters):")
label(text="")
label(text="C: Cursor (a, d, i, p)")
label(text="D: Duplicate Geometry (d, i)")
label(text="E: Extrude Geometry (d, i)")
label(text="F: Fillet (v, e)")
label(text="G: Grab (Move) (a, d, i, p)")
label(text="N: New Vertex (a, d, i, p)")
label(text="M: Maths Functions (x, y, z, d, a, p)")
label(text="P: Pivot Point (a, d, i, p)")
label(text="V: Extrude Vertice Only (a, d, i, p)")
label(text="S: Split Edges (a, d, i, p)")
label(text="?: Quick Help")
label(text="")
label(text="Secondary Letters:")
label(text="")
label(text="- General Options:")
label(text="a: Absolute (Global) Coordinates e.g. 1,3,2")
label(text="d: Delta (Relative) Coordinates, e.g. 0.5,0,1.2")
label(text="i: Directional (Polar) Coordinates e.g. 2.6,45")
label(text="p: Percent e.g. 67.5")
label(text="- Fillet Options:")
label(text="v: Fillet Vertices")
label(text="e: Fillet Edges")
label(text="i: Fillet & Intersect 2 Disconnected Edges")
label(text="- Math Options:")
label(text="x, y, z: Send result to X, Y and Z input fields in PDT Design")
label(text="d, a, p: Send result to Distance, Angle or Percent input field in PDT Design")
label(text="o: Send Maths Calculation to Output")
label(text="")
label(text="Note that commands are case-insensitive: ED = Ed = eD = ed")
label(text="")
label(text="Examples:")
label(text="")
label(text="ed0.5,,0.6")
label(text="'- Extrude Geometry Delta 0.5 in X, 0 in Y, 0.6 in Z")
label(text="")
label(text="fe0.1,4,0.5")
label(text="'- Fillet Edges")
label(text="'- Radius: 0.1 (float) -- the radius (or offset) of the bevel/fillet")
label(text="'- Segments: 4 (int) -- choosing an even amount of segments gives better geometry")
label(text="'- Profile: 0.5 (float[0.0;1.0]) -- 0.5 (default) yields a circular, convex shape")
class PDT_OT_CommandReRun(Operator):
"""Repeat Current Displayed Command."""
bl_idname = "pdt.command_rerun"
bl_label = "Re-run Current Command"
bl_options = {"REGISTER", "UNDO"}
def execute(self, context):
"""Repeat Current Command Line Input.
Args:
context: Blender bpy.context instance.
Returns:
Nothing.
"""
command_run(self, context)
return {"FINISHED"}
def command_run(self, context):
"""Run Command String as input into Command Line.
Args:
context: Blender bpy.context instance.
Note:
Uses pg.command, pg.error & many other 'pg.' variables to set PDT menu items,
or alter functions
Command Format; Operation(single letter) Mode(single letter) Values(up to 3 values
separated by commas)
Example; CD0.4,0.6,1.1 - Moves Cursor Delta XYZ = 0.4,0.6,1.1 from Current Position/Active
Vertex/Object Origin
Example; SP35 - Splits active Edge at 35% of separation between edge's vertices
Valid First Letters (as 'operation' - pg.command[0])
C = Cursor, G = Grab(move), N = New Vertex, V = Extrude Vertices Only,
E = Extrude geometry, P = Move Pivot Point, D = Duplicate geometry, S = Split Edges
Capitals and lower case letters are both allowed
Valid Second Letters (as 'mode' - pg.command[1])
A = Absolute XYZ, D = Delta XYZ, I = Distance at Angle, P = Percent
X = X Delta, Y = Y, Delta Z, = Z Delta, O = Output (Maths Operation only)
V = Vertex Bevel, E = Edge Bevel
Capitals and lower case letters are both allowed
Valid Values (pdt_command[2:])
Only Integers and Floats, missing values are set to 0, appropriate length checks are
performed as Values is split by commas.
Example; CA,,3 - Cursor to Absolute, is re-interpreted as CA0,0,3
Exception for Maths Operation, Values section is evaluated as Maths command
Example; madegrees(atan(3/4)) - sets PDT Angle to smallest angle of 3,4,5 Triangle;
(36.8699 degrees)
Returns:
Nothing.
"""
scene = context.scene
pg = scene.pdt_pg
command = pg.command.strip()
# Check First Letter.
if command == "?" or command.lower() == "help":
# fmt: off
context.window_manager.popup_menu(pdt_help, title="PDT Command Line Help", icon="INFO")
# fmt: on
return
elif command == "":
return
elif command.upper() == "J2V":
join_two_vertices(context)
return
elif command.upper() == "AD2":
set_angle_distance_two(context)
return
elif command.upper() == "AD3":
set_angle_distance_three(context)
return
elif command.upper() == "OTC":
origin_to_cursor(context)
return
elif command.upper() == "TAP":
taper(self, context)
return
elif command.upper() == "BIS":
add_line_to_bisection(context)
return
elif command.upper() == "ETF":
extend_vertex(self, context)
return
elif command.upper() == "INTALL":
intersect_all(context)
return
elif command.upper()[1:4] == "NML":
placement_normal(context, command.upper()[0])
return
elif command.upper()[1:4] == "CEN":
placement_centre(context, command.upper()[0])
return
elif command.upper()[1:4] == "INT":
placement_intersect(context, command.upper()[0])
return
elif len(command) < 3:
pg.error = PDT_ERR_CHARS_NUM
context.window_manager.popup_menu(oops, title="Error", icon="ERROR")
return
operation = command[0].upper()
if operation not in {"C", "D", "E", "F", "G", "N", "M", "P", "V", "S"}:
pg.error = PDT_ERR_BADFLETTER
context.window_manager.popup_menu(oops, title="Error", icon="ERROR")
return
mode = command[1].lower()
# Check Second Letter.
if operation == "F":
if mode not in {"v", "e", "i"}:
pg.error = f"'{mode}' {PDT_ERR_NON_VALID} '{operation}'"
context.window_manager.popup_menu(oops, title="Error", icon="ERROR")
return
elif operation in {"D", "E"}:
if mode not in {"d", "i"}:
pg.error = f"'{mode}' {PDT_ERR_NON_VALID} '{operation}'"
context.window_manager.popup_menu(oops, title="Error", icon="ERROR")
return
elif operation == "M":
if mode not in {"a", "d", "i", "p", "o", "x", "y", "z"}:
pg.error = f"'{mode}' {PDT_ERR_NON_VALID} '{operation}'"
context.window_manager.popup_menu(oops, title="Error", icon="ERROR")
return
else:
if mode not in {"a", "d", "i", "p"}:
pg.error = f"'{mode}' {PDT_ERR_NON_VALID} '{operation}'"
context.window_manager.popup_menu(oops, title="Error", icon="ERROR")
return
# --------------
# Maths Operation
if operation == "M":
command_maths(context, mode, pg, command[2:], mode)
return
# -----------------------------------------------------
# Not a Maths Operation, so let's parse the command line
values = command[2:].split(",")
ind = 0
for r in values:
try:
_ = float(r)
good = True
except ValueError:
values[ind] = "0"
ind = ind + 1
mode_s = pg.select
flip_a = pg.flip_angle
flip_p = pg.flip_percent
ext_a = pg.extend
plane = pg.plane
obj = context.view_layer.objects.active
bm, good = obj_check(obj, scene, operation)
if good:
obj_loc = obj.matrix_world.decompose()[0]
else:
obj_loc = None
if mode_s == 'SEL' and bm is not None and mode not in {"a"}:
if len(bm.select_history) == 0:
if len([v for v in bm.verts if v.select]) == 0:
pg.error = PDT_ERR_NO_SEL_GEOM
context.window_manager.popup_menu(oops, title="Error", icon="ERROR")
return
else:
verts = [v for v in bm.verts if v.select]
else:
verts = bm.select_history
else:
verts = []
debug(f"command: {command}")
debug(f"obj: {obj}, bm: {bm}, obj_loc: {obj_loc}")
# ---------------------
# Cursor or Pivot Point
if operation in {"C", "P"}:
# Absolute/Global Coordinates, or Delta/Relative Coordinates
if mode in {"a", "d"}:
valid_result, vector_delta = vector_build(context, pg, obj, operation, values, 3)
# Direction/Polar Coordinates
elif mode == "i":
valid_result, vector_delta = vector_build(context, pg, obj, operation, values, 2)
# Percent Options
elif mode == "p":
valid_result, vector_delta = vector_build(context, pg, obj, operation, values, 1)
if valid_result:
move_cursor_pivot(context, pg, obj, verts, operation,
mode, vector_delta)
return
# ------------------------
# Move Vertices or Objects
elif operation == "G":
if obj.mode == "EDIT":
if len(verts) == 0:
pg.error = PDT_ERR_NO_SEL_GEOM
context.window_manager.popup_menu(oops, title="Error", icon="ERROR")
return
# Absolute/Global Coordinates
if mode == "a":
valid_result, vector_delta = vector_build(context, pg, obj, operation, values, 3)
if not valid_result:
return
if obj.mode == "EDIT":
for v in verts:
v.co = vector_delta - obj_loc
bmesh.ops.remove_doubles(
bm, verts=[v for v in bm.verts if v.select], dist=0.0001
)
elif obj.mode == "OBJECT":
for ob in context.view_layer.objects.selected:
ob.location = vector_delta
elif mode in {"d", "i"}:
if mode == "d":
# Delta/Relative Coordinates
valid_result, vector_delta = vector_build(context, pg, obj, operation, values, 3)
if not valid_result:
return
else:
# Direction/Polar Coordinates
valid_result, vector_delta = vector_build(context, pg, obj, operation, values, 2)
if not valid_result:
return
if vector_delta is not None:
if obj.mode == "EDIT":
bmesh.ops.translate(
bm, verts=[v for v in bm.verts if v.select], vec=vector_delta
)
elif obj.mode == "OBJECT":
for ob in context.view_layer.objects.selected:
ob.location = obj_loc + vector_delta
# Percent Options
elif mode == "p":
valid_result, vector_delta = vector_build(context, pg, obj, operation, values, 1)
if not valid_result:
return
if vector_delta is not None:
if obj.mode == 'EDIT':
verts[-1].co = vector_delta
elif obj.mode == "OBJECT":
obj.location = vector_delta
if obj.mode == 'EDIT':
bmesh.update_edit_mesh(obj.data)
bm.select_history.clear()
return
# --------------
# Add New Vertex
elif operation == "N":
if not obj.mode == "EDIT":
pg.error = PDT_ERR_ADDVEDIT
context.window_manager.popup_menu(oops, title="Error", icon="ERROR")
return
# Absolute/Global Coordinates
if mode == "a":
valid_result, vector_delta = vector_build(context, pg, obj, operation, values, 3)
if not valid_result:
return
new_vertex = bm.verts.new(vector_delta - obj_loc)
# Delta/Relative Coordinates
elif mode == "d":
valid_result, vector_delta = vector_build(context, pg, obj, operation, values, 3)
if not valid_result:
return
new_vertex = bm.verts.new(verts[-1].co + vector_delta)
# Direction/Polar Coordinates
elif mode == "i":
valid_result, vector_delta = vector_build(context, pg, obj, operation, values, 2)
if not valid_result:
return
new_vertex = bm.verts.new(verts[-1].co + vector_delta)
# Percent Options
elif mode == "p":
valid_result, vector_delta = vector_build(context, pg, obj, operation, values, 1)
if not valid_result:
return
new_vertex = bm.verts.new(vector_delta)
for v in [v for v in bm.verts if v.select]:
v.select_set(False)
new_vertex.select_set(True)
bmesh.update_edit_mesh(obj.data)
bm.select_history.clear()
return
# -----------
# Split Edges
elif operation == "S":
if not obj.mode == "EDIT":
pg.error = PDT_ERR_SPLITEDIT
context.window_manager.popup_menu(oops, title="Error", icon="ERROR")
return
# Absolute/Global Coordinates
if mode == "a":
valid_result, vector_delta = vector_build(context, pg, obj, operation, values, 3)
if not valid_result:
return
edges = [e for e in bm.edges if e.select]
if len(edges) != 1:
pg.error = f"{PDT_ERR_SEL_1_EDGE} {len(edges)})"
context.window_manager.popup_menu(oops, title="Error", icon="ERROR")
return
geom = bmesh.ops.subdivide_edges(bm, edges=edges, cuts=1)
new_verts = [v for v in geom["geom_split"] if isinstance(v, bmesh.types.BMVert)]
new_vertex = new_verts[0]
new_vertex.co = vector_delta - obj_loc
# Delta/Relative Coordinates
elif mode == "d":
valid_result, vector_delta = vector_build(context, pg, obj, operation, values, 3)
if not valid_result:
return
edges = [e for e in bm.edges if e.select]
faces = [f for f in bm.faces if f.select]
if len(faces) != 0:
pg.error = PDT_ERR_FACE_SEL
context.window_manager.popup_menu(oops, title="Error", icon="ERROR")
return
if len(edges) < 1:
pg.error = f"{PDT_ERR_SEL_1_EDGEM} {len(edges)})"
context.window_manager.popup_menu(oops, title="Error", icon="ERROR")
return
geom = bmesh.ops.subdivide_edges(bm, edges=edges, cuts=1)
new_verts = [v for v in geom["geom_split"] if isinstance(v, bmesh.types.BMVert)]
bmesh.ops.translate(bm, verts=new_verts, vec=vector_delta)
# Directional/Polar Coordinates
elif mode == "i":
valid_result, vector_delta = vector_build(context, pg, obj, operation, values, 2)
if not valid_result:
return
edges = [e for e in bm.edges if e.select]
faces = [f for f in bm.faces if f.select]
if len(faces) != 0:
pg.error = PDT_ERR_FACE_SEL
context.window_manager.popup_menu(oops, title="Error", icon="ERROR")
return
if len(edges) < 1:
pg.error = f"{PDT_ERR_SEL_1_EDGEM} {len(edges)})"
context.window_manager.popup_menu(oops, title="Error", icon="ERROR")
return
geom = bmesh.ops.subdivide_edges(bm, edges=edges, cuts=1)
new_verts = [v for v in geom["geom_split"] if isinstance(v, bmesh.types.BMVert)]
bmesh.ops.translate(bm, verts=new_verts, vec=vector_delta)
# Percent Options
elif mode == "p":
valid_result, vector_delta = vector_build(context, pg, obj, operation, values, 1)
if not valid_result:
return
edges = [e for e in bm.edges if e.select]
faces = [f for f in bm.faces if f.select]
if len(faces) != 0:
pg.error = PDT_ERR_FACE_SEL
context.window_manager.popup_menu(oops, title="Error", icon="ERROR")
return
if len(edges) != 1:
pg.error = f"{PDT_ERR_SEL_1_EDGEM} {len(edges)})"
context.window_manager.popup_menu(oops, title="Error", icon="ERROR")
return
geom = bmesh.ops.subdivide_edges(bm, edges=edges, cuts=1)
new_verts = [v for v in geom["geom_split"] if isinstance(v, bmesh.types.BMVert)]
new_vertex = new_verts[0]
new_vertex.co = vector_delta
for v in [v for v in bm.verts if v.select]:
v.select_set(False)
for v in new_verts:
v.select_set(False)
bmesh.update_edit_mesh(obj.data)
bm.select_history.clear()
return
# ----------------
# Extrude Vertices
elif operation == "V":
if not obj.mode == "EDIT":
pg.error = PDT_ERR_EXTEDIT
context.window_manager.popup_menu(oops, title="Error", icon="ERROR")
return
# Absolute/Global Coordinates
if mode == "a":
valid_result, vector_delta = vector_build(context, pg, obj, operation, values, 3)
if not valid_result:
return
new_vertex = bm.verts.new(vector_delta - obj_loc)
for v in verts:
bm.edges.new([v, new_vertex])
v.select_set(False)
new_vertex.select_set(True)
bmesh.ops.remove_doubles(
bm, verts=[v for v in bm.verts if v.select], dist=0.0001
)
# Delta/Relative Coordinates
elif mode == "d":
valid_result, vector_delta = vector_build(context, pg, obj, operation, values, 3)
if not valid_result:
return
for v in verts:
new_vertex = bm.verts.new(v.co)
new_vertex.co = new_vertex.co + vector_delta
bm.edges.new([v, new_vertex])
v.select_set(False)
new_vertex.select_set(True)
# Direction/Polar Coordinates
elif mode == "i":
valid_result, vector_delta = vector_build(context, pg, obj, operation, values, 2)
if not valid_result:
return
for v in verts:
new_vertex = bm.verts.new(v.co)
new_vertex.co = new_vertex.co + vector_delta
bm.edges.new([v, new_vertex])
v.select_set(False)
new_vertex.select_set(True)
# Percent Options
elif mode == "p":
valid_result, vector_delta = vector_build(context, pg, obj, operation, values, 1)
if not valid_result:
return
verts = [v for v in bm.verts if v.select].copy()
if len(verts) == 0:
pg.error = PDT_ERR_NO_SEL_GEOM
context.window_manager.popup_menu(oops, title="Error", icon="ERROR")
return
new_vertex = bm.verts.new(vector_delta)
if ext_a:
for v in [v for v in bm.verts if v.select]:
bm.edges.new([v, new_vertex])
v.select_set(False)
else:
bm.edges.new([verts[-1], new_vertex])
new_vertex.select_set(True)
bmesh.update_edit_mesh(obj.data)
bm.select_history.clear()
return
# ----------------
# Extrude Geometry
elif operation == "E":
if not obj.mode == "EDIT":
pg.error = PDT_ERR_EXTEDIT
context.window_manager.popup_menu(oops, title="Error", icon="ERROR")
return
# Delta/Relative Coordinates
if mode == "d":
valid_result, vector_delta = vector_build(context, pg, obj, operation, values, 3)
if not valid_result:
return
# Direction/Polar Coordinates
elif mode == "i":
valid_result, vector_delta = vector_build(context, pg, obj, values, 2)
if not valid_result:
return
ret = bmesh.ops.extrude_face_region(
bm,
geom=(
[f for f in bm.faces if f.select]
+ [e for e in bm.edges if e.select]
+ [v for v in bm.verts if v.select]
),
use_select_history=True,
)
geom_extr = ret["geom"]
verts_extr = [v for v in geom_extr if isinstance(v, bmesh.types.BMVert)]
edges_extr = [e for e in geom_extr if isinstance(e, bmesh.types.BMEdge)]
faces_extr = [f for f in geom_extr if isinstance(f, bmesh.types.BMFace)]
del ret
bmesh.ops.translate(bm, verts=verts_extr, vec=vector_delta)
update_sel(bm, verts_extr, edges_extr, faces_extr)
bmesh.update_edit_mesh(obj.data)
bm.select_history.clear()
return
# ------------------
# Duplicate Geometry
elif operation == "D":
if not obj.mode == "EDIT":
pg.error = PDT_ERR_DUPEDIT
context.window_manager.popup_menu(oops, title="Error", icon="ERROR")
return
# Delta/Relative Coordinates
if mode == "d":
valid_result, vector_delta = vector_build(context, pg, obj, operation, values, 3)
if not valid_result:
return
# Direction/Polar Coordinates
elif mode == "i":
valid_result, vector_delta = vector_build(context, pg, obj, operation, values, 2)
if not valid_result:
return
ret = bmesh.ops.duplicate(
bm,
geom=(
[f for f in bm.faces if f.select]
+ [e for e in bm.edges if e.select]
+ [v for v in bm.verts if v.select]
),
use_select_history=True,
)
geom_dupe = ret["geom"]
verts_dupe = [v for v in geom_dupe if isinstance(v, bmesh.types.BMVert)]
edges_dupe = [e for e in geom_dupe if isinstance(e, bmesh.types.BMEdge)]
faces_dupe = [f for f in geom_dupe if isinstance(f, bmesh.types.BMFace)]
del ret
bmesh.ops.translate(bm, verts=verts_dupe, vec=vector_delta)
update_sel(bm, verts_dupe, edges_dupe, faces_dupe)
bmesh.update_edit_mesh(obj.data)
bm.select_history.clear()
return
# ---------------
# Fillet Geometry
elif operation == "F":
if obj is None:
pg.error = PDT_ERR_NO_ACT_OBJ
context.window_manager.popup_menu(oops, title="Error", icon="ERROR")
return
if not obj.mode == "EDIT":
pg.error = PDT_ERR_FILEDIT
context.window_manager.popup_menu(oops, title="Error", icon="ERROR")
return
if len(values) != 3:
pg.error = PDT_ERR_BAD3VALS
context.window_manager.popup_menu(oops, title="Error", icon="ERROR")
return
if mode in {"i", "v"}:
vert_bool = True
elif mode == "e":
vert_bool = False
verts = [v for v in bm.verts if v.select]
if len(verts) == 0:
pg.error = PDT_ERR_SEL_1_VERT
context.window_manager.popup_menu(oops, title="Error", icon="ERROR")
return
# Note that passing an empty parameter results in that parameter being seen as "0"
# _offset <= 0 is ignored since a bevel/fillet radius must be > 0 to make sense
_offset = float(values[0])
_segments = int(values[1])
if _segments < 1:
_segments = 1 # This is a single, flat segment (ignores profile)
_profile = float(values[2])
if _profile < 0.0 or _profile > 1.0:
_profile = 0.5 # This is a circular profile
if mode == "i":
# Fillet & Intersect Two Edges
edges = [e for e in bm.edges if e.select]
if len(edges) == 2 and len(verts) == 4:
v_active = edges[0].verts[0]
v_other = edges[0].verts[1]
v_last = edges[1].verts[0]
v_first = edges[1].verts[1]
vector_delta, done = intersection(v_active.co,
v_other.co,
v_last.co,
v_first.co,
plane
)
if not done:
errmsg = f"{PDT_ERR_INT_LINES} {plane} {PDT_LAB_PLANE}"
self.report({"ERROR"}, errmsg)
return {"FINISHED"}
if (v_active.co - vector_delta).length < (v_other.co - vector_delta).length:
v_active.co = vector_delta
v_other.select_set(False)
else:
v_other.co = vector_delta
v_active.select_set(False)
if (v_last.co - vector_delta).length < (v_first.co - vector_delta).length:
v_last.co = vector_delta
v_first.select_set(False)
else:
v_first.co = vector_delta
v_last.select_set(False)
bmesh.ops.remove_doubles(bm, verts=bm.verts, dist=0.0001)
bpy.ops.mesh.bevel(
offset_type="OFFSET",
offset=_offset,
segments=_segments,
profile=_profile,
vertex_only=vert_bool
)
return