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 #####
21 "name": "Curveaceous Galore!",
22 "author": "Jimmy Hazevoet, testscreenings",
25 "location": "View3D > Add > Curve",
26 "description": "Adds many different types of Curves",
28 "doc_url": "https://wiki.blender.org/index.php/Extensions:2.6/Py/"
29 "Scripts/Curve/Curves_Galore",
30 "category": "Add Curve",
35 from bpy_extras
import object_utils
36 from bpy
.props
import (
43 from mathutils
import Matrix
, Vector
44 from bpy
.types
import Operator
48 import mathutils
.noise
as Noise
51 # ------------------------------------------------------------
52 # Some functions to use with others:
53 # ------------------------------------------------------------
55 # ------------------------------------------------------------
56 # Generate random number:
57 def randnum(low
=0.0, high
=1.0, seed
=0):
59 randnum( low=0.0, high=1.0, seed=0 )
67 seed - the random seed number, if seed == 0, the current time will be used instead
76 rnum
= rnum
* (high
- low
)
81 # ------------------------------------------------------------
83 def vTurbNoise(x
, y
, z
, iScale
=0.25, Size
=1.0, Depth
=6, Hard
=False, Basis
=0, Seed
=0):
85 vTurbNoise((x,y,z), iScale=0.25, Size=1.0, Depth=6, Hard=0, Basis=0, Seed=0 )
87 Create randomised vTurbulence noise
90 xyz - (x,y,z) float values.
92 iScale - noise intensity scale
96 Depth - number of noise values added.
98 Hard - noise hardness: True - soft noise; False - hard noise
100 basis - type of noise used for turbulence
102 Seed - the random seed number, if seed == 0, the current time will be used instead
105 the generated turbulence vector.
108 rand
= randnum(-100, 100, Seed
)
111 vec
= Vector((x
/ Size
+ rand
, y
/ Size
+ rand
, z
/ Size
+ rand
))
112 vTurb
= Noise
.turbulence_vector(vec
, Depth
, Hard
)
113 #mathutils.noise.turbulence_vector(position, octaves, hard, noise_basis='PERLIN_ORIGINAL', amplitude_scale=0.5, frequency_scale=2.0)
114 tx
= vTurb
[0] * iScale
115 ty
= vTurb
[1] * iScale
116 tz
= vTurb
[2] * iScale
120 # -------------------------------------------------------------------
121 # 2D Curve shape functions:
122 # -------------------------------------------------------------------
124 # ------------------------------------------------------------
125 # 2DCurve: Profile: L, H, T, U, Z
126 def ProfileCurve(type=0, a
=0.25, b
=0.25):
128 ProfileCurve( type=0, a=0.25, b=0.25 )
133 type - select profile type, L, H, T, U, Z
135 a - a scaling parameter
137 b - b scaling parameter
140 a list with lists of x,y,z coordinates for curve points, [[x,y,z],[x,y,z],...n]
150 [-1.0, 1.0, 0.0], [-1.0 + a
, 1.0, 0.0],
151 [-1.0 + a
, b
, 0.0], [1.0 - a
, b
, 0.0], [1.0 - a
, 1.0, 0.0],
152 [1.0, 1.0, 0.0], [1.0, -1.0, 0.0], [1.0 - a
, -1.0, 0.0],
153 [1.0 - a
, -b
, 0.0], [-1.0 + a
, -b
, 0.0], [-1.0 + a
, -1.0, 0.0],
160 [-1.0, 1.0, 0.0], [1.0, 1.0, 0.0],
161 [1.0, 1.0 - b
, 0.0], [a
, 1.0 - b
, 0.0], [a
, -1.0, 0.0],
162 [-a
, -1.0, 0.0], [-a
, 1.0 - b
, 0.0], [-1.0, 1.0 - b
, 0.0]
168 [-1.0, 1.0, 0.0], [-1.0 + a
, 1.0, 0.0],
169 [-1.0 + a
, -1.0 + b
, 0.0], [1.0 - a
, -1.0 + b
, 0.0], [1.0 - a
, 1.0, 0.0],
170 [1.0, 1.0, 0.0], [1.0, -1.0, 0.0], [-1.0, -1.0, 0.0]
176 [-0.5, 1.0, 0.0], [a
, 1.0, 0.0],
177 [a
, -1.0 + b
, 0.0], [1.0, -1.0 + b
, 0.0], [1.0, -1.0, 0.0],
178 [-a
, -1.0, 0.0], [-a
, 1.0 - b
, 0.0], [-1.0, 1.0 - b
, 0.0],
184 [-1.0, 1.0, 0.0], [-1.0 + a
, 1.0, 0.0],
185 [-1.0 + a
, -1.0 + b
, 0.0], [1.0, -1.0 + b
, 0.0],
186 [1.0, -1.0, 0.0], [-1.0, -1.0, 0.0]
191 # ------------------------------------------------------------
193 def ArrowCurve(type=1, a
=1.0, b
=0.5):
195 ArrowCurve( type=1, a=1.0, b=0.5, c=1.0 )
200 type - select type, Arrow1, Arrow2
202 a - a scaling parameter
204 b - b scaling parameter
207 a list with lists of x,y,z coordinates for curve points, [[x,y,z],[x,y,z],...n]
217 [-1.0, b
, 0.0], [-1.0 + a
, b
, 0.0],
218 [-1.0 + a
, 1.0, 0.0], [1.0, 0.0, 0.0],
219 [-1.0 + a
, -1.0, 0.0], [-1.0 + a
, -b
, 0.0],
224 newpoints
= [[-a
, b
, 0.0], [a
, 0.0, 0.0], [-a
, -b
, 0.0], [0.0, 0.0, 0.0]]
227 newpoints
= [[0.0, b
, 0.0], [a
, 0.0, 0.0], [0.0, -b
, 0.0], [-a
, 0.0, 0.0]]
231 # ------------------------------------------------------------
232 # 2DCurve: Square / Rectangle
233 def RectCurve(type=1, a
=1.0, b
=0.5, c
=1.0):
235 RectCurve( type=1, a=1.0, b=0.5, c=1.0 )
237 Create square / rectangle curve
240 type - select type, Square, Rounded square 1, Rounded square 2
242 a - a scaling parameter
244 b - b scaling parameter
246 c - c scaling parameter
249 a list with lists of x,y,z coordinates for curve points, [[x,y,z],[x,y,z],...n]
257 [-a
, b
- b
* 0.2, 0.0], [-a
+ a
* 0.05, b
- b
* 0.05, 0.0], [-a
+ a
* 0.2, b
, 0.0],
258 [a
- a
* 0.2, b
, 0.0], [a
- a
* 0.05, b
- b
* 0.05, 0.0], [a
, b
- b
* 0.2, 0.0],
259 [a
, -b
+ b
* 0.2, 0.0], [a
- a
* 0.05, -b
+ b
* 0.05, 0.0], [a
- a
* 0.2, -b
, 0.0],
260 [-a
+ a
* 0.2, -b
, 0.0], [-a
+ a
* 0.05, -b
+ b
* 0.05, 0.0], [-a
, -b
+ b
* 0.2, 0.0]
263 # Rounded Rectangle II:
273 newpoints
.append([-x
+ r
, y
, 0])
274 newpoints
.append([x
- r
, y
, 0])
275 newpoints
.append([x
, y
- r
, 0])
276 newpoints
.append([x
, -y
+ r
, 0])
277 newpoints
.append([x
- r
, -y
, 0])
278 newpoints
.append([-x
+ r
, -y
, 0])
279 newpoints
.append([-x
, -y
+ r
, 0])
280 newpoints
.append([-x
, y
- r
, 0])
282 newpoints
.append([-x
, y
, 0])
283 newpoints
.append([x
, y
, 0])
284 newpoints
.append([x
, -y
, 0])
285 newpoints
.append([-x
, -y
, 0])
288 newpoints
= [[-a
, b
, 0.0], [a
, b
, 0.0], [a
, -b
, 0.0], [-a
, -b
, 0.0]]
292 # ------------------------------------------------------------
294 def StarCurve(starpoints
=8, innerradius
=0.5, outerradius
=1.0, twist
=0.0):
296 StarCurve( starpoints=8, innerradius=0.5, outerradius=1.0, twist=0.0 )
298 Create star shaped curve
301 starpoints - the number of points
303 innerradius - innerradius
305 outerradius - outerradius
310 a list with lists of x,y,z coordinates for curve points, [[x,y,z],[x,y,z],...n]
315 step
= 2.0 / starpoints
317 while i
< starpoints
:
319 x1
= cos(t
* pi
) * outerradius
320 y1
= sin(t
* pi
) * outerradius
321 newpoints
.append([x1
, y1
, 0])
322 x2
= cos(t
* pi
+ (pi
/ starpoints
+ twist
)) * innerradius
323 y2
= sin(t
* pi
+ (pi
/ starpoints
+ twist
)) * innerradius
324 newpoints
.append([x2
, y2
, 0])
329 # ------------------------------------------------------------
331 def FlowerCurve(petals
=8, innerradius
=0.5, outerradius
=1.0, petalwidth
=2.0):
333 FlowerCurve( petals=8, innerradius=0.5, outerradius=1.0, petalwidth=2.0 )
335 Create flower shaped curve
338 petals - the number of petals
340 innerradius - innerradius
342 outerradius - outerradius
344 petalwidth - width of petals
347 a list with lists of x,y,z coordinates for curve points, [[x,y,z],[x,y,z],...n]
353 pet
= (step
/ pi
* 2) * petalwidth
357 x1
= cos(t
* pi
- (pi
/ petals
)) * innerradius
358 y1
= sin(t
* pi
- (pi
/ petals
)) * innerradius
359 newpoints
.append([x1
, y1
, 0])
360 x2
= cos(t
* pi
- pet
) * outerradius
361 y2
= sin(t
* pi
- pet
) * outerradius
362 newpoints
.append([x2
, y2
, 0])
363 x3
= cos(t
* pi
+ pet
) * outerradius
364 y3
= sin(t
* pi
+ pet
) * outerradius
365 newpoints
.append([x3
, y3
, 0])
370 # ------------------------------------------------------------
371 # 2DCurve: Arc,Sector,Segment,Ring:
372 def ArcCurve(sides
=6, startangle
=0.0, endangle
=90.0, innerradius
=0.5, outerradius
=1.0, type=3):
374 ArcCurve( sides=6, startangle=0.0, endangle=90.0, innerradius=0.5, outerradius=1.0, type=3 )
376 Create arc shaped curve
379 sides - number of sides
381 startangle - startangle
385 innerradius - innerradius
387 outerradius - outerradius
389 type - select type Arc,Sector,Segment,Ring
392 a list with lists of x,y,z coordinates for curve points, [[x,y,z],[x,y,z],...n]
398 angle
= 2.0 * (1.0 / 360.0)
399 endangle
-= startangle
400 step
= (angle
* endangle
) / (sides
- 1)
403 t
= (i
* step
) + angle
* startangle
404 x1
= sin(t
* pi
) * outerradius
405 y1
= cos(t
* pi
) * outerradius
406 newpoints
.append([x1
, y1
, 0])
410 # Arc: turn cyclic curve flag off!
414 newpoints
.append([0, 0, 0])
419 t
= (j
* step
) + angle
* startangle
420 x2
= sin(t
* pi
) * innerradius
421 y2
= cos(t
* pi
) * innerradius
422 newpoints
.append([x2
, y2
, 0])
427 # ------------------------------------------------------------
428 # 2DCurve: Cog wheel:
429 def CogCurve(theeth
=8, innerradius
=0.8, middleradius
=0.95, outerradius
=1.0, bevel
=0.5):
431 CogCurve( theeth=8, innerradius=0.8, middleradius=0.95, outerradius=1.0, bevel=0.5 )
433 Create cog wheel shaped curve
436 theeth - number of theeth
438 innerradius - innerradius
440 middleradius - middleradius
442 outerradius - outerradius
447 a list with lists of x,y,z coordinates for curve points, [[x,y,z],[x,y,z],...n]
458 x1
= cos(t
* pi
- (pi
/ theeth
) - pet
) * innerradius
459 y1
= sin(t
* pi
- (pi
/ theeth
) - pet
) * innerradius
460 newpoints
.append([x1
, y1
, 0])
461 x2
= cos(t
* pi
- (pi
/ theeth
) + pet
) * innerradius
462 y2
= sin(t
* pi
- (pi
/ theeth
) + pet
) * innerradius
463 newpoints
.append([x2
, y2
, 0])
464 x3
= cos(t
* pi
- pet
) * middleradius
465 y3
= sin(t
* pi
- pet
) * middleradius
466 newpoints
.append([x3
, y3
, 0])
467 x4
= cos(t
* pi
- (pet
* bevel
)) * outerradius
468 y4
= sin(t
* pi
- (pet
* bevel
)) * outerradius
469 newpoints
.append([x4
, y4
, 0])
470 x5
= cos(t
* pi
+ (pet
* bevel
)) * outerradius
471 y5
= sin(t
* pi
+ (pet
* bevel
)) * outerradius
472 newpoints
.append([x5
, y5
, 0])
473 x6
= cos(t
* pi
+ pet
) * middleradius
474 y6
= sin(t
* pi
+ pet
) * middleradius
475 newpoints
.append([x6
, y6
, 0])
480 # ------------------------------------------------------------
482 def nSideCurve(sides
=6, radius
=1.0):
484 nSideCurve( sides=6, radius=1.0 )
489 sides - number of sides
494 a list with lists of x,y,z coordinates for curve points, [[x,y,z],[x,y,z],...n]
503 x
= sin(t
* pi
) * radius
504 y
= cos(t
* pi
) * radius
505 newpoints
.append([x
, y
, 0])
510 # ------------------------------------------------------------
512 def SplatCurve(sides
=24, scale
=1.0, seed
=0, basis
=0, radius
=1.0):
514 SplatCurve( sides=24, scale=1.0, seed=0, basis=0, radius=1.0 )
519 sides - number of sides
523 seed - noise random seed
530 a list with lists of x,y,z coordinates for curve points, [[x,y,z],[x,y,z],...n]
539 turb
= vTurbNoise(t
, t
, t
, 1.0, scale
, 6, False, basis
, seed
)
540 turb
= turb
[2] * 0.5 + 0.5
541 x
= sin(t
* pi
) * radius
* turb
542 y
= cos(t
* pi
) * radius
* turb
543 newpoints
.append([x
, y
, 0])
548 # -----------------------------------------------------------
550 def CycloidCurve(number
=100, type=0, R
=4.0, r
=1.0, d
=1.0):
552 CycloidCurve( number=100, type=0, a=4.0, b=1.0 )
554 Create a Cycloid, Hypotrochoid / Hypocycloid or Epitrochoid / Epycycloid type of curve
557 number - the number of points
559 type - types: Cycloid, Hypocycloid, Epicycloid
561 R = Radius a scaling parameter
563 r = Radius b scaling parameter
565 d = Distance scaling parameter
568 a list with lists of x,y,z coordinates for curve points, [[x,y,z],[x,y,z],...n]
575 step
= 2.0 / (number
- 1)
578 # Hypotrochoid / Hypocycloid
581 x
= ((a
- b
) * cos(t
* pi
)) + (d
* cos(((a
+ b
) / b
) * t
* pi
))
582 y
= ((a
- b
) * sin(t
* pi
)) - (d
* sin(((a
+ b
) / b
) * t
* pi
))
584 newpoints
.append([x
, y
, z
])
587 # Epitrochoid / Epycycloid
590 x
= ((a
+ b
) * cos(t
* pi
)) - (d
* cos(((a
+ b
) / b
) * t
* pi
))
591 y
= ((a
+ b
) * sin(t
* pi
)) - (d
* sin(((a
+ b
) / b
) * t
* pi
))
593 newpoints
.append([x
, y
, z
])
599 x
= (t
- sin(t
) * b
) * a
/ pi
600 y
= (1 - cos(t
) * b
) * a
/ pi
602 newpoints
.append([x
, y
, z
])
607 # -----------------------------------------------------------
608 # 3D curve shape functions:
609 # -----------------------------------------------------------
611 # ------------------------------------------------------------
613 def HelixCurve(number
=100, height
=2.0, startangle
=0.0, endangle
=360.0, width
=1.0, a
=0.0, b
=0.0):
615 HelixCurve( number=100, height=2.0, startangle=0.0, endangle=360.0, width=1.0, a=0.0, b=0.0 )
620 number - the number of points
624 startangle - startangle
635 a list with lists of x,y,z coordinates for curve points, [[x,y,z],[x,y,z],...n]
640 angle
= (2.0 / 360.0) * (endangle
- startangle
)
641 step
= angle
/ (number
- 1)
643 start
= startangle
* 2.0 / 360.0
647 t
= (i
* step
+ start
)
648 x
= sin((t
* pi
)) * (1.0 + cos(t
* pi
* a
- (b
* pi
))) * (0.25 * width
)
649 y
= cos((t
* pi
)) * (1.0 + cos(t
* pi
* a
- (b
* pi
))) * (0.25 * width
)
650 z
= (t
* h
) - h
* start
651 newpoints
.append([x
, y
, z
])
656 # -----------------------------------------------------------
658 def NoiseCurve(type=0, number
=100, length
=2.0, size
=0.5,
659 scale
=[0.5, 0.5, 0.5], octaves
=2, basis
=0, seed
=0):
664 number - number of points
666 length - curve length
670 scale - noise intensity scale x,y,z
674 seed - noise random seed
676 type - noise curve type
679 a list with lists of x,y,z coordinates for curve points, [[x,y,z],[x,y,z],...n]
684 step
= (length
/ number
)
690 v
= vTurbNoise(t
, t
, t
, 1.0, size
, octaves
, False, basis
, seed
)
691 x
= sin(t
* pi
) + (v
[0] * scale
[0])
692 y
= cos(t
* pi
) + (v
[1] * scale
[1])
694 newpoints
.append([x
, y
, z
])
700 v
= vTurbNoise(t
, t
, t
, 1.0, 1.0, octaves
, False, basis
, seed
)
701 x
= v
[0] * scale
[0] * size
702 y
= v
[1] * scale
[1] * size
703 z
= v
[2] * scale
[2] * size
704 newpoints
.append([x
, y
, z
])
710 v
= vTurbNoise(t
, t
, t
, 1.0, size
, octaves
, False, basis
, seed
)
711 x
= t
+ v
[0] * scale
[0]
714 newpoints
.append([x
, y
, z
])
719 # get array of vertcoordinates according to splinetype
720 def vertsToPoints(Verts
, splineType
):
725 # array for BEZIER spline output (V3)
726 if splineType
== 'BEZIER':
730 # array for nonBEZIER output (V4)
734 if splineType
== 'NURBS':
743 # create new CurveObject from vertarray and splineType
744 def createCurve(context
, vertArray
, self
):
745 # output splineType 'POLY' 'NURBS' 'BEZIER'
746 splineType
= self
.outputType
748 # GalloreType as name
749 name
= self
.ProfileType
752 if bpy
.context
.mode
== 'EDIT_CURVE':
753 Curve
= context
.active_object
754 newSpline
= Curve
.data
.splines
.new(type=splineType
) # spline
757 dataCurve
= bpy
.data
.curves
.new(name
, type='CURVE') # curve data block
758 newSpline
= dataCurve
.splines
.new(type=splineType
) # spline
760 # create object with newCurve
761 Curve
= object_utils
.object_data_add(context
, dataCurve
, operator
=self
) # place in active scene
763 # set newSpline Options
764 newSpline
.use_cyclic_u
= self
.use_cyclic_u
765 newSpline
.use_endpoint_u
= self
.endp_u
766 newSpline
.order_u
= self
.order_u
769 Curve
.data
.dimensions
= self
.shape
770 Curve
.data
.use_path
= True
771 if self
.shape
== '3D':
772 Curve
.data
.fill_mode
= 'FULL'
774 Curve
.data
.fill_mode
= 'BOTH'
776 for spline
in Curve
.data
.splines
:
777 if spline
.type == 'BEZIER':
778 for point
in spline
.bezier_points
:
779 point
.select_control_point
= False
780 point
.select_left_handle
= False
781 point
.select_right_handle
= False
783 for point
in spline
.points
:
786 # create spline from vertarray
787 if splineType
== 'BEZIER':
788 newSpline
.bezier_points
.add(int(len(vertArray
) * 0.33))
789 newSpline
.bezier_points
.foreach_set('co', vertArray
)
790 for point
in newSpline
.bezier_points
:
791 point
.handle_right_type
= self
.handleType
792 point
.handle_left_type
= self
.handleType
793 point
.select_control_point
= True
794 point
.select_left_handle
= True
795 point
.select_right_handle
= True
797 newSpline
.points
.add(int(len(vertArray
) * 0.25 - 1))
798 newSpline
.points
.foreach_set('co', vertArray
)
799 newSpline
.use_endpoint_u
= True
800 for point
in newSpline
.points
:
803 # move and rotate spline in edit mode
804 if bpy
.context
.mode
== 'EDIT_CURVE':
805 if self
.align
== "WORLD":
806 location
= self
.location
- context
.active_object
.location
807 bpy
.ops
.transform
.translate(value
= location
, orient_type
='GLOBAL')
808 bpy
.ops
.transform
.rotate(value
= self
.rotation
[0], orient_axis
= 'X', orient_type
='GLOBAL')
809 bpy
.ops
.transform
.rotate(value
= self
.rotation
[1], orient_axis
= 'Y', orient_type
='GLOBAL')
810 bpy
.ops
.transform
.rotate(value
= self
.rotation
[2], orient_axis
= 'Z', orient_type
='GLOBAL')
812 elif self
.align
== "VIEW":
813 bpy
.ops
.transform
.translate(value
= self
.location
)
814 bpy
.ops
.transform
.rotate(value
= self
.rotation
[0], orient_axis
= 'X')
815 bpy
.ops
.transform
.rotate(value
= self
.rotation
[1], orient_axis
= 'Y')
816 bpy
.ops
.transform
.rotate(value
= self
.rotation
[2], orient_axis
= 'Z')
818 elif self
.align
== "CURSOR":
819 location
= context
.active_object
.location
820 self
.location
= bpy
.context
.scene
.cursor
.location
- location
821 self
.rotation
= bpy
.context
.scene
.cursor
.rotation_euler
823 bpy
.ops
.transform
.translate(value
= self
.location
)
824 bpy
.ops
.transform
.rotate(value
= self
.rotation
[0], orient_axis
= 'X')
825 bpy
.ops
.transform
.rotate(value
= self
.rotation
[1], orient_axis
= 'Y')
826 bpy
.ops
.transform
.rotate(value
= self
.rotation
[2], orient_axis
= 'Z')
831 # ------------------------------------------------------------
833 def main(context
, self
):
835 proType
= self
.ProfileType
836 splineType
= self
.outputType
837 innerRadius
= self
.innerRadius
838 middleRadius
= self
.middleRadius
839 outerRadius
= self
.outerRadius
842 if proType
== 'Profile':
843 verts
= ProfileCurve(
844 self
.ProfileCurveType
,
845 self
.ProfileCurvevar1
,
846 self
.ProfileCurvevar2
848 if proType
== 'Arrow':
854 if proType
== 'Rectangle':
861 if proType
== 'Flower':
868 if proType
== 'Star':
884 if proType
== 'Cogwheel':
892 if proType
== 'Nsided':
897 if proType
== 'Splat':
905 if proType
== 'Cycloid':
906 verts
= CycloidCurve(
913 if proType
== 'Helix':
923 if proType
== 'Noise':
929 [self
.noiseScaleX
, self
.noiseScaleY
, self
.noiseScaleZ
],
935 # turn verts into array
936 vertArray
= vertsToPoints(verts
, splineType
)
939 createCurve(context
, vertArray
, self
)
944 class Curveaceous_galore(Operator
, object_utils
.AddObjectHelper
):
945 bl_idname
= "curve.curveaceous_galore"
946 bl_label
= "Curve Profiles"
947 bl_description
= "Construct many types of curves"
948 bl_options
= {'REGISTER', 'UNDO', 'PRESET'}
951 ProfileType
: EnumProperty(
953 description
="Form of Curve to create",
955 ('Arc', "Arc", "Arc"),
956 ('Arrow', "Arrow", "Arrow"),
957 ('Cogwheel', "Cogwheel", "Cogwheel"),
958 ('Cycloid', "Cycloid", "Cycloid"),
959 ('Flower', "Flower", "Flower"),
960 ('Helix', "Helix (3D)", "Helix"),
961 ('Noise', "Noise (3D)", "Noise"),
962 ('Nsided', "Nsided", "Nsided"),
963 ('Profile', "Profile", "Profile"),
964 ('Rectangle', "Rectangle", "Rectangle"),
965 ('Splat', "Splat", "Splat"),
966 ('Star', "Star", "Star")]
968 outputType
: EnumProperty(
969 name
="Output splines",
970 description
="Type of splines to output",
972 ('POLY', "Poly", "Poly Spline type"),
973 ('NURBS', "Nurbs", "Nurbs Spline type"),
974 ('BEZIER', "Bezier", "Bezier Spline type")]
977 shape
: EnumProperty(
979 description
="2D or 3D Curve",
985 use_cyclic_u
: BoolProperty(
988 description
="make curve closed"
990 endp_u
: BoolProperty(
991 name
="Use endpoint u",
993 description
="stretch to endpoints"
995 order_u
: IntProperty(
1000 description
="Order of nurbs spline"
1002 handleType
: EnumProperty(
1005 description
="Bezier handles type",
1007 ('VECTOR', "Vector", "Vector type Bezier handles"),
1008 ('AUTO', "Auto", "Automatic type Bezier handles")]
1010 # ProfileCurve properties
1011 ProfileCurveType
: IntProperty(
1016 description
="Type of Curve's Profile"
1018 ProfileCurvevar1
: FloatProperty(
1021 description
="Variable 1 of Curve's Profile"
1023 ProfileCurvevar2
: FloatProperty(
1026 description
="Variable 2 of Curve's Profile"
1028 # Arrow, Rectangle, MiscCurve properties
1029 MiscCurveType
: IntProperty(
1034 description
="Type of Curve"
1036 MiscCurvevar1
: FloatProperty(
1039 description
="Variable 1 of Curve"
1041 MiscCurvevar2
: FloatProperty(
1044 description
="Variable 2 of Curve"
1046 MiscCurvevar3
: FloatProperty(
1050 description
="Variable 3 of Curve"
1053 innerRadius
: FloatProperty(
1054 name
="Inner radius",
1057 description
="Inner radius"
1059 middleRadius
: FloatProperty(
1060 name
="Middle radius",
1063 description
="Middle radius"
1065 outerRadius
: FloatProperty(
1066 name
="Outer radius",
1069 description
="Outer radius"
1072 petals
: IntProperty(
1076 description
="Number of petals"
1078 petalWidth
: FloatProperty(
1082 description
="Petal width"
1085 starPoints
: IntProperty(
1089 description
="Number of star points"
1091 starTwist
: FloatProperty(
1097 arcSides
: IntProperty(
1101 description
="Sides of arc"
1103 startAngle
: FloatProperty(
1106 description
="Start angle"
1108 endAngle
: FloatProperty(
1111 description
="End angle"
1113 arcType
: IntProperty(
1118 description
="Sides of arc"
1120 # Cogwheel properties
1121 teeth
: IntProperty(
1125 description
="number of teeth"
1127 bevel
: FloatProperty(
1135 Nsides
: IntProperty(
1139 description
="Number of sides"
1142 splatSides
: IntProperty(
1146 description
="Splat sides"
1148 splatScale
: FloatProperty(
1152 description
="Splat scale"
1160 basis
: IntProperty(
1168 helixPoints
: IntProperty(
1172 description
="Resolution"
1174 helixHeight
: FloatProperty(
1178 description
="Helix height"
1180 helixStart
: FloatProperty(
1183 description
="Helix start angle"
1185 helixEnd
: FloatProperty(
1188 description
="Helix end angle"
1190 helixWidth
: FloatProperty(
1193 description
="Helix width"
1195 helix_a
: FloatProperty(
1198 description
="Helix Variable 1"
1200 helix_b
: FloatProperty(
1203 description
="Helix Variable 2"
1205 # Cycloid properties
1206 cycloPoints
: IntProperty(
1211 description
="Resolution"
1213 cycloType
: IntProperty(
1218 description
="Type: Cycloid , Hypocycloid / Hypotrochoid , Epicycloid / Epitrochoid"
1220 cyclo_a
: FloatProperty(
1224 description
="Cycloid: R radius a"
1226 cyclo_b
: FloatProperty(
1230 description
="Cycloid: r radius b"
1232 cyclo_d
: FloatProperty(
1235 description
="Cycloid: d distance"
1238 noiseType
: IntProperty(
1243 description
="Noise curve type: Linear, Circular or Knot"
1245 noisePoints
: IntProperty(
1249 description
="Resolution"
1251 noiseLength
: FloatProperty(
1255 description
="Curve Length"
1257 noiseSize
: FloatProperty(
1261 description
="Noise size"
1263 noiseScaleX
: FloatProperty(
1267 description
="Noise x"
1269 noiseScaleY
: FloatProperty(
1273 description
="Noise y"
1275 noiseScaleZ
: FloatProperty(
1279 description
="Noise z"
1281 noiseOctaves
: IntProperty(
1288 noiseBasis
: IntProperty(
1295 noiseSeed
: IntProperty(
1299 description
="Random Seed"
1302 edit_mode
: BoolProperty(
1303 name
="Show in edit mode",
1305 description
="Show in edit mode"
1308 def draw(self
, context
):
1309 layout
= self
.layout
1312 col
= layout
.column()
1313 col
.prop(self
, 'ProfileType')
1314 col
.label(text
=self
.ProfileType
+ " Options:")
1316 # options per ProfileType
1318 col
= box
.column(align
=True)
1320 if self
.ProfileType
== 'Profile':
1321 col
.prop(self
, "ProfileCurveType")
1322 col
.prop(self
, "ProfileCurvevar1")
1323 col
.prop(self
, "ProfileCurvevar2")
1325 elif self
.ProfileType
== 'Arrow':
1326 col
.prop(self
, "MiscCurveType")
1327 col
.prop(self
, "MiscCurvevar1", text
="Height")
1328 col
.prop(self
, "MiscCurvevar2", text
="Width")
1330 elif self
.ProfileType
== 'Rectangle':
1331 col
.prop(self
, "MiscCurveType")
1332 col
.prop(self
, "MiscCurvevar1", text
="Width")
1333 col
.prop(self
, "MiscCurvevar2", text
="Height")
1334 if self
.MiscCurveType
== 2:
1335 col
.prop(self
, "MiscCurvevar3", text
="Corners")
1337 elif self
.ProfileType
== 'Flower':
1338 col
.prop(self
, "petals")
1339 col
.prop(self
, "petalWidth")
1341 col
= box
.column(align
=True)
1342 col
.prop(self
, "innerRadius")
1343 col
.prop(self
, "outerRadius")
1345 elif self
.ProfileType
== 'Star':
1346 col
.prop(self
, "starPoints")
1347 col
.prop(self
, "starTwist")
1349 col
= box
.column(align
=True)
1350 col
.prop(self
, "innerRadius")
1351 col
.prop(self
, "outerRadius")
1353 elif self
.ProfileType
== 'Arc':
1354 col
.prop(self
, "arcType")
1355 col
.prop(self
, "arcSides")
1357 col
= box
.column(align
=True)
1358 col
.prop(self
, "startAngle")
1359 col
.prop(self
, "endAngle")
1361 col
= box
.column(align
=True)
1362 col
.prop(self
, "innerRadius")
1363 col
.prop(self
, "outerRadius")
1365 elif self
.ProfileType
== 'Cogwheel':
1366 col
.prop(self
, "teeth")
1367 col
.prop(self
, "bevel")
1369 col
= box
.column(align
=True)
1370 col
.prop(self
, "innerRadius")
1371 col
.prop(self
, "middleRadius")
1372 col
.prop(self
, "outerRadius")
1374 elif self
.ProfileType
== 'Nsided':
1375 col
.prop(self
, "Nsides")
1376 col
.prop(self
, "outerRadius")
1378 elif self
.ProfileType
== 'Splat':
1379 col
.prop(self
, "splatSides")
1380 col
.prop(self
, "outerRadius")
1382 col
= box
.column(align
=True)
1383 col
.prop(self
, "splatScale")
1384 col
.prop(self
, "seed")
1385 col
.prop(self
, "basis")
1387 elif self
.ProfileType
== 'Cycloid':
1388 col
.prop(self
, "cycloType")
1389 col
.prop(self
, "cycloPoints")
1391 col
= box
.column(align
=True)
1392 col
.prop(self
, "cyclo_a")
1393 col
.prop(self
, "cyclo_b")
1394 if self
.cycloType
!= 0:
1395 col
.prop(self
, "cyclo_d")
1397 elif self
.ProfileType
== 'Helix':
1398 col
.prop(self
, "helixPoints")
1399 col
.prop(self
, "helixHeight")
1400 col
.prop(self
, "helixWidth")
1402 col
= box
.column(align
=True)
1403 col
.prop(self
, "helixStart")
1404 col
.prop(self
, "helixEnd")
1406 col
= box
.column(align
=True)
1407 col
.prop(self
, "helix_a")
1408 col
.prop(self
, "helix_b")
1410 elif self
.ProfileType
== 'Noise':
1411 col
.prop(self
, "noiseType")
1412 col
.prop(self
, "noisePoints")
1413 col
.prop(self
, "noiseLength")
1415 col
= box
.column(align
=True)
1416 col
.prop(self
, "noiseSize")
1417 col
.prop(self
, "noiseScaleX")
1418 col
.prop(self
, "noiseScaleY")
1419 col
.prop(self
, "noiseScaleZ")
1421 col
= box
.column(align
=True)
1422 col
.prop(self
, "noiseOctaves")
1423 col
.prop(self
, "noiseBasis")
1424 col
.prop(self
, "noiseSeed")
1427 row
.prop(self
, "shape", expand
=True)
1430 col
= layout
.column()
1431 col
.label(text
="Output Curve Type:")
1432 col
.row().prop(self
, "outputType", expand
=True)
1434 if self
.outputType
== 'NURBS':
1435 col
.prop(self
, 'order_u')
1436 elif self
.outputType
== 'BEZIER':
1437 col
.row().prop(self
, 'handleType', expand
=True)
1439 col
= layout
.column()
1440 col
.row().prop(self
, "use_cyclic_u", expand
=True)
1442 col
= layout
.column()
1443 col
.row().prop(self
, "edit_mode", expand
=True)
1445 col
= layout
.column()
1446 # AddObjectHelper props
1447 col
.prop(self
, "align")
1448 col
.prop(self
, "location")
1449 col
.prop(self
, "rotation")
1452 def poll(cls
, context
):
1453 return context
.scene
is not None
1455 def execute(self
, context
):
1456 # turn off 'Enter Edit Mode'
1457 use_enter_edit_mode
= bpy
.context
.preferences
.edit
.use_enter_edit_mode
1458 bpy
.context
.preferences
.edit
.use_enter_edit_mode
= False
1463 if use_enter_edit_mode
:
1464 bpy
.ops
.object.mode_set(mode
= 'EDIT')
1466 # restore pre operator state
1467 bpy
.context
.preferences
.edit
.use_enter_edit_mode
= use_enter_edit_mode
1470 bpy
.ops
.object.mode_set(mode
= 'EDIT')
1472 bpy
.ops
.object.mode_set(mode
= 'OBJECT')
1476 def invoke(self
, context
, event
):
1477 # deal with 2D - 3D curve differences
1478 if self
.ProfileType
in ['Helix', 'Cycloid', 'Noise']:
1483 if self
.ProfileType
in ['Helix', 'Noise', 'Cycloid']:
1484 self
.use_cyclic_u
= False
1485 if self
.ProfileType
in ['Cycloid']:
1486 if self
.cycloType
== 0:
1487 self
.use_cyclic_u
= False
1489 self
.use_cyclic_u
= True
1491 if self
.ProfileType
== 'Arc' and self
.arcType
== 1:
1492 self
.use_cyclic_u
= False
1494 self
.use_cyclic_u
= True
1496 self
.execute(context
)
1506 from bpy
.utils
import register_class
1511 from bpy
.utils
import unregister_class
1512 for cls
in reversed(classes
):
1513 unregister_class(cls
)
1515 if __name__
== "__main__":