1 # SPDX-License-Identifier: GPL-2.0-or-later
5 "name": "Curveaceous Galore!",
6 "author": "Jimmy Hazevoet, testscreenings",
9 "location": "View3D > Add > Curve",
10 "description": "Adds many different types of Curves",
12 "doc_url": "{BLENDER_MANUAL_URL}/addons/add_curve/extra_objects.html",
13 "category": "Add Curve",
18 from bpy_extras
import object_utils
19 from bpy
.props
import (
26 from mathutils
import Matrix
, Vector
27 from bpy
.types
import Operator
31 import mathutils
.noise
as Noise
34 # ------------------------------------------------------------
35 # Some functions to use with others:
36 # ------------------------------------------------------------
38 # ------------------------------------------------------------
39 # Generate random number:
40 def randnum(low
=0.0, high
=1.0, seed
=0):
42 randnum( low=0.0, high=1.0, seed=0 )
50 seed - the random seed number, if seed == 0, the current time will be used instead
59 rnum
= rnum
* (high
- low
)
64 # ------------------------------------------------------------
66 def vTurbNoise(x
, y
, z
, iScale
=0.25, Size
=1.0, Depth
=6, Hard
=False, Basis
=0, Seed
=0):
68 vTurbNoise((x,y,z), iScale=0.25, Size=1.0, Depth=6, Hard=0, Basis=0, Seed=0 )
70 Create randomised vTurbulence noise
73 xyz - (x,y,z) float values.
75 iScale - noise intensity scale
79 Depth - number of noise values added.
81 Hard - noise hardness: True - soft noise; False - hard noise
83 basis - type of noise used for turbulence
85 Seed - the random seed number, if seed == 0, the current time will be used instead
88 the generated turbulence vector.
91 rand
= randnum(-100, 100, Seed
)
94 vec
= Vector((x
/ Size
+ rand
, y
/ Size
+ rand
, z
/ Size
+ rand
))
95 vTurb
= Noise
.turbulence_vector(vec
, Depth
, Hard
)
96 #mathutils.noise.turbulence_vector(position, octaves, hard, noise_basis='PERLIN_ORIGINAL', amplitude_scale=0.5, frequency_scale=2.0)
97 tx
= vTurb
[0] * iScale
98 ty
= vTurb
[1] * iScale
99 tz
= vTurb
[2] * iScale
103 # -------------------------------------------------------------------
104 # 2D Curve shape functions:
105 # -------------------------------------------------------------------
107 # ------------------------------------------------------------
108 # 2DCurve: Profile: L, H, T, U, Z
109 def ProfileCurve(type=0, a
=0.25, b
=0.25):
111 ProfileCurve( type=0, a=0.25, b=0.25 )
116 type - select profile type, L, H, T, U, Z
118 a - a scaling parameter
120 b - b scaling parameter
123 a list with lists of x,y,z coordinates for curve points, [[x,y,z],[x,y,z],...n]
133 [-1.0, 1.0, 0.0], [-1.0 + a
, 1.0, 0.0],
134 [-1.0 + a
, b
, 0.0], [1.0 - a
, b
, 0.0], [1.0 - a
, 1.0, 0.0],
135 [1.0, 1.0, 0.0], [1.0, -1.0, 0.0], [1.0 - a
, -1.0, 0.0],
136 [1.0 - a
, -b
, 0.0], [-1.0 + a
, -b
, 0.0], [-1.0 + a
, -1.0, 0.0],
143 [-1.0, 1.0, 0.0], [1.0, 1.0, 0.0],
144 [1.0, 1.0 - b
, 0.0], [a
, 1.0 - b
, 0.0], [a
, -1.0, 0.0],
145 [-a
, -1.0, 0.0], [-a
, 1.0 - b
, 0.0], [-1.0, 1.0 - b
, 0.0]
151 [-1.0, 1.0, 0.0], [-1.0 + a
, 1.0, 0.0],
152 [-1.0 + a
, -1.0 + b
, 0.0], [1.0 - a
, -1.0 + b
, 0.0], [1.0 - a
, 1.0, 0.0],
153 [1.0, 1.0, 0.0], [1.0, -1.0, 0.0], [-1.0, -1.0, 0.0]
159 [-0.5, 1.0, 0.0], [a
, 1.0, 0.0],
160 [a
, -1.0 + b
, 0.0], [1.0, -1.0 + b
, 0.0], [1.0, -1.0, 0.0],
161 [-a
, -1.0, 0.0], [-a
, 1.0 - b
, 0.0], [-1.0, 1.0 - b
, 0.0],
167 [-1.0, 1.0, 0.0], [-1.0 + a
, 1.0, 0.0],
168 [-1.0 + a
, -1.0 + b
, 0.0], [1.0, -1.0 + b
, 0.0],
169 [1.0, -1.0, 0.0], [-1.0, -1.0, 0.0]
174 # ------------------------------------------------------------
176 def ArrowCurve(type=1, a
=1.0, b
=0.5):
178 ArrowCurve( type=1, a=1.0, b=0.5, c=1.0 )
183 type - select type, Arrow1, Arrow2
185 a - a scaling parameter
187 b - b scaling parameter
190 a list with lists of x,y,z coordinates for curve points, [[x,y,z],[x,y,z],...n]
200 [-1.0, b
, 0.0], [-1.0 + a
, b
, 0.0],
201 [-1.0 + a
, 1.0, 0.0], [1.0, 0.0, 0.0],
202 [-1.0 + a
, -1.0, 0.0], [-1.0 + a
, -b
, 0.0],
207 newpoints
= [[-a
, b
, 0.0], [a
, 0.0, 0.0], [-a
, -b
, 0.0], [0.0, 0.0, 0.0]]
210 newpoints
= [[0.0, b
, 0.0], [a
, 0.0, 0.0], [0.0, -b
, 0.0], [-a
, 0.0, 0.0]]
214 # ------------------------------------------------------------
215 # 2DCurve: Square / Rectangle
216 def RectCurve(type=1, a
=1.0, b
=0.5, c
=1.0):
218 RectCurve( type=1, a=1.0, b=0.5, c=1.0 )
220 Create square / rectangle curve
223 type - select type, Square, Rounded square 1, Rounded square 2
225 a - a scaling parameter
227 b - b scaling parameter
229 c - c scaling parameter
232 a list with lists of x,y,z coordinates for curve points, [[x,y,z],[x,y,z],...n]
240 [-a
, b
- b
* 0.2, 0.0], [-a
+ a
* 0.05, b
- b
* 0.05, 0.0], [-a
+ a
* 0.2, b
, 0.0],
241 [a
- a
* 0.2, b
, 0.0], [a
- a
* 0.05, b
- b
* 0.05, 0.0], [a
, b
- b
* 0.2, 0.0],
242 [a
, -b
+ b
* 0.2, 0.0], [a
- a
* 0.05, -b
+ b
* 0.05, 0.0], [a
- a
* 0.2, -b
, 0.0],
243 [-a
+ a
* 0.2, -b
, 0.0], [-a
+ a
* 0.05, -b
+ b
* 0.05, 0.0], [-a
, -b
+ b
* 0.2, 0.0]
246 # Rounded Rectangle II:
256 newpoints
.append([-x
+ r
, y
, 0])
257 newpoints
.append([x
- r
, y
, 0])
258 newpoints
.append([x
, y
- r
, 0])
259 newpoints
.append([x
, -y
+ r
, 0])
260 newpoints
.append([x
- r
, -y
, 0])
261 newpoints
.append([-x
+ r
, -y
, 0])
262 newpoints
.append([-x
, -y
+ r
, 0])
263 newpoints
.append([-x
, y
- r
, 0])
265 newpoints
.append([-x
, y
, 0])
266 newpoints
.append([x
, y
, 0])
267 newpoints
.append([x
, -y
, 0])
268 newpoints
.append([-x
, -y
, 0])
271 newpoints
= [[-a
, b
, 0.0], [a
, b
, 0.0], [a
, -b
, 0.0], [-a
, -b
, 0.0]]
275 # ------------------------------------------------------------
277 def StarCurve(starpoints
=8, innerradius
=0.5, outerradius
=1.0, twist
=0.0):
279 StarCurve( starpoints=8, innerradius=0.5, outerradius=1.0, twist=0.0 )
281 Create star shaped curve
284 starpoints - the number of points
286 innerradius - innerradius
288 outerradius - outerradius
293 a list with lists of x,y,z coordinates for curve points, [[x,y,z],[x,y,z],...n]
298 step
= 2.0 / starpoints
300 while i
< starpoints
:
302 x1
= cos(t
* pi
) * outerradius
303 y1
= sin(t
* pi
) * outerradius
304 newpoints
.append([x1
, y1
, 0])
305 x2
= cos(t
* pi
+ (pi
/ starpoints
+ twist
)) * innerradius
306 y2
= sin(t
* pi
+ (pi
/ starpoints
+ twist
)) * innerradius
307 newpoints
.append([x2
, y2
, 0])
312 # ------------------------------------------------------------
314 def FlowerCurve(petals
=8, innerradius
=0.5, outerradius
=1.0, petalwidth
=2.0):
316 FlowerCurve( petals=8, innerradius=0.5, outerradius=1.0, petalwidth=2.0 )
318 Create flower shaped curve
321 petals - the number of petals
323 innerradius - innerradius
325 outerradius - outerradius
327 petalwidth - width of petals
330 a list with lists of x,y,z coordinates for curve points, [[x,y,z],[x,y,z],...n]
336 pet
= (step
/ pi
* 2) * petalwidth
340 x1
= cos(t
* pi
- (pi
/ petals
)) * innerradius
341 y1
= sin(t
* pi
- (pi
/ petals
)) * innerradius
342 newpoints
.append([x1
, y1
, 0])
343 x2
= cos(t
* pi
- pet
) * outerradius
344 y2
= sin(t
* pi
- pet
) * outerradius
345 newpoints
.append([x2
, y2
, 0])
346 x3
= cos(t
* pi
+ pet
) * outerradius
347 y3
= sin(t
* pi
+ pet
) * outerradius
348 newpoints
.append([x3
, y3
, 0])
353 # ------------------------------------------------------------
354 # 2DCurve: Arc,Sector,Segment,Ring:
355 def ArcCurve(sides
=6, startangle
=0.0, endangle
=90.0, innerradius
=0.5, outerradius
=1.0, type=3):
357 ArcCurve( sides=6, startangle=0.0, endangle=90.0, innerradius=0.5, outerradius=1.0, type=3 )
359 Create arc shaped curve
362 sides - number of sides
364 startangle - startangle
368 innerradius - innerradius
370 outerradius - outerradius
372 type - select type Arc,Sector,Segment,Ring
375 a list with lists of x,y,z coordinates for curve points, [[x,y,z],[x,y,z],...n]
381 angle
= 2.0 * (1.0 / 360.0)
382 endangle
-= startangle
383 step
= (angle
* endangle
) / (sides
- 1)
386 t
= (i
* step
) + angle
* startangle
387 x1
= sin(t
* pi
) * outerradius
388 y1
= cos(t
* pi
) * outerradius
389 newpoints
.append([x1
, y1
, 0])
393 # Arc: turn cyclic curve flag off!
397 newpoints
.append([0, 0, 0])
402 t
= (j
* step
) + angle
* startangle
403 x2
= sin(t
* pi
) * innerradius
404 y2
= cos(t
* pi
) * innerradius
405 newpoints
.append([x2
, y2
, 0])
410 # ------------------------------------------------------------
411 # 2DCurve: Cog wheel:
412 def CogCurve(theeth
=8, innerradius
=0.8, middleradius
=0.95, outerradius
=1.0, bevel
=0.5):
414 CogCurve( theeth=8, innerradius=0.8, middleradius=0.95, outerradius=1.0, bevel=0.5 )
416 Create cog wheel shaped curve
419 theeth - number of theeth
421 innerradius - innerradius
423 middleradius - middleradius
425 outerradius - outerradius
430 a list with lists of x,y,z coordinates for curve points, [[x,y,z],[x,y,z],...n]
441 x1
= cos(t
* pi
- (pi
/ theeth
) - pet
) * innerradius
442 y1
= sin(t
* pi
- (pi
/ theeth
) - pet
) * innerradius
443 newpoints
.append([x1
, y1
, 0])
444 x2
= cos(t
* pi
- (pi
/ theeth
) + pet
) * innerradius
445 y2
= sin(t
* pi
- (pi
/ theeth
) + pet
) * innerradius
446 newpoints
.append([x2
, y2
, 0])
447 x3
= cos(t
* pi
- pet
) * middleradius
448 y3
= sin(t
* pi
- pet
) * middleradius
449 newpoints
.append([x3
, y3
, 0])
450 x4
= cos(t
* pi
- (pet
* bevel
)) * outerradius
451 y4
= sin(t
* pi
- (pet
* bevel
)) * outerradius
452 newpoints
.append([x4
, y4
, 0])
453 x5
= cos(t
* pi
+ (pet
* bevel
)) * outerradius
454 y5
= sin(t
* pi
+ (pet
* bevel
)) * outerradius
455 newpoints
.append([x5
, y5
, 0])
456 x6
= cos(t
* pi
+ pet
) * middleradius
457 y6
= sin(t
* pi
+ pet
) * middleradius
458 newpoints
.append([x6
, y6
, 0])
463 # ------------------------------------------------------------
465 def nSideCurve(sides
=6, radius
=1.0):
467 nSideCurve( sides=6, radius=1.0 )
472 sides - number of sides
477 a list with lists of x,y,z coordinates for curve points, [[x,y,z],[x,y,z],...n]
486 x
= sin(t
* pi
) * radius
487 y
= cos(t
* pi
) * radius
488 newpoints
.append([x
, y
, 0])
493 # ------------------------------------------------------------
495 def SplatCurve(sides
=24, scale
=1.0, seed
=0, basis
=0, radius
=1.0):
497 SplatCurve( sides=24, scale=1.0, seed=0, basis=0, radius=1.0 )
502 sides - number of sides
506 seed - noise random seed
513 a list with lists of x,y,z coordinates for curve points, [[x,y,z],[x,y,z],...n]
522 turb
= vTurbNoise(t
, t
, t
, 1.0, scale
, 6, False, basis
, seed
)
523 turb
= turb
[2] * 0.5 + 0.5
524 x
= sin(t
* pi
) * radius
* turb
525 y
= cos(t
* pi
) * radius
* turb
526 newpoints
.append([x
, y
, 0])
531 # -----------------------------------------------------------
533 def CycloidCurve(number
=100, type=0, R
=4.0, r
=1.0, d
=1.0):
535 CycloidCurve( number=100, type=0, a=4.0, b=1.0 )
537 Create a Cycloid, Hypotrochoid / Hypocycloid or Epitrochoid / Epycycloid type of curve
540 number - the number of points
542 type - types: Cycloid, Hypocycloid, Epicycloid
544 R = Radius a scaling parameter
546 r = Radius b scaling parameter
548 d = Distance scaling parameter
551 a list with lists of x,y,z coordinates for curve points, [[x,y,z],[x,y,z],...n]
558 step
= 2.0 / (number
- 1)
561 # Hypotrochoid / Hypocycloid
564 x
= ((a
- b
) * cos(t
* pi
)) + (d
* cos(((a
+ b
) / b
) * t
* pi
))
565 y
= ((a
- b
) * sin(t
* pi
)) - (d
* sin(((a
+ b
) / b
) * t
* pi
))
567 newpoints
.append([x
, y
, z
])
570 # Epitrochoid / Epycycloid
573 x
= ((a
+ b
) * cos(t
* pi
)) - (d
* cos(((a
+ b
) / b
) * t
* pi
))
574 y
= ((a
+ b
) * sin(t
* pi
)) - (d
* sin(((a
+ b
) / b
) * t
* pi
))
576 newpoints
.append([x
, y
, z
])
582 x
= (t
- sin(t
) * b
) * a
/ pi
583 y
= (1 - cos(t
) * b
) * a
/ pi
585 newpoints
.append([x
, y
, z
])
590 # -----------------------------------------------------------
591 # 3D curve shape functions:
592 # -----------------------------------------------------------
594 # ------------------------------------------------------------
596 def HelixCurve(number
=100, height
=2.0, startangle
=0.0, endangle
=360.0, width
=1.0, a
=0.0, b
=0.0):
598 HelixCurve( number=100, height=2.0, startangle=0.0, endangle=360.0, width=1.0, a=0.0, b=0.0 )
603 number - the number of points
607 startangle - startangle
618 a list with lists of x,y,z coordinates for curve points, [[x,y,z],[x,y,z],...n]
623 angle
= (2.0 / 360.0) * (endangle
- startangle
)
624 step
= angle
/ (number
- 1)
626 start
= startangle
* 2.0 / 360.0
630 t
= (i
* step
+ start
)
631 x
= sin((t
* pi
)) * (1.0 + cos(t
* pi
* a
- (b
* pi
))) * (0.25 * width
)
632 y
= cos((t
* pi
)) * (1.0 + cos(t
* pi
* a
- (b
* pi
))) * (0.25 * width
)
633 z
= (t
* h
) - h
* start
634 newpoints
.append([x
, y
, z
])
639 # -----------------------------------------------------------
641 def NoiseCurve(type=0, number
=100, length
=2.0, size
=0.5,
642 scale
=[0.5, 0.5, 0.5], octaves
=2, basis
=0, seed
=0):
647 number - number of points
649 length - curve length
653 scale - noise intensity scale x,y,z
657 seed - noise random seed
659 type - noise curve type
662 a list with lists of x,y,z coordinates for curve points, [[x,y,z],[x,y,z],...n]
667 step
= (length
/ number
)
673 v
= vTurbNoise(t
, t
, t
, 1.0, size
, octaves
, False, basis
, seed
)
674 x
= sin(t
* pi
) + (v
[0] * scale
[0])
675 y
= cos(t
* pi
) + (v
[1] * scale
[1])
677 newpoints
.append([x
, y
, z
])
683 v
= vTurbNoise(t
, t
, t
, 1.0, 1.0, octaves
, False, basis
, seed
)
684 x
= v
[0] * scale
[0] * size
685 y
= v
[1] * scale
[1] * size
686 z
= v
[2] * scale
[2] * size
687 newpoints
.append([x
, y
, z
])
693 v
= vTurbNoise(t
, t
, t
, 1.0, size
, octaves
, False, basis
, seed
)
694 x
= t
+ v
[0] * scale
[0]
697 newpoints
.append([x
, y
, z
])
702 # get array of vertcoordinates according to splinetype
703 def vertsToPoints(Verts
, splineType
):
708 # array for BEZIER spline output (V3)
709 if splineType
== 'BEZIER':
713 # array for nonBEZIER output (V4)
717 if splineType
== 'NURBS':
726 # create new CurveObject from vertarray and splineType
727 def createCurve(context
, vertArray
, self
):
728 # output splineType 'POLY' 'NURBS' 'BEZIER'
729 splineType
= self
.outputType
731 # GalloreType as name
732 name
= self
.ProfileType
735 if bpy
.context
.mode
== 'EDIT_CURVE':
736 Curve
= context
.active_object
737 newSpline
= Curve
.data
.splines
.new(type=splineType
) # spline
740 dataCurve
= bpy
.data
.curves
.new(name
, type='CURVE') # curve data block
741 newSpline
= dataCurve
.splines
.new(type=splineType
) # spline
743 # create object with newCurve
744 Curve
= object_utils
.object_data_add(context
, dataCurve
, operator
=self
) # place in active scene
746 # set newSpline Options
747 newSpline
.use_cyclic_u
= self
.use_cyclic_u
748 newSpline
.use_endpoint_u
= self
.endp_u
749 newSpline
.order_u
= self
.order_u
752 Curve
.data
.dimensions
= self
.shape
753 Curve
.data
.use_path
= True
754 if self
.shape
== '3D':
755 Curve
.data
.fill_mode
= 'FULL'
757 Curve
.data
.fill_mode
= 'BOTH'
759 for spline
in Curve
.data
.splines
:
760 if spline
.type == 'BEZIER':
761 for point
in spline
.bezier_points
:
762 point
.select_control_point
= False
763 point
.select_left_handle
= False
764 point
.select_right_handle
= False
766 for point
in spline
.points
:
769 # create spline from vertarray
770 if splineType
== 'BEZIER':
771 newSpline
.bezier_points
.add(int(len(vertArray
) * 0.33))
772 newSpline
.bezier_points
.foreach_set('co', vertArray
)
773 for point
in newSpline
.bezier_points
:
774 point
.handle_right_type
= self
.handleType
775 point
.handle_left_type
= self
.handleType
776 point
.select_control_point
= True
777 point
.select_left_handle
= True
778 point
.select_right_handle
= True
780 newSpline
.points
.add(int(len(vertArray
) * 0.25 - 1))
781 newSpline
.points
.foreach_set('co', vertArray
)
782 newSpline
.use_endpoint_u
= True
783 for point
in newSpline
.points
:
786 # move and rotate spline in edit mode
787 if bpy
.context
.mode
== 'EDIT_CURVE':
788 if self
.align
== "WORLD":
789 location
= self
.location
- context
.active_object
.location
790 bpy
.ops
.transform
.translate(value
= location
, orient_type
='GLOBAL')
791 bpy
.ops
.transform
.rotate(value
= self
.rotation
[0], orient_axis
= 'X', orient_type
='GLOBAL')
792 bpy
.ops
.transform
.rotate(value
= self
.rotation
[1], orient_axis
= 'Y', orient_type
='GLOBAL')
793 bpy
.ops
.transform
.rotate(value
= self
.rotation
[2], orient_axis
= 'Z', orient_type
='GLOBAL')
795 elif self
.align
== "VIEW":
796 bpy
.ops
.transform
.translate(value
= self
.location
)
797 bpy
.ops
.transform
.rotate(value
= self
.rotation
[0], orient_axis
= 'X')
798 bpy
.ops
.transform
.rotate(value
= self
.rotation
[1], orient_axis
= 'Y')
799 bpy
.ops
.transform
.rotate(value
= self
.rotation
[2], orient_axis
= 'Z')
801 elif self
.align
== "CURSOR":
802 location
= context
.active_object
.location
803 self
.location
= bpy
.context
.scene
.cursor
.location
- location
804 self
.rotation
= bpy
.context
.scene
.cursor
.rotation_euler
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')
814 # ------------------------------------------------------------
816 def main(context
, self
):
818 proType
= self
.ProfileType
819 splineType
= self
.outputType
820 innerRadius
= self
.innerRadius
821 middleRadius
= self
.middleRadius
822 outerRadius
= self
.outerRadius
825 if proType
== 'Profile':
826 verts
= ProfileCurve(
827 self
.ProfileCurveType
,
828 self
.ProfileCurvevar1
,
829 self
.ProfileCurvevar2
831 if proType
== 'Arrow':
837 if proType
== 'Rectangle':
844 if proType
== 'Flower':
851 if proType
== 'Star':
867 if proType
== 'Cogwheel':
875 if proType
== 'Nsided':
880 if proType
== 'Splat':
888 if proType
== 'Cycloid':
889 verts
= CycloidCurve(
896 if proType
== 'Helix':
906 if proType
== 'Noise':
912 [self
.noiseScaleX
, self
.noiseScaleY
, self
.noiseScaleZ
],
918 # turn verts into array
919 vertArray
= vertsToPoints(verts
, splineType
)
922 createCurve(context
, vertArray
, self
)
927 class Curveaceous_galore(Operator
, object_utils
.AddObjectHelper
):
928 bl_idname
= "curve.curveaceous_galore"
929 bl_label
= "Curve Profiles"
930 bl_description
= "Construct many types of curves"
931 bl_options
= {'REGISTER', 'UNDO', 'PRESET'}
934 ProfileType
: EnumProperty(
936 description
="Form of Curve to create",
938 ('Arc', "Arc", "Arc"),
939 ('Arrow', "Arrow", "Arrow"),
940 ('Cogwheel', "Cogwheel", "Cogwheel"),
941 ('Cycloid', "Cycloid", "Cycloid"),
942 ('Flower', "Flower", "Flower"),
943 ('Helix', "Helix (3D)", "Helix"),
944 ('Noise', "Noise (3D)", "Noise"),
945 ('Nsided', "Nsided", "Nsided"),
946 ('Profile', "Profile", "Profile"),
947 ('Rectangle', "Rectangle", "Rectangle"),
948 ('Splat', "Splat", "Splat"),
949 ('Star', "Star", "Star")]
951 outputType
: EnumProperty(
952 name
="Output splines",
953 description
="Type of splines to output",
955 ('POLY', "Poly", "Poly Spline type"),
956 ('NURBS', "Nurbs", "Nurbs Spline type"),
957 ('BEZIER', "Bezier", "Bezier Spline type")]
960 shape
: EnumProperty(
962 description
="2D or 3D Curve",
968 use_cyclic_u
: BoolProperty(
971 description
="make curve closed"
973 endp_u
: BoolProperty(
974 name
="Use endpoint u",
976 description
="stretch to endpoints"
978 order_u
: IntProperty(
983 description
="Order of nurbs spline"
985 handleType
: EnumProperty(
988 description
="Bezier handles type",
990 ('VECTOR', "Vector", "Vector type Bezier handles"),
991 ('AUTO', "Auto", "Automatic type Bezier handles")]
993 # ProfileCurve properties
994 ProfileCurveType
: IntProperty(
999 description
="Type of Curve's Profile"
1001 ProfileCurvevar1
: FloatProperty(
1004 description
="Variable 1 of Curve's Profile"
1006 ProfileCurvevar2
: FloatProperty(
1009 description
="Variable 2 of Curve's Profile"
1011 # Arrow, Rectangle, MiscCurve properties
1012 MiscCurveType
: IntProperty(
1017 description
="Type of Curve"
1019 MiscCurvevar1
: FloatProperty(
1022 description
="Variable 1 of Curve"
1024 MiscCurvevar2
: FloatProperty(
1027 description
="Variable 2 of Curve"
1029 MiscCurvevar3
: FloatProperty(
1033 description
="Variable 3 of Curve"
1036 innerRadius
: FloatProperty(
1037 name
="Inner radius",
1040 description
="Inner radius"
1042 middleRadius
: FloatProperty(
1043 name
="Middle radius",
1046 description
="Middle radius"
1048 outerRadius
: FloatProperty(
1049 name
="Outer radius",
1052 description
="Outer radius"
1055 petals
: IntProperty(
1059 description
="Number of petals"
1061 petalWidth
: FloatProperty(
1065 description
="Petal width"
1068 starPoints
: IntProperty(
1072 description
="Number of star points"
1074 starTwist
: FloatProperty(
1080 arcSides
: IntProperty(
1084 description
="Sides of arc"
1086 startAngle
: FloatProperty(
1089 description
="Start angle"
1091 endAngle
: FloatProperty(
1094 description
="End angle"
1096 arcType
: IntProperty(
1101 description
="Sides of arc"
1103 # Cogwheel properties
1104 teeth
: IntProperty(
1108 description
="number of teeth"
1110 bevel
: FloatProperty(
1118 Nsides
: IntProperty(
1122 description
="Number of sides"
1125 splatSides
: IntProperty(
1129 description
="Splat sides"
1131 splatScale
: FloatProperty(
1135 description
="Splat scale"
1143 basis
: IntProperty(
1151 helixPoints
: IntProperty(
1155 description
="Resolution"
1157 helixHeight
: FloatProperty(
1161 description
="Helix height"
1163 helixStart
: FloatProperty(
1166 description
="Helix start angle"
1168 helixEnd
: FloatProperty(
1171 description
="Helix end angle"
1173 helixWidth
: FloatProperty(
1176 description
="Helix width"
1178 helix_a
: FloatProperty(
1181 description
="Helix Variable 1"
1183 helix_b
: FloatProperty(
1186 description
="Helix Variable 2"
1188 # Cycloid properties
1189 cycloPoints
: IntProperty(
1194 description
="Resolution"
1196 cycloType
: IntProperty(
1201 description
="Type: Cycloid , Hypocycloid / Hypotrochoid , Epicycloid / Epitrochoid"
1203 cyclo_a
: FloatProperty(
1207 description
="Cycloid: R radius a"
1209 cyclo_b
: FloatProperty(
1213 description
="Cycloid: r radius b"
1215 cyclo_d
: FloatProperty(
1218 description
="Cycloid: d distance"
1221 noiseType
: IntProperty(
1226 description
="Noise curve type: Linear, Circular or Knot"
1228 noisePoints
: IntProperty(
1232 description
="Resolution"
1234 noiseLength
: FloatProperty(
1238 description
="Curve Length"
1240 noiseSize
: FloatProperty(
1244 description
="Noise size"
1246 noiseScaleX
: FloatProperty(
1250 description
="Noise x"
1252 noiseScaleY
: FloatProperty(
1256 description
="Noise y"
1258 noiseScaleZ
: FloatProperty(
1262 description
="Noise z"
1264 noiseOctaves
: IntProperty(
1271 noiseBasis
: IntProperty(
1278 noiseSeed
: IntProperty(
1282 description
="Random Seed"
1285 edit_mode
: BoolProperty(
1286 name
="Show in edit mode",
1288 description
="Show in edit mode"
1291 def draw(self
, context
):
1292 layout
= self
.layout
1295 col
= layout
.column()
1296 col
.prop(self
, 'ProfileType')
1297 col
.label(text
=self
.ProfileType
+ " Options:")
1299 # options per ProfileType
1301 col
= box
.column(align
=True)
1303 if self
.ProfileType
== 'Profile':
1304 col
.prop(self
, "ProfileCurveType")
1305 col
.prop(self
, "ProfileCurvevar1")
1306 col
.prop(self
, "ProfileCurvevar2")
1308 elif self
.ProfileType
== 'Arrow':
1309 col
.prop(self
, "MiscCurveType")
1310 col
.prop(self
, "MiscCurvevar1", text
="Height")
1311 col
.prop(self
, "MiscCurvevar2", text
="Width")
1313 elif self
.ProfileType
== 'Rectangle':
1314 col
.prop(self
, "MiscCurveType")
1315 col
.prop(self
, "MiscCurvevar1", text
="Width")
1316 col
.prop(self
, "MiscCurvevar2", text
="Height")
1317 if self
.MiscCurveType
== 2:
1318 col
.prop(self
, "MiscCurvevar3", text
="Corners")
1320 elif self
.ProfileType
== 'Flower':
1321 col
.prop(self
, "petals")
1322 col
.prop(self
, "petalWidth")
1324 col
= box
.column(align
=True)
1325 col
.prop(self
, "innerRadius")
1326 col
.prop(self
, "outerRadius")
1328 elif self
.ProfileType
== 'Star':
1329 col
.prop(self
, "starPoints")
1330 col
.prop(self
, "starTwist")
1332 col
= box
.column(align
=True)
1333 col
.prop(self
, "innerRadius")
1334 col
.prop(self
, "outerRadius")
1336 elif self
.ProfileType
== 'Arc':
1337 col
.prop(self
, "arcType")
1338 col
.prop(self
, "arcSides")
1340 col
= box
.column(align
=True)
1341 col
.prop(self
, "startAngle")
1342 col
.prop(self
, "endAngle")
1344 col
= box
.column(align
=True)
1345 col
.prop(self
, "innerRadius")
1346 col
.prop(self
, "outerRadius")
1348 elif self
.ProfileType
== 'Cogwheel':
1349 col
.prop(self
, "teeth")
1350 col
.prop(self
, "bevel")
1352 col
= box
.column(align
=True)
1353 col
.prop(self
, "innerRadius")
1354 col
.prop(self
, "middleRadius")
1355 col
.prop(self
, "outerRadius")
1357 elif self
.ProfileType
== 'Nsided':
1358 col
.prop(self
, "Nsides")
1359 col
.prop(self
, "outerRadius")
1361 elif self
.ProfileType
== 'Splat':
1362 col
.prop(self
, "splatSides")
1363 col
.prop(self
, "outerRadius")
1365 col
= box
.column(align
=True)
1366 col
.prop(self
, "splatScale")
1367 col
.prop(self
, "seed")
1368 col
.prop(self
, "basis")
1370 elif self
.ProfileType
== 'Cycloid':
1371 col
.prop(self
, "cycloType")
1372 col
.prop(self
, "cycloPoints")
1374 col
= box
.column(align
=True)
1375 col
.prop(self
, "cyclo_a")
1376 col
.prop(self
, "cyclo_b")
1377 if self
.cycloType
!= 0:
1378 col
.prop(self
, "cyclo_d")
1380 elif self
.ProfileType
== 'Helix':
1381 col
.prop(self
, "helixPoints")
1382 col
.prop(self
, "helixHeight")
1383 col
.prop(self
, "helixWidth")
1385 col
= box
.column(align
=True)
1386 col
.prop(self
, "helixStart")
1387 col
.prop(self
, "helixEnd")
1389 col
= box
.column(align
=True)
1390 col
.prop(self
, "helix_a")
1391 col
.prop(self
, "helix_b")
1393 elif self
.ProfileType
== 'Noise':
1394 col
.prop(self
, "noiseType")
1395 col
.prop(self
, "noisePoints")
1396 col
.prop(self
, "noiseLength")
1398 col
= box
.column(align
=True)
1399 col
.prop(self
, "noiseSize")
1400 col
.prop(self
, "noiseScaleX")
1401 col
.prop(self
, "noiseScaleY")
1402 col
.prop(self
, "noiseScaleZ")
1404 col
= box
.column(align
=True)
1405 col
.prop(self
, "noiseOctaves")
1406 col
.prop(self
, "noiseBasis")
1407 col
.prop(self
, "noiseSeed")
1410 row
.prop(self
, "shape", expand
=True)
1413 col
= layout
.column()
1414 col
.label(text
="Output Curve Type:")
1415 col
.row().prop(self
, "outputType", expand
=True)
1417 if self
.outputType
== 'NURBS':
1418 col
.prop(self
, 'order_u')
1419 elif self
.outputType
== 'BEZIER':
1420 col
.row().prop(self
, 'handleType', expand
=True)
1422 col
= layout
.column()
1423 col
.row().prop(self
, "use_cyclic_u", expand
=True)
1425 col
= layout
.column()
1426 col
.row().prop(self
, "edit_mode", expand
=True)
1428 col
= layout
.column()
1429 # AddObjectHelper props
1430 col
.prop(self
, "align")
1431 col
.prop(self
, "location")
1432 col
.prop(self
, "rotation")
1435 def poll(cls
, context
):
1436 return context
.scene
is not None
1438 def execute(self
, context
):
1439 # turn off 'Enter Edit Mode'
1440 use_enter_edit_mode
= bpy
.context
.preferences
.edit
.use_enter_edit_mode
1441 bpy
.context
.preferences
.edit
.use_enter_edit_mode
= False
1446 if use_enter_edit_mode
:
1447 bpy
.ops
.object.mode_set(mode
= 'EDIT')
1449 # restore pre operator state
1450 bpy
.context
.preferences
.edit
.use_enter_edit_mode
= use_enter_edit_mode
1453 bpy
.ops
.object.mode_set(mode
= 'EDIT')
1455 bpy
.ops
.object.mode_set(mode
= 'OBJECT')
1459 def invoke(self
, context
, event
):
1460 # deal with 2D - 3D curve differences
1461 if self
.ProfileType
in ['Helix', 'Cycloid', 'Noise']:
1466 if self
.ProfileType
in ['Helix', 'Noise', 'Cycloid']:
1467 self
.use_cyclic_u
= False
1468 if self
.ProfileType
in ['Cycloid']:
1469 if self
.cycloType
== 0:
1470 self
.use_cyclic_u
= False
1472 self
.use_cyclic_u
= True
1474 if self
.ProfileType
== 'Arc' and self
.arcType
== 1:
1475 self
.use_cyclic_u
= False
1477 self
.use_cyclic_u
= True
1479 self
.execute(context
)
1489 from bpy
.utils
import register_class
1494 from bpy
.utils
import unregister_class
1495 for cls
in reversed(classes
):
1496 unregister_class(cls
)
1498 if __name__
== "__main__":