1 # ##### BEGIN GPL LICENSE BLOCK #####
3 # This program is free software; you can redistribute it and / or
4 # modify it under the terms of the GNU General Public License
5 # as published by the Free Software Foundation; either version 2
6 # of the License, or (at your option) any later version.
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
13 # You should have received a copy of the GNU General Public License
14 # along with this program; if not, write to the Free Software Foundation,
15 # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301, USA.
17 # ##### END GPL LICENSE BLOCK #####
20 "name": "Simple Curve",
21 "author": "Vladimir Spivak (cwolf3d)",
23 "blender": (2, 80, 0),
24 "location": "View3D > Add > Curve",
25 "description": "Adds Simple Curve",
27 "doc_url": "https://wiki.blender.org/index.php/Extensions:2.6/"
28 "Py/Scripts/Curve/Simple_curves",
29 "category": "Add Curve",
33 # ------------------------------------------------------------
36 from bpy_extras
import object_utils
37 from bpy
.types
import (
43 from bpy
.props
import (
52 from mathutils
import (
62 # from bpy_extras.object_utils import *
65 # ------------------------------------------------------------
71 newpoints
.append([0.0, 0.0, 0.0])
76 # ------------------------------------------------------------
79 def SimpleLine(c1
=[0.0, 0.0, 0.0], c2
=[2.0, 2.0, 2.0]):
82 c3
= Vector(c2
) - Vector(c1
)
83 newpoints
.append([0.0, 0.0, 0.0])
84 newpoints
.append([c3
[0], c3
[1], c3
[2]])
89 # ------------------------------------------------------------
92 def SimpleAngle(length
=1.0, angle
=45.0):
95 angle
= radians(angle
)
96 newpoints
.append([length
, 0.0, 0.0])
97 newpoints
.append([0.0, 0.0, 0.0])
98 newpoints
.append([length
* cos(angle
), length
* sin(angle
), 0.0])
103 # ------------------------------------------------------------
106 def SimpleDistance(length
=1.0, center
=True):
110 newpoints
.append([-length
/ 2, 0.0, 0.0])
111 newpoints
.append([length
/ 2, 0.0, 0.0])
113 newpoints
.append([0.0, 0.0, 0.0])
114 newpoints
.append([length
, 0.0, 0.0])
119 # ------------------------------------------------------------
122 def SimpleCircle(sides
=4, radius
=1.0):
125 angle
= radians(360) / sides
126 newpoints
.append([radius
, 0, 0])
133 newpoints
.append([x
, y
, 0])
139 # ------------------------------------------------------------
142 def SimpleEllipse(a
=2.0, b
=1.0):
145 newpoints
.append([a
, 0.0, 0.0])
146 newpoints
.append([0.0, b
, 0.0])
147 newpoints
.append([-a
, 0.0, 0.0])
148 newpoints
.append([0.0, -b
, 0.0])
153 # ------------------------------------------------------------
156 def SimpleArc(sides
=0, radius
=1.0, startangle
=0.0, endangle
=45.0):
159 startangle
= radians(startangle
)
160 endangle
= radians(endangle
)
163 angle
= (endangle
- startangle
) / sides
164 x
= cos(startangle
) * radius
165 y
= sin(startangle
) * radius
166 newpoints
.append([x
, y
, 0])
170 x
= cos(t
+ startangle
) * radius
171 y
= sin(t
+ startangle
) * radius
172 newpoints
.append([x
, y
, 0])
174 x
= cos(endangle
) * radius
175 y
= sin(endangle
) * radius
176 newpoints
.append([x
, y
, 0])
181 # ------------------------------------------------------------
184 def SimpleSector(sides
=0, radius
=1.0, startangle
=0.0, endangle
=45.0):
187 startangle
= radians(startangle
)
188 endangle
= radians(endangle
)
191 newpoints
.append([0, 0, 0])
192 angle
= (endangle
- startangle
) / sides
193 x
= cos(startangle
) * radius
194 y
= sin(startangle
) * radius
195 newpoints
.append([x
, y
, 0])
199 x
= cos(t
+ startangle
) * radius
200 y
= sin(t
+ startangle
) * radius
201 newpoints
.append([x
, y
, 0])
203 x
= cos(endangle
) * radius
204 y
= sin(endangle
) * radius
205 newpoints
.append([x
, y
, 0])
210 # ------------------------------------------------------------
213 def SimpleSegment(sides
=0, a
=2.0, b
=1.0, startangle
=0.0, endangle
=45.0):
216 startangle
= radians(startangle
)
217 endangle
= radians(endangle
)
220 angle
= (endangle
- startangle
) / sides
221 x
= cos(startangle
) * a
222 y
= sin(startangle
) * a
223 newpoints
.append([x
, y
, 0])
227 x
= cos(t
+ startangle
) * a
228 y
= sin(t
+ startangle
) * a
229 newpoints
.append([x
, y
, 0])
231 x
= cos(endangle
) * a
232 y
= sin(endangle
) * a
233 newpoints
.append([x
, y
, 0])
235 x
= cos(endangle
) * b
236 y
= sin(endangle
) * b
237 newpoints
.append([x
, y
, 0])
241 x
= cos(t
+ startangle
) * b
242 y
= sin(t
+ startangle
) * b
243 newpoints
.append([x
, y
, 0])
245 x
= cos(startangle
) * b
246 y
= sin(startangle
) * b
247 newpoints
.append([x
, y
, 0])
252 # ------------------------------------------------------------
255 def SimpleRectangle(width
=2.0, length
=2.0, rounded
=0.0, center
=True):
264 newpoints
.append([-x
+ r
, y
, 0.0])
265 newpoints
.append([x
- r
, y
, 0.0])
266 newpoints
.append([x
, y
- r
, 0.0])
267 newpoints
.append([x
, -y
+ r
, 0.0])
268 newpoints
.append([x
- r
, -y
, 0.0])
269 newpoints
.append([-x
+ r
, -y
, 0.0])
270 newpoints
.append([-x
, -y
+ r
, 0.0])
271 newpoints
.append([-x
, y
- r
, 0.0])
273 newpoints
.append([-x
, y
, 0.0])
274 newpoints
.append([x
, y
, 0.0])
275 newpoints
.append([x
, -y
, 0.0])
276 newpoints
.append([-x
, -y
, 0.0])
282 newpoints
.append([r
, y
, 0.0])
283 newpoints
.append([x
- r
, y
, 0.0])
284 newpoints
.append([x
, y
- r
, 0.0])
285 newpoints
.append([x
, r
, 0.0])
286 newpoints
.append([x
- r
, 0.0, 0.0])
287 newpoints
.append([r
, 0.0, 0.0])
288 newpoints
.append([0.0, r
, 0.0])
289 newpoints
.append([0.0, y
- r
, 0.0])
291 newpoints
.append([0.0, 0.0, 0.0])
292 newpoints
.append([0.0, y
, 0.0])
293 newpoints
.append([x
, y
, 0.0])
294 newpoints
.append([x
, 0.0, 0.0])
299 # ------------------------------------------------------------
302 def SimpleRhomb(width
=2.0, length
=2.0, center
=True):
308 newpoints
.append([-x
, 0.0, 0.0])
309 newpoints
.append([0.0, y
, 0.0])
310 newpoints
.append([x
, 0.0, 0.0])
311 newpoints
.append([0.0, -y
, 0.0])
313 newpoints
.append([x
, 0.0, 0.0])
314 newpoints
.append([0.0, y
, 0.0])
315 newpoints
.append([x
, length
, 0.0])
316 newpoints
.append([width
, y
, 0.0])
321 # ------------------------------------------------------------
324 def SimplePolygon(sides
=3, radius
=1.0):
326 angle
= radians(360.0) / sides
333 newpoints
.append([x
, y
, 0.0])
339 # ------------------------------------------------------------
342 def SimplePolygon_ab(sides
=3, a
=2.0, b
=1.0):
344 angle
= radians(360.0) / sides
351 newpoints
.append([x
, y
, 0.0])
357 # ------------------------------------------------------------
360 def SimpleTrapezoid(a
=2.0, b
=1.0, h
=1.0, center
=True):
367 newpoints
.append([-x
, -r
, 0.0])
368 newpoints
.append([-y
, r
, 0.0])
369 newpoints
.append([y
, r
, 0.0])
370 newpoints
.append([x
, -r
, 0.0])
373 newpoints
.append([0.0, 0.0, 0.0])
374 newpoints
.append([x
- y
, h
, 0.0])
375 newpoints
.append([x
+ y
, h
, 0.0])
376 newpoints
.append([a
, 0.0, 0.0])
381 # ------------------------------------------------------------
382 # get array of vertcoordinates according to splinetype
383 def vertsToPoints(Verts
, splineType
):
388 # array for BEZIER spline output (V3)
389 if splineType
== 'BEZIER':
393 # array for nonBEZIER output (V4)
397 if splineType
== 'NURBS':
406 # ------------------------------------------------------------
409 def main(context
, self
, use_enter_edit_mode
):
410 # output splineType 'POLY' 'NURBS' 'BEZIER'
411 splineType
= self
.outputType
413 sides
= abs(int((self
.Simple_endangle
- self
.Simple_startangle
) / 90))
416 if self
.Simple_Type
== 'Point':
417 verts
= SimplePoint()
419 if self
.Simple_Type
== 'Line':
420 verts
= SimpleLine(self
.location
, self
.Simple_endlocation
)
422 if self
.Simple_Type
== 'Distance':
423 verts
= SimpleDistance(self
.Simple_length
, self
.Simple_center
)
425 if self
.Simple_Type
== 'Angle':
426 verts
= SimpleAngle(self
.Simple_length
, self
.Simple_angle
)
428 if self
.Simple_Type
== 'Circle':
429 if self
.Simple_sides
< 4:
430 self
.Simple_sides
= 4
431 if self
.Simple_radius
== 0:
433 verts
= SimpleCircle(self
.Simple_sides
, self
.Simple_radius
)
435 if self
.Simple_Type
== 'Ellipse':
436 verts
= SimpleEllipse(self
.Simple_a
, self
.Simple_b
)
438 if self
.Simple_Type
== 'Arc':
439 if self
.Simple_sides
< sides
:
440 self
.Simple_sides
= sides
441 if self
.Simple_radius
== 0:
444 self
.Simple_sides
, self
.Simple_radius
,
445 self
.Simple_startangle
, self
.Simple_endangle
448 if self
.Simple_Type
== 'Sector':
449 if self
.Simple_sides
< sides
:
450 self
.Simple_sides
= sides
451 if self
.Simple_radius
== 0:
453 verts
= SimpleSector(
454 self
.Simple_sides
, self
.Simple_radius
,
455 self
.Simple_startangle
, self
.Simple_endangle
458 if self
.Simple_Type
== 'Segment':
459 if self
.Simple_sides
< sides
:
460 self
.Simple_sides
= sides
461 if self
.Simple_a
== 0 or self
.Simple_b
== 0 or self
.Simple_a
== self
.Simple_b
:
463 if self
.Simple_a
> self
.Simple_b
:
464 verts
= SimpleSegment(
465 self
.Simple_sides
, self
.Simple_a
, self
.Simple_b
,
466 self
.Simple_startangle
, self
.Simple_endangle
468 if self
.Simple_a
< self
.Simple_b
:
469 verts
= SimpleSegment(
470 self
.Simple_sides
, self
.Simple_b
, self
.Simple_a
,
471 self
.Simple_startangle
, self
.Simple_endangle
474 if self
.Simple_Type
== 'Rectangle':
475 verts
= SimpleRectangle(
476 self
.Simple_width
, self
.Simple_length
,
477 self
.Simple_rounded
, self
.Simple_center
480 if self
.Simple_Type
== 'Rhomb':
482 self
.Simple_width
, self
.Simple_length
, self
.Simple_center
485 if self
.Simple_Type
== 'Polygon':
486 if self
.Simple_sides
< 3:
487 self
.Simple_sides
= 3
488 verts
= SimplePolygon(
489 self
.Simple_sides
, self
.Simple_radius
492 if self
.Simple_Type
== 'Polygon_ab':
493 if self
.Simple_sides
< 3:
494 self
.Simple_sides
= 3
495 verts
= SimplePolygon_ab(
496 self
.Simple_sides
, self
.Simple_a
, self
.Simple_b
499 if self
.Simple_Type
== 'Trapezoid':
500 verts
= SimpleTrapezoid(
501 self
.Simple_a
, self
.Simple_b
, self
.Simple_h
, self
.Simple_center
504 # turn verts into array
505 vertArray
= vertsToPoints(verts
, splineType
)
508 if bpy
.context
.mode
== 'EDIT_CURVE':
510 Curve
= context
.active_object
511 newSpline
= Curve
.data
.splines
.new(type=splineType
) # spline
513 name
= self
.Simple_Type
# Type as name
515 dataCurve
= bpy
.data
.curves
.new(name
, type='CURVE') # curve data block
516 newSpline
= dataCurve
.splines
.new(type=splineType
) # spline
518 # create object with new Curve
519 Curve
= object_utils
.object_data_add(context
, dataCurve
, operator
=self
) # place in active scene
520 Curve
.select_set(True)
522 for spline
in Curve
.data
.splines
:
523 if spline
.type == 'BEZIER':
524 for point
in spline
.bezier_points
:
525 point
.select_control_point
= False
526 point
.select_left_handle
= False
527 point
.select_right_handle
= False
529 for point
in spline
.points
:
532 # create spline from vertarray
534 if splineType
== 'BEZIER':
535 newSpline
.bezier_points
.add(int(len(vertArray
) * 0.33))
536 newSpline
.bezier_points
.foreach_set('co', vertArray
)
537 for point
in newSpline
.bezier_points
:
538 point
.handle_right_type
= self
.handleType
539 point
.handle_left_type
= self
.handleType
540 point
.select_control_point
= True
541 point
.select_left_handle
= True
542 point
.select_right_handle
= True
543 all_points
.append(point
)
545 newSpline
.points
.add(int(len(vertArray
) * 0.25 - 1))
546 newSpline
.points
.foreach_set('co', vertArray
)
547 newSpline
.use_endpoint_u
= True
548 for point
in newSpline
.points
:
549 all_points
.append(point
)
556 if splineType
== 'BEZIER':
557 if self
.Simple_Type
== 'Circle' or self
.Simple_Type
== 'Arc' or \
558 self
.Simple_Type
== 'Sector' or self
.Simple_Type
== 'Segment' or \
559 self
.Simple_Type
== 'Ellipse':
562 p
.handle_right_type
= 'FREE'
563 p
.handle_left_type
= 'FREE'
565 if self
.Simple_Type
== 'Circle':
567 for p1
in all_points
:
569 p2
= all_points
[i
+ 1]
570 u1
= asin(p1
.co
.y
/ self
.Simple_radius
)
571 u2
= asin(p2
.co
.y
/ self
.Simple_radius
)
572 if p1
.co
.x
> 0 and p2
.co
.x
< 0:
573 u1
= acos(p1
.co
.x
/ self
.Simple_radius
)
574 u2
= acos(p2
.co
.x
/ self
.Simple_radius
)
575 elif p1
.co
.x
< 0 and p2
.co
.x
> 0:
576 u1
= acos(p1
.co
.x
/ self
.Simple_radius
)
577 u2
= acos(p2
.co
.x
/ self
.Simple_radius
)
581 l
= 4 / 3 * tan(1 / 4 * u
) * self
.Simple_radius
582 v1
= Vector((-p1
.co
.y
, p1
.co
.x
, 0))
584 v2
= Vector((-p2
.co
.y
, p2
.co
.x
, 0))
588 v1
= Vector((p1
.co
.x
, p1
.co
.y
, 0)) + vh1
589 v2
= Vector((p2
.co
.x
, p2
.co
.y
, 0)) - vh2
594 u1
= asin(p1
.co
.y
/ self
.Simple_radius
)
595 u2
= asin(p2
.co
.y
/ self
.Simple_radius
)
596 if p1
.co
.x
> 0 and p2
.co
.x
< 0:
597 u1
= acos(p1
.co
.x
/ self
.Simple_radius
)
598 u2
= acos(p2
.co
.x
/ self
.Simple_radius
)
599 elif p1
.co
.x
< 0 and p2
.co
.x
> 0:
600 u1
= acos(p1
.co
.x
/ self
.Simple_radius
)
601 u2
= acos(p2
.co
.x
/ self
.Simple_radius
)
605 l
= 4 / 3 * tan(1 / 4 * u
) * self
.Simple_radius
606 v1
= Vector((-p1
.co
.y
, p1
.co
.x
, 0))
608 v2
= Vector((-p2
.co
.y
, p2
.co
.x
, 0))
612 v1
= Vector((p1
.co
.x
, p1
.co
.y
, 0)) + vh1
613 v2
= Vector((p2
.co
.x
, p2
.co
.y
, 0)) - vh2
618 if self
.Simple_Type
== 'Ellipse':
619 all_points
[0].handle_right
= Vector((self
.Simple_a
, self
.Simple_b
* d
, 0))
620 all_points
[0].handle_left
= Vector((self
.Simple_a
, -self
.Simple_b
* d
, 0))
621 all_points
[1].handle_right
= Vector((-self
.Simple_a
* d
, self
.Simple_b
, 0))
622 all_points
[1].handle_left
= Vector((self
.Simple_a
* d
, self
.Simple_b
, 0))
623 all_points
[2].handle_right
= Vector((-self
.Simple_a
, -self
.Simple_b
* d
, 0))
624 all_points
[2].handle_left
= Vector((-self
.Simple_a
, self
.Simple_b
* d
, 0))
625 all_points
[3].handle_right
= Vector((self
.Simple_a
* d
, -self
.Simple_b
, 0))
626 all_points
[3].handle_left
= Vector((-self
.Simple_a
* d
, -self
.Simple_b
, 0))
628 if self
.Simple_Type
== 'Arc':
630 for p1
in all_points
:
632 p2
= all_points
[i
+ 1]
633 u1
= asin(p1
.co
.y
/ self
.Simple_radius
)
634 u2
= asin(p2
.co
.y
/ self
.Simple_radius
)
635 if p1
.co
.x
> 0 and p2
.co
.x
< 0:
636 u1
= acos(p1
.co
.x
/ self
.Simple_radius
)
637 u2
= acos(p2
.co
.x
/ self
.Simple_radius
)
638 elif p1
.co
.x
< 0 and p2
.co
.x
> 0:
639 u1
= acos(p1
.co
.x
/ self
.Simple_radius
)
640 u2
= acos(p2
.co
.x
/ self
.Simple_radius
)
644 l
= 4 / 3 * tan(1 / 4 * u
) * self
.Simple_radius
645 v1
= Vector((-p1
.co
.y
, p1
.co
.x
, 0))
647 v2
= Vector((-p2
.co
.y
, p2
.co
.x
, 0))
651 if self
.Simple_startangle
< self
.Simple_endangle
:
652 v1
= Vector((p1
.co
.x
, p1
.co
.y
, 0)) + vh1
653 v2
= Vector((p2
.co
.x
, p2
.co
.y
, 0)) - vh2
657 v1
= Vector((p1
.co
.x
, p1
.co
.y
, 0)) - vh1
658 v2
= Vector((p2
.co
.x
, p2
.co
.y
, 0)) + vh2
662 all_points
[0].handle_left_type
= 'VECTOR'
663 all_points
[-1].handle_right_type
= 'VECTOR'
665 if self
.Simple_Type
== 'Sector':
667 for p1
in all_points
:
669 p1
.handle_right_type
= 'VECTOR'
670 p1
.handle_left_type
= 'VECTOR'
672 p2
= all_points
[i
+ 1]
673 u1
= asin(p1
.co
.y
/ self
.Simple_radius
)
674 u2
= asin(p2
.co
.y
/ self
.Simple_radius
)
675 if p1
.co
.x
> 0 and p2
.co
.x
< 0:
676 u1
= acos(p1
.co
.x
/ self
.Simple_radius
)
677 u2
= acos(p2
.co
.x
/ self
.Simple_radius
)
678 elif p1
.co
.x
< 0 and p2
.co
.x
> 0:
679 u1
= acos(p1
.co
.x
/ self
.Simple_radius
)
680 u2
= acos(p2
.co
.x
/ self
.Simple_radius
)
684 l
= 4 / 3 * tan(1 / 4 * u
) * self
.Simple_radius
685 v1
= Vector((-p1
.co
.y
, p1
.co
.x
, 0))
687 v2
= Vector((-p2
.co
.y
, p2
.co
.x
, 0))
691 if self
.Simple_startangle
< self
.Simple_endangle
:
692 v1
= Vector((p1
.co
.x
, p1
.co
.y
, 0)) + vh1
693 v2
= Vector((p2
.co
.x
, p2
.co
.y
, 0)) - vh2
697 v1
= Vector((p1
.co
.x
, p1
.co
.y
, 0)) - vh1
698 v2
= Vector((p2
.co
.x
, p2
.co
.y
, 0)) + vh2
702 all_points
[0].handle_left_type
= 'VECTOR'
703 all_points
[0].handle_right_type
= 'VECTOR'
704 all_points
[1].handle_left_type
= 'VECTOR'
705 all_points
[-1].handle_right_type
= 'VECTOR'
707 if self
.Simple_Type
== 'Segment':
709 if self
.Simple_a
> self
.Simple_b
:
710 Segment_a
= self
.Simple_a
711 Segment_b
= self
.Simple_b
712 if self
.Simple_a
< self
.Simple_b
:
713 Segment_b
= self
.Simple_a
714 Segment_a
= self
.Simple_b
715 for p1
in all_points
:
717 p2
= all_points
[i
+ 1]
718 u1
= asin(p1
.co
.y
/ Segment_a
)
719 u2
= asin(p2
.co
.y
/ Segment_a
)
720 if p1
.co
.x
> 0 and p2
.co
.x
< 0:
721 u1
= acos(p1
.co
.x
/ Segment_a
)
722 u2
= acos(p2
.co
.x
/ Segment_a
)
723 elif p1
.co
.x
< 0 and p2
.co
.x
> 0:
724 u1
= acos(p1
.co
.x
/ Segment_a
)
725 u2
= acos(p2
.co
.x
/ Segment_a
)
729 l
= 4 / 3 * tan(1 / 4 * u
) * Segment_a
730 v1
= Vector((-p1
.co
.y
, p1
.co
.x
, 0))
732 v2
= Vector((-p2
.co
.y
, p2
.co
.x
, 0))
736 if self
.Simple_startangle
< self
.Simple_endangle
:
737 v1
= Vector((p1
.co
.x
, p1
.co
.y
, 0)) + vh1
738 v2
= Vector((p2
.co
.x
, p2
.co
.y
, 0)) - vh2
742 v1
= Vector((p1
.co
.x
, p1
.co
.y
, 0)) - vh1
743 v2
= Vector((p2
.co
.x
, p2
.co
.y
, 0)) + vh2
746 elif i
!= (n
/ 2 - 1) and i
!= (n
- 1):
747 p2
= all_points
[i
+ 1]
748 u1
= asin(p1
.co
.y
/ Segment_b
)
749 u2
= asin(p2
.co
.y
/ Segment_b
)
750 if p1
.co
.x
> 0 and p2
.co
.x
< 0:
751 u1
= acos(p1
.co
.x
/ Segment_b
)
752 u2
= acos(p2
.co
.x
/ Segment_b
)
753 elif p1
.co
.x
< 0 and p2
.co
.x
> 0:
754 u1
= acos(p1
.co
.x
/ Segment_b
)
755 u2
= acos(p2
.co
.x
/ Segment_b
)
759 l
= 4 / 3 * tan(1 / 4 * u
) * Segment_b
760 v1
= Vector((-p1
.co
.y
, p1
.co
.x
, 0))
762 v2
= Vector((-p2
.co
.y
, p2
.co
.x
, 0))
766 if self
.Simple_startangle
< self
.Simple_endangle
:
767 v1
= Vector((p1
.co
.x
, p1
.co
.y
, 0)) - vh1
768 v2
= Vector((p2
.co
.x
, p2
.co
.y
, 0)) + vh2
772 v1
= Vector((p1
.co
.x
, p1
.co
.y
, 0)) + vh1
773 v2
= Vector((p2
.co
.x
, p2
.co
.y
, 0)) - vh2
778 all_points
[0].handle_left_type
= 'VECTOR'
779 all_points
[n
- 1].handle_right_type
= 'VECTOR'
780 all_points
[int(n
/ 2) - 1].handle_right_type
= 'VECTOR'
781 all_points
[int(n
/ 2)].handle_left_type
= 'VECTOR'
783 # set newSpline Options
784 newSpline
.use_cyclic_u
= self
.use_cyclic_u
785 newSpline
.use_endpoint_u
= self
.endp_u
786 newSpline
.order_u
= self
.order_u
789 Curve
.data
.dimensions
= self
.shape
790 Curve
.data
.use_path
= True
791 if self
.shape
== '3D':
792 Curve
.data
.fill_mode
= 'FULL'
794 Curve
.data
.fill_mode
= 'BOTH'
796 # move and rotate spline in edit mode
797 if bpy
.context
.mode
== 'EDIT_CURVE':
798 if self
.align
== "WORLD":
799 location
= self
.location
- context
.active_object
.location
800 bpy
.ops
.transform
.translate(value
= location
, orient_type
='GLOBAL')
801 bpy
.ops
.transform
.rotate(value
= self
.rotation
[0], orient_axis
= 'X', orient_type
='GLOBAL')
802 bpy
.ops
.transform
.rotate(value
= self
.rotation
[1], orient_axis
= 'Y', orient_type
='GLOBAL')
803 bpy
.ops
.transform
.rotate(value
= self
.rotation
[2], orient_axis
= 'Z', orient_type
='GLOBAL')
805 elif self
.align
== "VIEW":
806 bpy
.ops
.transform
.translate(value
= self
.location
)
807 bpy
.ops
.transform
.rotate(value
= self
.rotation
[0], orient_axis
= 'X')
808 bpy
.ops
.transform
.rotate(value
= self
.rotation
[1], orient_axis
= 'Y')
809 bpy
.ops
.transform
.rotate(value
= self
.rotation
[2], orient_axis
= 'Z')
811 elif self
.align
== "CURSOR":
812 location
= context
.active_object
.location
813 self
.location
= bpy
.context
.scene
.cursor
.location
- location
814 self
.rotation
= bpy
.context
.scene
.cursor
.rotation_euler
816 bpy
.ops
.transform
.translate(value
= self
.location
)
817 bpy
.ops
.transform
.rotate(value
= self
.rotation
[0], orient_axis
= 'X')
818 bpy
.ops
.transform
.rotate(value
= self
.rotation
[1], orient_axis
= 'Y')
819 bpy
.ops
.transform
.rotate(value
= self
.rotation
[2], orient_axis
= 'Z')
822 def menu(self
, context
):
823 oper1
= self
.layout
.operator(Simple
.bl_idname
, text
="Angle", icon
="DRIVER_ROTATIONAL_DIFFERENCE")
824 oper1
.Simple_Type
= "Angle"
825 oper1
.use_cyclic_u
= False
827 oper2
= self
.layout
.operator(Simple
.bl_idname
, text
="Arc", icon
="MOD_THICKNESS")
828 oper2
.Simple_Type
= "Arc"
829 oper2
.use_cyclic_u
= False
831 oper3
= self
.layout
.operator(Simple
.bl_idname
, text
="Circle", icon
="ANTIALIASED")
832 oper3
.Simple_Type
= "Circle"
833 oper3
.use_cyclic_u
= True
835 oper4
= self
.layout
.operator(Simple
.bl_idname
, text
="Distance", icon
="DRIVER_DISTANCE")
836 oper4
.Simple_Type
= "Distance"
837 oper4
.use_cyclic_u
= False
839 oper5
= self
.layout
.operator(Simple
.bl_idname
, text
="Ellipse", icon
="MESH_TORUS")
840 oper5
.Simple_Type
= "Ellipse"
841 oper5
.use_cyclic_u
= True
843 oper6
= self
.layout
.operator(Simple
.bl_idname
, text
="Line", icon
="MOD_SIMPLIFY")
844 oper6
.Simple_Type
= "Line"
845 oper6
.use_cyclic_u
= False
848 oper7
= self
.layout
.operator(Simple
.bl_idname
, text
="Point", icon
="LAYER_ACTIVE")
849 oper7
.Simple_Type
= "Point"
850 oper7
.use_cyclic_u
= False
852 oper8
= self
.layout
.operator(Simple
.bl_idname
, text
="Polygon", icon
="SEQ_CHROMA_SCOPE")
853 oper8
.Simple_Type
= "Polygon"
854 oper8
.use_cyclic_u
= True
856 oper9
= self
.layout
.operator(Simple
.bl_idname
, text
="Polygon ab", icon
="SEQ_CHROMA_SCOPE")
857 oper9
.Simple_Type
= "Polygon_ab"
858 oper9
.use_cyclic_u
= True
860 oper10
= self
.layout
.operator(Simple
.bl_idname
, text
="Rectangle", icon
="MESH_PLANE")
861 oper10
.Simple_Type
= "Rectangle"
862 oper10
.use_cyclic_u
= True
864 oper11
= self
.layout
.operator(Simple
.bl_idname
, text
="Rhomb", icon
="DECORATE_ANIMATE")
865 oper11
.Simple_Type
= "Rhomb"
866 oper11
.use_cyclic_u
= True
868 oper12
= self
.layout
.operator(Simple
.bl_idname
, text
="Sector", icon
="CON_SHRINKWRAP")
869 oper12
.Simple_Type
= "Sector"
870 oper12
.use_cyclic_u
= True
872 oper13
= self
.layout
.operator(Simple
.bl_idname
, text
="Segment", icon
="MOD_SIMPLEDEFORM")
873 oper13
.Simple_Type
= "Segment"
874 oper13
.use_cyclic_u
= True
876 oper14
= self
.layout
.operator(Simple
.bl_idname
, text
="Trapezoid", icon
="MOD_EDGESPLIT")
877 oper14
.Simple_Type
= "Trapezoid"
878 oper14
.use_cyclic_u
= True
880 # ------------------------------------------------------------
883 class Simple(Operator
, object_utils
.AddObjectHelper
):
884 bl_idname
= "curve.simple"
885 bl_label
= "Simple Curve"
886 bl_description
= "Construct a Simple Curve"
887 bl_options
= {'REGISTER', 'UNDO', 'PRESET'}
890 Simple
: BoolProperty(
893 description
="Simple Curve"
895 Simple_Change
: BoolProperty(
898 description
="Change Simple Curve"
900 Simple_Delete
: StringProperty(
902 description
="Delete Simple Curve"
905 Types
= [('Point', "Point", "Construct a Point"),
906 ('Line', "Line", "Construct a Line"),
907 ('Distance', "Distance", "Construct a two point Distance"),
908 ('Angle', "Angle", "Construct an Angle"),
909 ('Circle', "Circle", "Construct a Circle"),
910 ('Ellipse', "Ellipse", "Construct an Ellipse"),
911 ('Arc', "Arc", "Construct an Arc"),
912 ('Sector', "Sector", "Construct a Sector"),
913 ('Segment', "Segment", "Construct a Segment"),
914 ('Rectangle', "Rectangle", "Construct a Rectangle"),
915 ('Rhomb', "Rhomb", "Construct a Rhomb"),
916 ('Polygon', "Polygon", "Construct a Polygon"),
917 ('Polygon_ab', "Polygon ab", "Construct a Polygon ab"),
918 ('Trapezoid', "Trapezoid", "Construct a Trapezoid")
920 Simple_Type
: EnumProperty(
922 description
="Form of Curve to create",
926 Simple_endlocation
: FloatVectorProperty(
928 description
="End location",
929 default
=(2.0, 2.0, 2.0),
930 subtype
='TRANSLATION'
932 # Trapezoid properties
933 Simple_a
: FloatProperty(
936 min=0.0, soft_min
=0.0,
938 description
="a side Value"
940 Simple_b
: FloatProperty(
943 min=0.0, soft_min
=0.0,
945 description
="b side Value"
947 Simple_h
: FloatProperty(
951 description
="Height of the Trapezoid - distance between a and b"
953 Simple_angle
: FloatProperty(
958 Simple_startangle
: FloatProperty(
961 min=-360.0, soft_min
=-360.0,
962 max=360.0, soft_max
=360.0,
963 description
="Start angle"
965 Simple_endangle
: FloatProperty(
968 min=-360.0, soft_min
=-360.0,
969 max=360.0, soft_max
=360.0,
970 description
="End angle"
972 Simple_sides
: IntProperty(
978 Simple_radius
: FloatProperty(
981 min=0.0, soft_min
=0.0,
985 Simple_center
: BoolProperty(
986 name
="Length center",
988 description
="Length center"
991 Angle_types
= [('Degrees', "Degrees", "Use Degrees"),
992 ('Radians', "Radians", "Use Radians")]
993 Simple_degrees_or_radians
: EnumProperty(
994 name
="Degrees or radians",
995 description
="Degrees or radians",
998 # Rectangle properties
999 Simple_width
: FloatProperty(
1002 min=0.0, soft_min
=0,
1006 Simple_length
: FloatProperty(
1009 min=0.0, soft_min
=0.0,
1011 description
="Length"
1013 Simple_rounded
: FloatProperty(
1016 min=0.0, soft_min
=0.0,
1018 description
="Rounded corners"
1022 ('2D', "2D", "2D shape Curve"),
1023 ('3D', "3D", "3D shape Curve")]
1024 shape
: EnumProperty(
1027 description
="2D or 3D Curve"
1029 outputType
: EnumProperty(
1030 name
="Output splines",
1031 description
="Type of splines to output",
1033 ('POLY', "Poly", "Poly Spline type"),
1034 ('NURBS', "Nurbs", "Nurbs Spline type"),
1035 ('BEZIER', "Bezier", "Bezier Spline type")],
1038 use_cyclic_u
: BoolProperty(
1041 description
="make curve closed"
1043 endp_u
: BoolProperty(
1044 name
="Use endpoint u",
1046 description
="stretch to endpoints"
1048 order_u
: IntProperty(
1053 description
="Order of nurbs spline"
1055 handleType
: EnumProperty(
1058 description
="Bezier handles type",
1060 ('VECTOR', "Vector", "Vector type Bezier handles"),
1061 ('AUTO', "Auto", "Automatic type Bezier handles")]
1063 edit_mode
: BoolProperty(
1064 name
="Show in edit mode",
1066 description
="Show in edit mode"
1069 def draw(self
, context
):
1070 layout
= self
.layout
1073 col
= layout
.column()
1074 col
.prop(self
, "Simple_Type")
1079 if self
.Simple_Type
== 'Line':
1081 col
= box
.column(align
=True)
1082 col
.label(text
=self
.Simple_Type
+ " Options:")
1083 col
.prop(self
, "Simple_endlocation")
1084 v
= Vector(self
.Simple_endlocation
) - Vector(self
.location
)
1087 if self
.Simple_Type
== 'Distance':
1089 col
= box
.column(align
=True)
1090 col
.label(text
=self
.Simple_Type
+ " Options:")
1091 col
.prop(self
, "Simple_length")
1092 col
.prop(self
, "Simple_center")
1093 l
= self
.Simple_length
1095 if self
.Simple_Type
== 'Angle':
1097 col
= box
.column(align
=True)
1098 col
.label(text
=self
.Simple_Type
+ " Options:")
1099 col
.prop(self
, "Simple_length")
1100 col
.prop(self
, "Simple_angle")
1102 if self
.Simple_Type
== 'Circle':
1104 col
= box
.column(align
=True)
1105 col
.label(text
=self
.Simple_Type
+ " Options:")
1106 col
.prop(self
, "Simple_sides")
1107 col
.prop(self
, "Simple_radius")
1109 l
= 2 * pi
* abs(self
.Simple_radius
)
1110 s
= pi
* self
.Simple_radius
* self
.Simple_radius
1112 if self
.Simple_Type
== 'Ellipse':
1114 col
= box
.column(align
=True)
1115 col
.label(text
=self
.Simple_Type
+ " Options:")
1116 col
.prop(self
, "Simple_a", text
="Radius a")
1117 col
.prop(self
, "Simple_b", text
="Radius b")
1119 l
= pi
* (3 * (self
.Simple_a
+ self
.Simple_b
) -
1120 sqrt((3 * self
.Simple_a
+ self
.Simple_b
) *
1121 (self
.Simple_a
+ 3 * self
.Simple_b
)))
1123 s
= pi
* abs(self
.Simple_b
) * abs(self
.Simple_a
)
1125 if self
.Simple_Type
== 'Arc':
1127 col
= box
.column(align
=True)
1128 col
.label(text
=self
.Simple_Type
+ " Options:")
1129 col
.prop(self
, "Simple_sides")
1130 col
.prop(self
, "Simple_radius")
1132 col
= box
.column(align
=True)
1133 col
.prop(self
, "Simple_startangle")
1134 col
.prop(self
, "Simple_endangle")
1136 #row.prop(self, "Simple_degrees_or_radians", expand=True)
1138 l
= abs(pi
* self
.Simple_radius
* (self
.Simple_endangle
- self
.Simple_startangle
) / 180)
1140 if self
.Simple_Type
== 'Sector':
1142 col
= box
.column(align
=True)
1143 col
.label(text
=self
.Simple_Type
+ " Options:")
1144 col
.prop(self
, "Simple_sides")
1145 col
.prop(self
, "Simple_radius")
1147 col
= box
.column(align
=True)
1148 col
.prop(self
, "Simple_startangle")
1149 col
.prop(self
, "Simple_endangle")
1151 #row.prop(self, "Simple_degrees_or_radians", expand=True)
1153 l
= abs(pi
* self
.Simple_radius
*
1154 (self
.Simple_endangle
- self
.Simple_startangle
) / 180) + self
.Simple_radius
* 2
1156 s
= pi
* self
.Simple_radius
* self
.Simple_radius
* \
1157 abs(self
.Simple_endangle
- self
.Simple_startangle
) / 360
1159 if self
.Simple_Type
== 'Segment':
1161 col
= box
.column(align
=True)
1162 col
.label(text
=self
.Simple_Type
+ " Options:")
1163 col
.prop(self
, "Simple_sides")
1164 col
.prop(self
, "Simple_a", text
="Radius a")
1165 col
.prop(self
, "Simple_b", text
="Radius b")
1167 col
= box
.column(align
=True)
1168 col
.prop(self
, "Simple_startangle")
1169 col
.prop(self
, "Simple_endangle")
1172 #row.prop(self, "Simple_degrees_or_radians", expand=True)
1174 la
= abs(pi
* self
.Simple_a
* (self
.Simple_endangle
- self
.Simple_startangle
) / 180)
1175 lb
= abs(pi
* self
.Simple_b
* (self
.Simple_endangle
- self
.Simple_startangle
) / 180)
1176 l
= abs(self
.Simple_a
- self
.Simple_b
) * 2 + la
+ lb
1178 sa
= pi
* self
.Simple_a
* self
.Simple_a
* \
1179 abs(self
.Simple_endangle
- self
.Simple_startangle
) / 360
1181 sb
= pi
* self
.Simple_b
* self
.Simple_b
* \
1182 abs(self
.Simple_endangle
- self
.Simple_startangle
) / 360
1186 if self
.Simple_Type
== 'Rectangle':
1188 col
= box
.column(align
=True)
1189 col
.label(text
=self
.Simple_Type
+ " Options:")
1190 col
.prop(self
, "Simple_width")
1191 col
.prop(self
, "Simple_length")
1192 col
.prop(self
, "Simple_rounded")
1194 box
.prop(self
, "Simple_center")
1195 l
= 2 * abs(self
.Simple_width
) + 2 * abs(self
.Simple_length
)
1196 s
= abs(self
.Simple_width
) * abs(self
.Simple_length
)
1198 if self
.Simple_Type
== 'Rhomb':
1200 col
= box
.column(align
=True)
1201 col
.label(text
=self
.Simple_Type
+ " Options:")
1202 col
.prop(self
, "Simple_width")
1203 col
.prop(self
, "Simple_length")
1204 col
.prop(self
, "Simple_center")
1206 g
= hypot(self
.Simple_width
/ 2, self
.Simple_length
/ 2)
1208 s
= self
.Simple_width
* self
.Simple_length
/ 2
1210 if self
.Simple_Type
== 'Polygon':
1212 col
= box
.column(align
=True)
1213 col
.label(text
=self
.Simple_Type
+ " Options:")
1214 col
.prop(self
, "Simple_sides")
1215 col
.prop(self
, "Simple_radius")
1217 if self
.Simple_Type
== 'Polygon_ab':
1219 col
= box
.column(align
=True)
1220 col
.label(text
="Polygon ab Options:")
1221 col
.prop(self
, "Simple_sides")
1222 col
.prop(self
, "Simple_a")
1223 col
.prop(self
, "Simple_b")
1225 if self
.Simple_Type
== 'Trapezoid':
1227 col
= box
.column(align
=True)
1228 col
.label(text
=self
.Simple_Type
+ " Options:")
1229 col
.prop(self
, "Simple_a")
1230 col
.prop(self
, "Simple_b")
1231 col
.prop(self
, "Simple_h")
1233 box
.prop(self
, "Simple_center")
1234 g
= hypot(self
.Simple_h
, (self
.Simple_a
- self
.Simple_b
) / 2)
1235 l
= self
.Simple_a
+ self
.Simple_b
+ g
* 2
1236 s
= (abs(self
.Simple_a
) + abs(self
.Simple_b
)) / 2 * self
.Simple_h
1239 row
.prop(self
, "shape", expand
=True)
1242 col
= layout
.column()
1243 col
.label(text
="Output Curve Type:")
1244 col
.row().prop(self
, "outputType", expand
=True)
1246 if self
.outputType
== 'NURBS':
1247 col
.prop(self
, "order_u")
1248 elif self
.outputType
== 'BEZIER':
1249 col
.row().prop(self
, 'handleType', expand
=True)
1251 col
= layout
.column()
1252 col
.row().prop(self
, "use_cyclic_u", expand
=True)
1254 col
= layout
.column()
1255 col
.row().prop(self
, "edit_mode", expand
=True)
1257 col
= layout
.column()
1258 # AddObjectHelper props
1259 col
.prop(self
, "align")
1260 col
.prop(self
, "location")
1261 col
.prop(self
, "rotation")
1263 if l
!= 0 or s
!= 0:
1265 box
.label(text
="Statistics:", icon
="INFO")
1267 l_str
= str(round(l
, 4))
1268 box
.label(text
="Length: " + l_str
)
1270 s_str
= str(round(s
, 4))
1271 box
.label(text
="Area: " + s_str
)
1274 def poll(cls
, context
):
1275 return context
.scene
is not None
1277 def execute(self
, context
):
1279 # turn off 'Enter Edit Mode'
1280 use_enter_edit_mode
= bpy
.context
.preferences
.edit
.use_enter_edit_mode
1281 bpy
.context
.preferences
.edit
.use_enter_edit_mode
= False
1284 main(context
, self
, use_enter_edit_mode
)
1286 if use_enter_edit_mode
:
1287 bpy
.ops
.object.mode_set(mode
= 'EDIT')
1289 # restore pre operator state
1290 bpy
.context
.preferences
.edit
.use_enter_edit_mode
= use_enter_edit_mode
1293 bpy
.ops
.object.mode_set(mode
= 'EDIT')
1295 bpy
.ops
.object.mode_set(mode
= 'OBJECT')
1299 def invoke(self
, context
, event
):
1301 self
.execute(context
)
1311 from bpy
.utils
import register_class
1315 bpy
.types
.VIEW3D_MT_curve_add
.append(menu
)
1318 from bpy
.utils
import unregister_class
1319 for cls
in reversed(classes
):
1320 unregister_class(cls
)
1322 bpy
.types
.VIEW3D_MT_curve_add
.remove(menu
)
1324 if __name__
== "__main__":