FBX: reformat props.
[blender-addons.git] / add_mesh_extra_objects / add_mesh_gears.py
blobd657fcfbac2421ec30d99f15b4b79de476499204
1 # add_mesh_gear.py (c) 2009, 2010 Michel J. Anders (varkenvarken)
3 # ***** BEGIN GPL LICENSE BLOCK *****
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU General Public License
8 # as published by the Free Software Foundation; either version 2
9 # of the License, or (at your option) any later version.
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software Foundation,
18 # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 # ***** END GPL LICENCE BLOCK *****
21 '''
22 bl_info = {
23 "name": "Gears",
24 "author": "Michel J. Anders (varkenvarken)",
25 "version": (2, 4, 2),
26 "blender": (2, 57, 0),
27 "location": "View3D > Add > Mesh > Gears ",
28 "description": "Adds a mesh Gear to the Add Mesh menu",
29 "warning": "",
30 "wiki_url": "http://wiki.blender.org/index.php/Extensions:2.5/Py/"
31 "Scripts/Add_Mesh/Add_Gear",
32 "category": "Add Mesh",
34 '''
36 import bpy
37 from math import *
38 from bpy.props import *
40 # Create a new mesh (object) from verts/edges/faces.
41 # verts/edges/faces ... List of vertices/edges/faces for the
42 # new mesh (as used in from_pydata).
43 # name ... Name of the new mesh (& object).
44 def create_mesh_object(context, verts, edges, faces, name):
45 # Create new mesh
46 mesh = bpy.data.meshes.new(name)
48 # Make a mesh from a list of verts/edges/faces.
49 mesh.from_pydata(verts, edges, faces)
51 # Update mesh geometry after adding stuff.
52 mesh.update()
54 from bpy_extras import object_utils
55 return object_utils.object_data_add(context, mesh, operator=None)
58 # A very simple "bridge" tool.
59 # Connects two equally long vertex rows with faces.
60 # Returns a list of the new faces (list of lists)
62 # vertIdx1 ... First vertex list (list of vertex indices).
63 # vertIdx2 ... Second vertex list (list of vertex indices).
64 # closed ... Creates a loop (first & last are closed).
65 # flipped ... Invert the normal of the face(s).
67 # Note: You can set vertIdx1 to a single vertex index to create
68 # a fan/star of faces.
69 # Note: If both vertex idx list are the same length they have
70 # to have at least 2 vertices.
71 def createFaces(vertIdx1, vertIdx2, closed=False, flipped=False):
72 faces = []
74 if not vertIdx1 or not vertIdx2:
75 return None
77 if len(vertIdx1) < 2 and len(vertIdx2) < 2:
78 return None
80 fan = False
81 if (len(vertIdx1) != len(vertIdx2)):
82 if (len(vertIdx1) == 1 and len(vertIdx2) > 1):
83 fan = True
84 else:
85 return None
87 total = len(vertIdx2)
89 if closed:
90 # Bridge the start with the end.
91 if flipped:
92 face = [
93 vertIdx1[0],
94 vertIdx2[0],
95 vertIdx2[total - 1]]
96 if not fan:
97 face.append(vertIdx1[total - 1])
98 faces.append(face)
100 else:
101 face = [vertIdx2[0], vertIdx1[0]]
102 if not fan:
103 face.append(vertIdx1[total - 1])
104 face.append(vertIdx2[total - 1])
105 faces.append(face)
107 # Bridge the rest of the faces.
108 for num in range(total - 1):
109 if flipped:
110 if fan:
111 face = [vertIdx2[num], vertIdx1[0], vertIdx2[num + 1]]
112 else:
113 face = [vertIdx2[num], vertIdx1[num],
114 vertIdx1[num + 1], vertIdx2[num + 1]]
115 faces.append(face)
116 else:
117 if fan:
118 face = [vertIdx1[0], vertIdx2[num], vertIdx2[num + 1]]
119 else:
120 face = [vertIdx1[num], vertIdx2[num],
121 vertIdx2[num + 1], vertIdx1[num + 1]]
122 faces.append(face)
124 return faces
127 # Calculate the vertex coordinates for a single
128 # section of a gear tooth.
129 # Returns 4 lists of vertex coords (list of tuples):
130 # *-*---*---* (1.) verts_inner_base
131 # | | | |
132 # *-*---*---* (2.) verts_outer_base
133 # | | |
134 # *---*---* (3.) verts_middle_tooth
135 # \ | /
136 # *-*-* (4.) verts_tip_tooth
141 # radius
142 # Ad
143 # De
144 # base
145 # p_angle
146 # rack
147 # crown
148 def add_tooth(a, t, d, radius, Ad, De, base, p_angle, rack=0, crown=0.0):
149 A = [a, a + t / 4, a + t / 2, a + 3 * t / 4]
150 C = [cos(i) for i in A]
151 S = [sin(i) for i in A]
153 Ra = radius + Ad
154 Rd = radius - De
155 Rb = Rd - base
157 # Pressure angle calc
158 O = Ad * tan(p_angle)
159 p_angle = atan(O / Ra)
161 if radius < 0:
162 p_angle = -p_angle
164 if rack:
165 S = [sin(t / 4) * I for I in range(-2, 3)]
166 Sp = [0, sin(-t / 4 + p_angle), 0, sin(t / 4 - p_angle)]
168 verts_inner_base = [(Rb, radius * S[I], d) for I in range(4)]
169 verts_outer_base = [(Rd, radius * S[I], d) for I in range(4)]
170 verts_middle_tooth = [(radius, radius * S[I], d) for I in range(1, 4)]
171 verts_tip_tooth = [(Ra, radius * Sp[I], d) for I in range(1, 4)]
173 else:
174 Cp = [
176 cos(a + t / 4 + p_angle),
177 cos(a + t / 2),
178 cos(a + 3 * t / 4 - p_angle)]
179 Sp = [0,
180 sin(a + t / 4 + p_angle),
181 sin(a + t / 2),
182 sin(a + 3 * t / 4 - p_angle)]
184 verts_inner_base = [(Rb * C[I], Rb * S[I], d)
185 for I in range(4)]
186 verts_outer_base = [(Rd * C[I], Rd * S[I], d)
187 for I in range(4)]
188 verts_middle_tooth = [(radius * C[I], radius * S[I], d + crown / 3)
189 for I in range(1, 4)]
190 verts_tip_tooth = [(Ra * Cp[I], Ra * Sp[I], d + crown)
191 for I in range(1, 4)]
193 return (verts_inner_base, verts_outer_base,
194 verts_middle_tooth, verts_tip_tooth)
197 # EXPERIMENTAL Calculate the vertex coordinates for a single
198 # section of a gearspoke.
199 # Returns them as a list of tuples.
204 # radius
205 # De
206 # base
210 # gap
211 # width
213 # @todo Finish this.
214 def add_spoke(a, t, d, radius, De, base, s, w, l, gap=0, width=19):
215 Rd = radius - De
216 Rb = Rd - base
217 # Rl = Rb # UNUSED
219 verts = []
220 edgefaces = []
221 edgefaces2 = []
222 sf = []
224 if not gap:
225 for N in range(width, 1, -2):
226 edgefaces.append(len(verts))
227 ts = t / 4
228 tm = a + 2 * ts
229 te = asin(w / Rb)
230 td = te - ts
231 t4 = ts + td * (width - N) / (width - 3.0)
232 A = [tm + (i - int(N / 2)) * t4 for i in range(N)]
233 C = [cos(i) for i in A]
234 S = [sin(i) for i in A]
236 verts.extend((Rb * I, Rb * J, d) for (I, J) in zip(C, S))
237 edgefaces2.append(len(verts) - 1)
239 Rb = Rb - s
241 n = 0
242 for N in range(width, 3, -2):
243 sf.extend([(i + n, i + 1 + n, i + 2 + n, i + N + n)
244 for i in range(0, N - 1, 2)])
245 sf.extend([(i + 2 + n, i + N + n, i + N + 1 + n, i + N + 2 + n)
246 for i in range(0, N - 3, 2)])
248 n = n + N
250 return verts, edgefaces, edgefaces2, sf
253 # Create gear geometry.
254 # Returns:
255 # * A list of vertices (list of tuples)
256 # * A list of faces (list of lists)
257 # * A list (group) of vertices of the tip (list of vertex indices).
258 # * A list (group) of vertices of the valley (list of vertex indices).
260 # teethNum ... Number of teeth on the gear.
261 # radius ... Radius of the gear, negative for crown gear
262 # Ad ... Addendum, extent of tooth above radius.
263 # De ... Dedendum, extent of tooth below radius.
264 # base ... Base, extent of gear below radius.
265 # p_angle ... Pressure angle. Skewness of tooth tip. (radiant)
266 # width ... Width, thickness of gear.
267 # skew ... Skew of teeth. (radiant)
268 # conangle ... Conical angle of gear. (radiant)
269 # rack
270 # crown ... Inward pointing extend of crown teeth.
272 # inner radius = radius - (De + base)
273 def add_gear(teethNum, radius, Ad, De, base, p_angle,
274 width=1, skew=0, conangle=0, rack=0, crown=0.0):
276 if teethNum < 2:
277 return None, None, None, None
279 t = 2 * pi / teethNum
281 if rack:
282 teethNum = 1
284 print(radius, width, conangle)
285 scale = (radius - 2 * width * tan(conangle)) / radius
287 verts = []
288 faces = []
289 vgroup_top = [] # Vertex group of top/tip? vertices.
290 vgroup_valley = [] # Vertex group of valley vertices
292 verts_bridge_prev = []
293 for toothCnt in range(teethNum):
294 a = toothCnt * t
296 verts_bridge_start = []
297 verts_bridge_end = []
299 verts_outside_top = []
300 verts_outside_bottom = []
301 for (s, d, c, top) \
302 in [(0, -width, 1, True), \
303 (skew, width, scale, False)]:
305 verts1, verts2, verts3, verts4 = add_tooth(a + s, t, d,
306 radius * c, Ad * c, De * c, base * c, p_angle,
307 rack, crown)
309 vertsIdx1 = list(range(len(verts), len(verts) + len(verts1)))
310 verts.extend(verts1)
311 vertsIdx2 = list(range(len(verts), len(verts) + len(verts2)))
312 verts.extend(verts2)
313 vertsIdx3 = list(range(len(verts), len(verts) + len(verts3)))
314 verts.extend(verts3)
315 vertsIdx4 = list(range(len(verts), len(verts) + len(verts4)))
316 verts.extend(verts4)
318 verts_outside = []
319 verts_outside.extend(vertsIdx2[:2])
320 verts_outside.append(vertsIdx3[0])
321 verts_outside.extend(vertsIdx4)
322 verts_outside.append(vertsIdx3[-1])
323 verts_outside.append(vertsIdx2[-1])
325 if top:
326 #verts_inside_top = vertsIdx1
327 verts_outside_top = verts_outside
329 verts_bridge_start.append(vertsIdx1[0])
330 verts_bridge_start.append(vertsIdx2[0])
331 verts_bridge_end.append(vertsIdx1[-1])
332 verts_bridge_end.append(vertsIdx2[-1])
334 else:
335 #verts_inside_bottom = vertsIdx1
336 verts_outside_bottom = verts_outside
338 verts_bridge_start.append(vertsIdx2[0])
339 verts_bridge_start.append(vertsIdx1[0])
340 verts_bridge_end.append(vertsIdx2[-1])
341 verts_bridge_end.append(vertsIdx1[-1])
343 # Valley = first 2 vertices of outer base:
344 vgroup_valley.extend(vertsIdx2[:1])
345 # Top/tip vertices:
346 vgroup_top.extend(vertsIdx4)
348 faces_tooth_middle_top = createFaces(vertsIdx2[1:], vertsIdx3,
349 flipped=top)
350 faces_tooth_outer_top = createFaces(vertsIdx3, vertsIdx4,
351 flipped=top)
353 faces_base_top = createFaces(vertsIdx1, vertsIdx2, flipped=top)
354 faces.extend(faces_base_top)
356 faces.extend(faces_tooth_middle_top)
357 faces.extend(faces_tooth_outer_top)
359 #faces_inside = createFaces(verts_inside_top, verts_inside_bottom)
360 #faces.extend(faces_inside)
362 faces_outside = createFaces(verts_outside_top, verts_outside_bottom,
363 flipped=True)
364 faces.extend(faces_outside)
366 if toothCnt == 0:
367 verts_bridge_first = verts_bridge_start
369 # Bridge one tooth to the next
370 if verts_bridge_prev:
371 faces_bridge = createFaces(verts_bridge_prev, verts_bridge_start)
372 #, closed=True (for "inside" faces)
373 faces.extend(faces_bridge)
375 # Remember "end" vertices for next tooth.
376 verts_bridge_prev = verts_bridge_end
378 # Bridge the first to the last tooth.
379 faces_bridge_f_l = createFaces(verts_bridge_prev, verts_bridge_first)
380 #, closed=True (for "inside" faces)
381 faces.extend(faces_bridge_f_l)
383 return verts, faces, vgroup_top, vgroup_valley
386 # Create spokes geometry.
387 # Returns:
388 # * A list of vertices (list of tuples)
389 # * A list of faces (list of lists)
391 # teethNum ... Number of teeth on the gear.
392 # radius ... Radius of the gear, negative for crown gear
393 # De ... Dedendum, extent of tooth below radius.
394 # base ... Base, extent of gear below radius.
395 # width ... Width, thickness of gear.
396 # conangle ... Conical angle of gear. (radiant)
397 # rack
398 # spoke
399 # spbevel
400 # spwidth
401 # splength
402 # spresol
404 # @todo Finish this
405 # @todo Create a function that takes a "Gear" and creates a
406 # matching "Gear Spokes" object.
407 def add_spokes(teethNum, radius, De, base, width=1, conangle=0, rack=0,
408 spoke=3, spbevel=0.1, spwidth=0.2, splength=1.0, spresol=9):
410 if teethNum < 2:
411 return None, None, None, None
413 if spoke < 2:
414 return None, None, None, None
416 t = 2 * pi / teethNum
418 if rack:
419 teethNum = 1
421 scale = (radius - 2 * width * tan(conangle)) / radius
423 verts = []
424 faces = []
426 c = scale # debug
428 fl = len(verts)
429 for toothCnt in range(teethNum):
430 a = toothCnt * t
431 s = 0 # For test
433 if toothCnt % spoke == 0:
434 for d in (-width, width):
435 sv, edgefaces, edgefaces2, sf = add_spoke(a + s, t, d,
436 radius * c, De * c, base * c,
437 spbevel, spwidth, splength, 0, spresol)
438 verts.extend(sv)
439 faces.extend([j + fl for j in i] for i in sf)
440 fl += len(sv)
442 d1 = fl - len(sv)
443 d2 = fl - 2 * len(sv)
445 faces.extend([(i + d2, j + d2, j + d1, i + d1)
446 for (i, j) in zip(edgefaces[:-1], edgefaces[1:])])
447 faces.extend([(i + d2, j + d2, j + d1, i + d1)
448 for (i, j) in zip(edgefaces2[:-1], edgefaces2[1:])])
450 else:
451 for d in (-width, width):
452 sv, edgefaces, edgefaces2, sf = add_spoke(a + s, t, d,
453 radius * c, De * c, base * c,
454 spbevel, spwidth, splength, 1, spresol)
456 verts.extend(sv)
457 fl += len(sv)
459 d1 = fl - len(sv)
460 d2 = fl - 2 * len(sv)
462 faces.extend([[i + d2, i + 1 + d2, i + 1 + d1, i + d1]
463 for (i) in range(0, 3)])
464 faces.extend([[i + d2, i + 1 + d2, i + 1 + d1, i + d1]
465 for (i) in range(5, 8)])
467 return verts, faces
470 # Create worm geometry.
471 # Returns:
472 # * A list of vertices
473 # * A list of faces
474 # * A list (group) of vertices of the tip
475 # * A list (group) of vertices of the valley
477 # teethNum ... Number of teeth on the worm
478 # radius ... Radius of the gear, negative for crown gear
479 # Ad ... Addendum, extent of tooth above radius.
480 # De ... Dedendum, extent of tooth below radius.
481 # p_angle ... Pressure angle. Skewness of tooth tip. (radiant)
482 # width ... Width, thickness of gear.
483 # crown ... Inward pointing extend of crown teeth.
485 # @todo: Fix teethNum. Some numbers are not possible yet.
486 # @todo: Create start & end geoemtry (closing faces)
487 def add_worm(teethNum, rowNum, radius, Ad, De, p_angle,
488 width=1, skew=radians(11.25), crown=0.0):
490 worm = teethNum
491 teethNum = 24
493 t = 2 * pi / teethNum
495 verts = []
496 faces = []
497 vgroup_top = [] # Vertex group of top/tip? vertices.
498 vgroup_valley = [] # Vertex group of valley vertices
500 #width = width / 2.0
502 edgeloop_prev = []
503 for Row in range(rowNum):
504 edgeloop = []
506 for toothCnt in range(teethNum):
507 a = toothCnt * t
509 s = Row * skew
510 d = Row * width
511 c = 1
513 isTooth = False
514 if toothCnt % (teethNum / worm) != 0:
515 # Flat
516 verts1, verts2, verts3, verts4 = add_tooth(a + s, t, d,
517 radius - De, 0.0, 0.0, 0, p_angle)
519 # Ignore other verts than the "other base".
520 verts1 = verts3 = verts4 = []
522 else:
523 # Tooth
524 isTooth = True
525 verts1, verts2, verts3, verts4 = add_tooth(a + s, t, d,
526 radius * c, Ad * c, De * c, 0 * c, p_angle, 0, crown)
528 # Remove various unneeded verts (if we are "inside" the tooth)
529 del(verts2[2]) # Central vertex in the base of the tooth.
530 del(verts3[1]) # Central vertex in the middle of the tooth.
532 vertsIdx2 = list(range(len(verts), len(verts) + len(verts2)))
533 verts.extend(verts2)
534 vertsIdx3 = list(range(len(verts), len(verts) + len(verts3)))
535 verts.extend(verts3)
536 vertsIdx4 = list(range(len(verts), len(verts) + len(verts4)))
537 verts.extend(verts4)
539 if isTooth:
540 verts_current = []
541 verts_current.extend(vertsIdx2[:2])
542 verts_current.append(vertsIdx3[0])
543 verts_current.extend(vertsIdx4)
544 verts_current.append(vertsIdx3[-1])
545 verts_current.append(vertsIdx2[-1])
547 # Valley = first 2 vertices of outer base:
548 vgroup_valley.extend(vertsIdx2[:1])
549 # Top/tip vertices:
550 vgroup_top.extend(vertsIdx4)
552 else:
553 # Flat
554 verts_current = vertsIdx2
556 # Valley - all of them.
557 vgroup_valley.extend(vertsIdx2)
559 edgeloop.extend(verts_current)
561 # Create faces between rings/rows.
562 if edgeloop_prev:
563 faces_row = createFaces(edgeloop, edgeloop_prev, closed=True)
564 faces.extend(faces_row)
566 # Remember last ring/row of vertices for next ring/row iteration.
567 edgeloop_prev = edgeloop
569 return verts, faces, vgroup_top, vgroup_valley
572 class AddGear(bpy.types.Operator):
573 """Add a gear mesh"""
574 bl_idname = "mesh.primitive_gear"
575 bl_label = "Add Gear"
576 bl_options = {'REGISTER', 'UNDO', 'PRESET'}
578 number_of_teeth = IntProperty(name="Number of Teeth",
579 description="Number of teeth on the gear",
580 min=2,
581 max=265,
582 default=12)
583 radius = FloatProperty(name="Radius",
584 description="Radius of the gear, negative for crown gear",
585 min=-100.0,
586 max=100.0,
587 unit='LENGTH',
588 default=1.0)
589 addendum = FloatProperty(name="Addendum",
590 description="Addendum, extent of tooth above radius",
591 min=0.01,
592 max=100.0,
593 unit='LENGTH',
594 default=0.1)
595 dedendum = FloatProperty(name="Dedendum",
596 description="Dedendum, extent of tooth below radius",
597 min=0.0,
598 max=100.0,
599 unit='LENGTH',
600 default=0.1)
601 angle = FloatProperty(name="Pressure Angle",
602 description="Pressure angle, skewness of tooth tip",
603 min=0.0,
604 max=radians(45.0),
605 unit='ROTATION',
606 default=radians(20.0))
607 base = FloatProperty(name="Base",
608 description="Base, extent of gear below radius",
609 min=0.0,
610 max=100.0,
611 unit='LENGTH',
612 default=0.2)
613 width = FloatProperty(name="Width",
614 description="Width, thickness of gear",
615 min=0.05,
616 max=100.0,
617 unit='LENGTH',
618 default=0.2)
619 skew = FloatProperty(name="Skewness",
620 description="Skew of teeth",
621 min=radians(-90.0),
622 max=radians(90.0),
623 unit='ROTATION',
624 default=radians(0.0))
625 conangle = FloatProperty(name="Conical angle",
626 description="Conical angle of gear",
627 min=0.0,
628 max=radians(90.0),
629 unit='ROTATION',
630 default=radians(0.0))
631 crown = FloatProperty(name="Crown",
632 description="Inward pointing extend of crown teeth",
633 min=0.0,
634 max=100.0,
635 unit='LENGTH',
636 default=0.0)
638 def draw(self, context):
639 layout = self.layout
641 box = layout.box()
642 box.prop(self, 'number_of_teeth')
644 box = layout.box()
645 box.prop(self, 'radius')
646 box.prop(self, 'width')
647 box.prop(self, 'base')
649 box = layout.box()
650 box.prop(self, 'dedendum')
651 box.prop(self, 'addendum')
653 box = layout.box()
654 box.prop(self, 'angle')
655 box.prop(self, 'skew')
656 box.prop(self, 'conangle')
657 box.prop(self, 'crown')
660 def execute(self, context):
661 verts, faces, verts_tip, verts_valley = add_gear(
662 self.number_of_teeth,
663 self.radius,
664 self.addendum,
665 self.dedendum,
666 self.base,
667 self.angle,
668 width=self.width,
669 skew=self.skew,
670 conangle=self.conangle,
671 crown=self.crown)
673 # Actually create the mesh object from this geometry data.
674 base = create_mesh_object(context, verts, [], faces, "Gear")
675 obj = base.object
677 # XXX, supporting adding in editmode is move involved
678 if obj.mode != 'EDIT':
679 # Create vertex groups from stored vertices.
680 tipGroup = obj.vertex_groups.new('Tips')
681 tipGroup.add(verts_tip, 1.0, 'ADD')
683 valleyGroup = obj.vertex_groups.new('Valleys')
684 valleyGroup.add(verts_valley, 1.0, 'ADD')
686 return {'FINISHED'}
689 class AddWormGear(bpy.types.Operator):
690 """Add a worm gear mesh"""
691 bl_idname = "mesh.primitive_worm_gear"
692 bl_label = "Add Worm Gear"
693 bl_options = {'REGISTER', 'UNDO', 'PRESET'}
695 number_of_teeth = IntProperty(name="Number of Teeth",
696 description="Number of teeth on the gear",
697 min=2,
698 max=265,
699 default=12)
700 number_of_rows = IntProperty(name="Number of Rows",
701 description="Number of rows on the worm gear",
702 min=2,
703 max=265,
704 default=32)
705 radius = FloatProperty(name="Radius",
706 description="Radius of the gear, negative for crown gear",
707 min=-100.0,
708 max=100.0,
709 unit='LENGTH',
710 default=1.0)
711 addendum = FloatProperty(name="Addendum",
712 description="Addendum, extent of tooth above radius",
713 min=0.01,
714 max=100.0,
715 unit='LENGTH',
716 default=0.1)
717 dedendum = FloatProperty(name="Dedendum",
718 description="Dedendum, extent of tooth below radius",
719 min=0.0,
720 max=100.0,
721 unit='LENGTH',
722 default=0.1)
723 angle = FloatProperty(name="Pressure Angle",
724 description="Pressure angle, skewness of tooth tip",
725 min=0.0,
726 max=radians(45.0),
727 default=radians(20.0),
728 unit='ROTATION')
729 row_height = FloatProperty(name="Row Height",
730 description="Height of each Row",
731 min=0.05,
732 max=100.0,
733 unit='LENGTH',
734 default=0.2)
735 skew = FloatProperty(name="Skewness per Row",
736 description="Skew of each row",
737 min=radians(-90.0),
738 max=radians(90.0),
739 default=radians(11.25),
740 unit='ROTATION')
741 crown = FloatProperty(name="Crown",
742 description="Inward pointing extend of crown teeth",
743 min=0.0,
744 max=100.0,
745 unit='LENGTH',
746 default=0.0)
748 def draw(self, context):
749 layout = self.layout
750 box = layout.box()
751 box.prop(self, 'number_of_teeth')
752 box.prop(self, 'number_of_rows')
753 box.prop(self, 'radius')
754 box.prop(self, 'row_height')
755 box = layout.box()
756 box.prop(self, 'addendum')
757 box.prop(self, 'dedendum')
758 box = layout.box()
759 box.prop(self, 'angle')
760 box.prop(self, 'skew')
761 box.prop(self, 'crown')
763 def execute(self, context):
765 verts, faces, verts_tip, verts_valley = add_worm(
766 self.number_of_teeth,
767 self.number_of_rows,
768 self.radius,
769 self.addendum,
770 self.dedendum,
771 self.angle,
772 width=self.row_height,
773 skew=self.skew,
774 crown=self.crown)
776 # Actually create the mesh object from this geometry data.
777 base = create_mesh_object(context, verts, [], faces, "Worm Gear")
778 obj = base.object
780 # XXX, supporting adding in editmode is move involved
781 if obj.mode != 'EDIT':
782 # Create vertex groups from stored vertices.
783 tipGroup = obj.vertex_groups.new('Tips')
784 tipGroup.add(verts_tip, 1.0, 'ADD')
786 valleyGroup = obj.vertex_groups.new('Valleys')
787 valleyGroup.add(verts_valley, 1.0, 'ADD')
789 return {'FINISHED'}