Cleanup: strip trailing space, remove BOM
[blender-addons.git] / precision_drawing_tools / pdt_design.py
blobd8caa455c916b37511a7de3d01bd48732cea68bc
1 # ***** BEGIN GPL LICENSE BLOCK *****
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software Foundation,
16 # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 # ***** END GPL LICENCE BLOCK *****
20 # -----------------------------------------------------------------------
21 # Author: Alan Odom (Clockmender), Rune Morling (ermo) Copyright (c) 2019
22 # -----------------------------------------------------------------------
24 from bpy.types import Operator
25 from .pdt_msg_strings import (
26 PDT_ERR_NON_VALID,
27 PDT_LAB_ABS,
28 PDT_LAB_DEL,
29 PDT_LAB_DIR,
30 PDT_LAB_INTERSECT,
31 PDT_LAB_PERCENT,
35 class PDT_OT_PlacementAbs(Operator):
36 """Use Absolute, or Global Placement"""
38 bl_idname = "pdt.absolute"
39 bl_label = "Absolute Mode"
40 bl_options = {"REGISTER", "UNDO"}
42 def execute(self, context):
43 """Manipulates Geometry, or Objects by Absolute (World) Coordinates.
45 Note:
46 - Reads pg.operate from Operation Mode Selector as 'operation'
47 - Reads pg.cartesian_coords scene variables to:
48 -- set position of CUrsor (CU)
49 -- set postion of Pivot Point (PP)
50 -- MoVe geometry/objects (MV)
51 -- Extrude Vertices (EV)
52 -- Split Edges (SE)
53 -- add a New Vertex (NV)
55 Invalid Options result in self.report Error.
57 Args:
58 context: Blender bpy.context instance.
60 Returns:
61 Status Set.
62 """
64 pg = context.scene.pdt_pg
65 operation = pg.operation
66 decimal_places = context.preferences.addons[__package__].preferences.pdt_input_round
68 if operation == "CU":
69 # Cursor
70 pg.command = (
71 f"ca{str(round(pg.cartesian_coords.x, decimal_places))}"
72 f",{str(round(pg.cartesian_coords.y, decimal_places))}"
73 f",{str(round(pg.cartesian_coords.z, decimal_places))}"
75 elif operation == "PP":
76 # Pivot Point
77 pg.command = (
78 f"pa{str(round(pg.cartesian_coords.x, decimal_places))}"
79 f",{str(round(pg.cartesian_coords.y, decimal_places))}"
80 f",{str(round(pg.cartesian_coords.z, decimal_places))}"
82 elif operation == "MV":
83 # Move Entities
84 pg.command = (
85 f"ga{str(round(pg.cartesian_coords.x, decimal_places))}"
86 f",{str(round(pg.cartesian_coords.y, decimal_places))}"
87 f",{str(round(pg.cartesian_coords.z, decimal_places))}"
89 elif operation == "SE":
90 # Split Edges
91 pg.command = (
92 f"sa{str(round(pg.cartesian_coords.x, decimal_places))}"
93 f",{str(round(pg.cartesian_coords.y, decimal_places))}"
94 f",{str(round(pg.cartesian_coords.z, decimal_places))}"
96 elif operation == "NV":
97 # New Vertex
98 pg.command = (
99 f"na{str(round(pg.cartesian_coords.x, decimal_places))}"
100 f",{str(round(pg.cartesian_coords.y, decimal_places))}"
101 f",{str(round(pg.cartesian_coords.z, decimal_places))}"
103 elif operation == "EV":
104 # Extrude Vertices
105 pg.command = (
106 f"va{str(round(pg.cartesian_coords.x, decimal_places))}"
107 f",{str(round(pg.cartesian_coords.y, decimal_places))}"
108 f",{str(round(pg.cartesian_coords.z, decimal_places))}"
110 else:
111 error_message = f"{operation} {PDT_ERR_NON_VALID} {PDT_LAB_ABS}"
112 self.report({"ERROR"}, error_message)
113 return {"FINISHED"}
116 class PDT_OT_PlacementDelta(Operator):
117 """Use Delta, or Incremental Placement"""
119 bl_idname = "pdt.delta"
120 bl_label = "Delta Mode"
121 bl_options = {"REGISTER", "UNDO"}
123 def execute(self, context):
124 """Manipulates Geometry, or Objects by Delta Offset (Increment).
126 Note:
127 - Reads pg.operation from Operation Mode Selector as 'operation'
128 - Reads pg.select, pg.plane, pg.cartesian_coords scene variables to:
129 -- set position of CUrsor (CU)
130 -- set position of Pivot Point (PP)
131 -- MoVe geometry/objects (MV)
132 -- Extrude Vertices (EV)
133 -- Split Edges (SE)
134 -- add a New Vertex (NV)
135 -- Duplicate Geometry (DG)
136 -- Extrude Geometry (EG)
138 Invalid Options result in self.report Error.
140 Args:
141 context: Blender bpy.context instance.
143 Returns:
144 Status Set.
147 pg = context.scene.pdt_pg
148 operation = pg.operation
149 decimal_places = context.preferences.addons[__package__].preferences.pdt_input_round
151 if operation == "CU":
152 # Cursor
153 pg.command = (
154 f"cd{str(round(pg.cartesian_coords.x, decimal_places))}"
155 f",{str(round(pg.cartesian_coords.y, decimal_places))}"
156 f",{str(round(pg.cartesian_coords.z, decimal_places))}"
158 elif operation == "PP":
159 # Pivot Point
160 pg.command = (
161 f"pd{str(round(pg.cartesian_coords.x, decimal_places))}"
162 f",{str(round(pg.cartesian_coords.y, decimal_places))}"
163 f",{str(round(pg.cartesian_coords.z, decimal_places))}"
165 elif operation == "MV":
166 # Move Entities
167 pg.command = (
168 f"gd{str(round(pg.cartesian_coords.x, decimal_places))}"
169 f",{str(round(pg.cartesian_coords.y, decimal_places))}"
170 f",{str(round(pg.cartesian_coords.z, decimal_places))}"
172 elif operation == "SE":
173 # Split Edges
174 pg.command = (
175 f"sd{str(round(pg.cartesian_coords.x, decimal_places))}"
176 f",{str(round(pg.cartesian_coords.y, decimal_places))}"
177 f",{str(round(pg.cartesian_coords.z, decimal_places))}"
179 elif operation == "NV":
180 # New Vertex
181 pg.command = (
182 f"nd{str(round(pg.cartesian_coords.x, decimal_places))}"
183 f",{str(round(pg.cartesian_coords.y, decimal_places))}"
184 f",{str(round(pg.cartesian_coords.z, decimal_places))}"
186 elif operation == "EV":
187 # Extrude Vertices
188 pg.command = (
189 f"vd{str(round(pg.cartesian_coords.x, decimal_places))}"
190 f",{str(round(pg.cartesian_coords.y, decimal_places))}"
191 f",{str(round(pg.cartesian_coords.z, decimal_places))}"
193 elif operation == "DG":
194 # Duplicate Entities
195 pg.command = (
196 f"dd{str(round(pg.cartesian_coords.x, decimal_places))}"
197 f",{str(round(pg.cartesian_coords.y, decimal_places))}"
198 f",{str(round(pg.cartesian_coords.z, decimal_places))}"
200 elif operation == "EG":
201 # Extrude Geometry
202 pg.command = (
203 f"ed{str(round(pg.cartesian_coords.x, decimal_places))}"
204 f",{str(round(pg.cartesian_coords.y, decimal_places))}"
205 f",{str(round(pg.cartesian_coords.z, decimal_places))}"
207 else:
208 error_message = f"{operation} {PDT_ERR_NON_VALID} {PDT_LAB_DEL}"
209 self.report({"ERROR"}, error_message)
210 return {"FINISHED"}
213 class PDT_OT_PlacementDis(Operator):
214 """Use Directional, or Distance @ Angle Placement"""
216 bl_idname = "pdt.distance"
217 bl_label = "Distance@Angle Mode"
218 bl_options = {"REGISTER", "UNDO"}
220 def execute(self, context):
221 """Manipulates Geometry, or Objects by Distance at Angle (Direction).
223 Note:
224 - Reads pg.operation from Operation Mode Selector as 'operation'
225 - Reads pg.select, pg.distance, pg.angle, pg.plane & pg.flip_angle scene variables to:
226 -- set position of CUrsor (CU)
227 -- set position of Pivot Point (PP)
228 -- MoVe geometry/objects (MV)
229 -- Extrude Vertices (EV)
230 -- Split Edges (SE)
231 -- add a New Vertex (NV)
232 -- Duplicate Geometry (DG)
233 -- Extrude Geometry (EG)
235 Invalid Options result in self.report Error.
237 Args:
238 context: Blender bpy.context instance.
240 Returns:
241 Status Set.
244 pg = context.scene.pdt_pg
245 operation = pg.operation
246 decimal_places = context.preferences.addons[__package__].preferences.pdt_input_round
248 if operation == "CU":
249 # Cursor
250 pg.command = (
251 f"ci{str(round(pg.distance, decimal_places))}"
252 f",{str(round(pg.angle, decimal_places))}"
254 elif operation == "PP":
255 # Pivot Point
256 pg.command = (
257 f"pi{str(round(pg.distance, decimal_places))}"
258 f",{str(round(pg.angle, decimal_places))}"
260 elif operation == "MV":
261 # Move Entities
262 pg.command = (
263 f"gi{str(round(pg.distance, decimal_places))}"
264 f",{str(round(pg.angle, decimal_places))}"
266 elif operation == "SE":
267 # Split Edges
268 pg.command = (
269 f"si{str(round(pg.distance, decimal_places))}"
270 f",{str(round(pg.angle, decimal_places))}"
272 elif operation == "NV":
273 # New Vertex
274 pg.command = (
275 f"ni{str(round(pg.distance, decimal_places))}"
276 f",{str(round(pg.angle, decimal_places))}"
278 elif operation == "EV":
279 # Extrude Vertices
280 pg.command = (
281 f"vi{str(round(pg.distance, decimal_places))}"
282 f",{str(round(pg.angle, decimal_places))}"
284 elif operation == "DG":
285 # Duplicate Geometry
286 pg.command = (
287 f"di{str(round(pg.distance, decimal_places))}"
288 f",{str(round(pg.angle, decimal_places))}"
290 elif operation == "EG":
291 # Extrude Geometry
292 pg.command = (
293 f"ei{str(round(pg.distance, decimal_places))}"
294 f",{str(round(pg.angle, decimal_places))}"
296 else:
297 error_message = f"{operation} {PDT_ERR_NON_VALID} {PDT_LAB_DIR}"
298 self.report({"ERROR"}, error_message)
299 return {"FINISHED"}
302 class PDT_OT_PlacementView(Operator):
303 """Use Distance Input for View Normal Axis Operations"""
305 bl_idname = "pdt.view_axis"
306 bl_label = "View Normal Axis Mode"
307 bl_options = {"REGISTER", "UNDO"}
309 def execute(self, context):
310 """Manipulates Geometry, or Objects by View Normal Axis Offset (Increment).
312 Note:
313 - Reads pg.operation from Operation Mode Selector as 'operation'
314 - Reads pg.select, pg.plane, pg.cartesian_coords scene variables to:
315 -- set position of CUrsor (CU)
316 -- set position of Pivot Point (PP)
317 -- MoVe geometry/objects (MV)
318 -- Extrude Vertices (EV)
319 -- Split Edges (SE)
320 -- add a New Vertex (NV)
321 -- Duplicate Geometry (DG)
322 -- Extrude Geometry (EG)
324 Invalid Options result in self.report Error.
326 Args:
327 context: Blender bpy.context instance.
329 Returns:
330 Status Set.
333 pg = context.scene.pdt_pg
334 operation = pg.operation
335 decimal_places = context.preferences.addons[__package__].preferences.pdt_input_round
337 if operation == "CU":
338 # Cursor
339 pg.command = (
340 f"cn{str(round(pg.distance, decimal_places))}"
342 elif operation == "PP":
343 # Pivot Point
344 pg.command = (
345 f"pn{str(round(pg.distance, decimal_places))}"
347 elif operation == "MV":
348 # Move Entities
349 pg.command = (
350 f"gn{str(round(pg.distance, decimal_places))}"
352 elif operation == "NV":
353 # New Vertex
354 pg.command = (
355 f"nn{str(round(pg.distance, decimal_places))}"
357 elif operation == "EV":
358 # Extrude Vertices
359 pg.command = (
360 f"vn{str(round(pg.distance, decimal_places))}"
362 elif operation == "DG":
363 # Duplicate Entities
364 pg.command = (
365 f"dn{str(round(pg.distance, decimal_places))}"
367 elif operation == "EG":
368 # Extrude Geometry
369 pg.command = (
370 f"en{str(round(pg.distance, decimal_places))}"
372 else:
373 error_message = f"{operation} {PDT_ERR_NON_VALID} {PDT_LAB_DEL}"
374 self.report({"ERROR"}, error_message)
375 return {"FINISHED"}
378 class PDT_OT_PlacementPer(Operator):
379 """Use Percentage Placement"""
381 bl_idname = "pdt.percent"
382 bl_label = "Percentage Mode"
383 bl_options = {"REGISTER", "UNDO"}
385 def execute(self, context):
386 """Manipulates Geometry, or Objects by Percentage between 2 points.
388 Note:
389 - Reads pg.operation from Operation Mode Selector as 'operation'
390 - Reads pg.percent, pg.extend & pg.flip_percent scene variables to:
391 -- set position of CUrsor (CU)
392 -- set position of Pivot Point (PP)
393 -- MoVe geometry/objects (MV)
394 -- Extrude Vertices (EV)
395 -- Split Edges (SE)
396 -- add a New Vertex (NV)
398 Invalid Options result in self.report Error.
400 Args:
401 context: Blender bpy.context instance.
403 Returns:
404 Status Set.
407 pg = context.scene.pdt_pg
408 operation = pg.operation
409 decimal_places = context.preferences.addons[__package__].preferences.pdt_input_round
411 if operation == "CU":
412 # Cursor
413 pg.command = f"cp{str(round(pg.percent, decimal_places))}"
414 elif operation == "PP":
415 # Pivot Point
416 pg.command = f"pp{str(round(pg.percent, decimal_places))}"
417 elif operation == "MV":
418 # Move Entities
419 pg.command = f"gp{str(round(pg.percent, decimal_places))}"
420 elif operation == "SE":
421 # Split Edges
422 pg.command = f"sp{str(round(pg.percent, decimal_places))}"
423 elif operation == "NV":
424 # New Vertex
425 pg.command = f"np{str(round(pg.percent, decimal_places))}"
426 elif operation == "EV":
427 # Extrude Vertices
428 pg.command = f"vp{str(round(pg.percent, decimal_places))}"
429 else:
430 error_message = f"{operation} {PDT_ERR_NON_VALID} {PDT_LAB_PERCENT}"
431 self.report({"ERROR"}, error_message)
432 return {"FINISHED"}
435 class PDT_OT_PlacementNormal(Operator):
436 """Use Normal, or Perpendicular Placement"""
438 bl_idname = "pdt.normal"
439 bl_label = "Normal Mode"
440 bl_options = {"REGISTER", "UNDO"}
442 def execute(self, context):
443 """Manipulates Geometry, or Objects by Normal Intersection between 3 points.
445 Note:
446 - Reads pg.operation from Operation Mode Selector as 'operation'
447 - Reads pg.extend scene variable to:
448 -- set position of CUrsor (CU)
449 -- set position of Pivot Point (PP)
450 -- MoVe geometry/objects (MV)
451 -- Extrude Vertices (EV)
452 -- Split Edges (SE)
453 -- add a New Vertex (NV)
455 Invalid Options result in self.report Error.
457 Args:
458 context: Blender bpy.context instance.
460 Returns:
461 Status Set.
464 pg = context.scene.pdt_pg
465 operation = pg.operation
466 if operation == "CU":
467 pg.command = f"cnml"
468 elif operation == "PP":
469 pg.command = f"pnml"
470 elif operation == "MV":
471 pg.command = f"gnml"
472 elif operation == "EV":
473 pg.command = f"vnml"
474 elif operation == "SE":
475 pg.command = f"snml"
476 elif operation == "NV":
477 pg.command = f"nnml"
478 else:
479 error_message = f"{operation} {PDT_ERR_NON_VALID} {PDT_LAB_INTERSECT}"
480 self.report({"ERROR"}, error_message)
481 return {"FINISHED"}
484 class PDT_OT_PlacementCen(Operator):
485 """Use Placement at Arc Centre"""
487 bl_idname = "pdt.centre"
488 bl_label = "Centre Mode"
489 bl_options = {"REGISTER", "UNDO"}
491 def execute(self, context):
492 """Manipulates Geometry, or Objects to an Arc Centre defined by 3 points on an Imaginary Arc.
494 Note:
495 - Reads pg.operation from Operation Mode Selector as 'operation'
496 -- set position of CUrsor (CU)
497 -- set position of Pivot Point (PP)
498 -- MoVe geometry/objects (MV)
499 -- Extrude Vertices (EV)
500 -- add a New vertex (NV)
502 Invalid Options result in self.report Error.
504 Args:
505 context: Blender bpy.context instance.
507 Returns:
508 Status Set.
511 pg = context.scene.pdt_pg
512 operation = pg.operation
513 if operation == "CU":
514 pg.command = f"ccen"
515 elif operation == "PP":
516 pg.command = f"pcen"
517 elif operation == "MV":
518 pg.command = f"gcen"
519 elif operation == "EV":
520 pg.command = f"vcen"
521 elif operation == "NV":
522 pg.command = f"ncen"
523 else:
524 error_message = f"{operation} {PDT_ERR_NON_VALID} {PDT_LAB_INTERSECT}"
525 self.report({"ERROR"}, error_message)
526 return {"FINISHED"}
529 class PDT_OT_PlacementInt(Operator):
530 """Use Intersection, or Convergence Placement"""
532 bl_idname = "pdt.intersect"
533 bl_label = "Intersect Mode"
534 bl_options = {"REGISTER", "UNDO"}
536 def execute(self, context):
537 """Manipulates Geometry, or Objects by Convergance Intersection between 4 points, or 2 Edges.
539 Note:
540 - Reads pg.operation from Operation Mode Selector as 'operation'
541 - Reads pg.plane scene variable and operates in Working Plane to:
542 -- set position of CUrsor (CU)
543 -- set position of Pivot Point (PP)
544 -- MoVe geometry/objects (MV)
545 -- Extrude Vertices (EV)
546 -- add a New vertex (NV)
548 Invalid Options result in "self.report" Error.
550 Args:
551 context: Blender bpy.context instance.
553 Returns:
554 Status Set.
557 pg = context.scene.pdt_pg
558 operation = pg.operation
559 if operation == "CU":
560 pg.command = f"cint"
561 elif operation == "PP":
562 pg.command = f"pint"
563 elif operation == "MV":
564 pg.command = f"gint"
565 elif operation == "EV":
566 pg.command = f"vint"
567 elif operation == "NV":
568 pg.command = f"nint"
569 else:
570 error_message = f"{operation} {PDT_ERR_NON_VALID} {PDT_LAB_INTERSECT}"
571 self.report({"ERROR"}, error_message)
572 return {"FINISHED"}
575 class PDT_OT_JoinVerts(Operator):
576 """Join 2 Free Vertices into an Edge"""
578 bl_idname = "pdt.join"
579 bl_label = "Join 2 Vertices"
580 bl_options = {"REGISTER", "UNDO"}
582 @classmethod
583 def poll(cls, context):
584 ob = context.object
585 if ob is None:
586 return False
587 return all([bool(ob), ob.type == "MESH", ob.mode == "EDIT"])
589 def execute(self, context):
590 """Joins 2 Free Vertices that do not form part of a Face.
592 Note:
593 Joins two vertices that do not form part of a single face
594 It is designed to close open Edge Loops, where a face is not required
595 or to join two disconnected Edges.
597 Args:
598 context: Blender bpy.context instance.
600 Returns:
601 Status Set.
604 pg = context.scene.pdt_pg
605 pg.command = f"j2v"
606 return {"FINISHED"}
609 class PDT_OT_Fillet(Operator):
610 """Fillet Edges by Vertex, Set Use Verts to False for Extruded Structure"""
612 bl_idname = "pdt.fillet"
613 bl_label = "Fillet"
614 bl_options = {"REGISTER", "UNDO"}
616 @classmethod
617 def poll(cls, context):
618 ob = context.object
619 if ob is None:
620 return False
621 return all([bool(ob), ob.type == "MESH", ob.mode == "EDIT"])
623 def execute(self, context):
624 """Create Fillets by Vertex or by Geometry.
626 Note:
627 Fillets connected edges, or connected faces
628 Uses:
629 - pg.fillet_radius ; Radius of fillet
630 - pg.fillet_segments ; Number of segments
631 - pg.fillet_profile ; Profile, values 0 to 1
632 - pg.fillet_vertices_only ; Vertices (True), or Face/Edges
633 - pg.fillet_intersect ; Intersect dges first (True), or not
635 Args:
636 context: Blender bpy.context instance.
638 Returns:
639 Status Set.
642 pg = context.scene.pdt_pg
643 decimal_places = context.preferences.addons[__package__].preferences.pdt_input_round
644 if pg.fillet_intersect:
645 pg.command = (
646 f"fi{str(round(pg.fillet_radius, decimal_places))}"
647 f",{str(round(pg.fillet_segments, decimal_places))}"
648 f",{str(round(pg.fillet_profile, decimal_places))}"
650 elif pg.fillet_vertices_only:
651 pg.command = (
652 f"fv{str(round(pg.fillet_radius, decimal_places))}"
653 f",{str(round(pg.fillet_segments, decimal_places))}"
654 f",{str(round(pg.fillet_profile, decimal_places))}"
656 else:
657 pg.command = (
658 f"fe{str(round(pg.fillet_radius, decimal_places))}"
659 f",{str(round(pg.fillet_segments, decimal_places))}"
660 f",{str(round(pg.fillet_profile, decimal_places))}"
662 return {"FINISHED"}
665 class PDT_OT_Angle2(Operator):
666 """Measure Distance and Angle in Working Plane, Also sets Deltas"""
668 bl_idname = "pdt.angle2"
669 bl_label = "Measure 2D"
670 bl_options = {"REGISTER", "UNDO"}
672 def execute(self, context):
673 """Measures Angle and Offsets between 2 Points in View Plane.
675 Note:
676 Uses 2 Selected Vertices to set pg.angle and pg.distance scene variables
677 also sets delta offset from these 2 points using standard Numpy Routines
678 Works in Edit and Oject Modes.
680 Args:
681 context: Blender bpy.context instance.
683 Returns:
684 Status Set.
687 pg = context.scene.pdt_pg
688 pg.command = f"ad2"
689 return {"FINISHED"}
692 class PDT_OT_Angle3(Operator):
693 """Measure Distance and Angle in 3D Space"""
695 bl_idname = "pdt.angle3"
696 bl_label = "Measure 3D"
697 bl_options = {"REGISTER", "UNDO"}
699 def execute(self, context):
700 """Measures Angle and Offsets between 3 Points in World Space, Also sets Deltas.
702 Note:
703 Uses 3 Selected Vertices to set pg.angle and pg.distance scene variables
704 also sets delta offset from these 3 points using standard Numpy Routines
705 Works in Edit and Oject Modes.
707 Args:
708 context: Blender bpy.context instance.
710 Returns:
711 Status Set.
714 pg = context.scene.pdt_pg
715 pg.command = f"ad3"
716 return {"FINISHED"}
719 class PDT_OT_Origin(Operator):
720 """Move Object Origin to Cursor Location"""
722 bl_idname = "pdt.origin"
723 bl_label = "Move Origin"
724 bl_options = {"REGISTER", "UNDO"}
726 def execute(self, context):
727 """Sets Object Origin in Edit Mode to Cursor Location.
729 Note:
730 Keeps geometry static in World Space whilst moving Object Origin
731 Requires cursor location
732 Works in Edit and Object Modes.
734 Args:
735 context: Blender bpy.context instance.
737 Returns:
738 Status Set.
741 pg = context.scene.pdt_pg
742 pg.command = f"otc"
743 return {"FINISHED"}
746 class PDT_OT_Taper(Operator):
747 """Taper Vertices at Angle in Chosen Axis Mode"""
749 bl_idname = "pdt.taper"
750 bl_label = "Taper"
751 bl_options = {"REGISTER", "UNDO"}
753 @classmethod
754 def poll(cls, context):
755 ob = context.object
756 if ob is None:
757 return False
758 return all([bool(ob), ob.type == "MESH", ob.mode == "EDIT"])
760 def execute(self, context):
761 """Taper Geometry along World Axes.
763 Note:
764 Similar to Blender Shear command except that it shears by angle rather than displacement.
765 Rotates about World Axes and displaces along World Axes, angle must not exceed +-80 degrees.
766 Rotation axis is centred on Active Vertex.
767 Works only in Edit mode.
769 Args:
770 context: Blender bpy.context instance.
772 Note:
773 Uses pg.taper & pg.angle scene variables
775 Returns:
776 Status Set.
779 pg = context.scene.pdt_pg
780 pg.command = f"tap"
781 return {"FINISHED"}
783 #class PDT_Extrude_Modal(Operator):
784 # """Extrude Modal Plane Along Normal Axis"""
785 # bl_idname = "pdt.extrude_modal"
786 # bl_label = "Extrude Modal Normal"
787 # bl_options = {"REGISTER", "UNDO"}