synched with trunk at revision 30597
[blender.git] / release / scripts / ui / properties_data_modifier.py
1 # ##### BEGIN GPL LICENSE BLOCK #####
2 #
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.
7 #
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.
12 #
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.
16 #
17 # ##### END GPL LICENSE BLOCK #####
18
19 # <pep8 compliant>
20 import bpy
21
22 narrowui = bpy.context.user_preferences.view.properties_width_check
23 narrowmod = 260
24
25
26 class DataButtonsPanel(bpy.types.Panel):
27     bl_space_type = 'PROPERTIES'
28     bl_region_type = 'WINDOW'
29     bl_context = "modifier"
30
31
32 class DATA_PT_modifiers(DataButtonsPanel):
33     bl_label = "Modifiers"
34
35     def draw(self, context):
36         layout = self.layout
37
38         ob = context.object
39         wide_ui = context.region.width > narrowui
40         compact_mod = context.region.width < narrowmod
41
42         layout.operator_menu_enum("object.modifier_add", "type")
43
44         for md in ob.modifiers:
45             box = layout.template_modifier(md, compact=compact_mod)
46             if box:
47                 # match enum type to our functions, avoids a lookup table.
48                 getattr(self, md.type)(box, ob, md, wide_ui)
49
50     # the mt.type enum is (ab)used for a lookup on function names
51     # ...to avoid lengthy if statements
52     # so each type must have a function here.
53
54     def ARMATURE(self, layout, ob, md, wide_ui):
55         split = layout.split()
56
57         col = split.column()
58         col.label(text="Object:")
59         col.prop(md, "object", text="")
60
61         if wide_ui:
62             col = split.column()
63         col.label(text="Vertex Group::")
64         col.prop_object(md, "vertex_group", ob, "vertex_groups", text="")
65         sub = col.column()
66         sub.active = bool(md.vertex_group)
67         sub.prop(md, "invert")
68
69         split = layout.split()
70
71         col = split.column()
72         col.label(text="Bind To:")
73         col.prop(md, "use_vertex_groups", text="Vertex Groups")
74         col.prop(md, "use_bone_envelopes", text="Bone Envelopes")
75
76         if wide_ui:
77             col = split.column()
78         col.label(text="Deformation:")
79         col.prop(md, "quaternion")
80         col.prop(md, "multi_modifier")
81
82     def ARRAY(self, layout, ob, md, wide_ui):
83         if wide_ui:
84             layout.prop(md, "fit_type")
85         else:
86             layout.prop(md, "fit_type", text="")
87
88
89         if md.fit_type == 'FIXED_COUNT':
90             layout.prop(md, "count")
91         elif md.fit_type == 'FIT_LENGTH':
92             layout.prop(md, "length")
93         elif md.fit_type == 'FIT_CURVE':
94             layout.prop(md, "curve")
95
96         layout.separator()
97
98         split = layout.split()
99
100         col = split.column()
101         col.prop(md, "constant_offset")
102         sub = col.column()
103         sub.active = md.constant_offset
104         sub.prop(md, "constant_offset_displacement", text="")
105
106         col.separator()
107
108         col.prop(md, "merge_adjacent_vertices", text="Merge")
109         sub = col.column()
110         sub.active = md.merge_adjacent_vertices
111         sub.prop(md, "merge_end_vertices", text="First Last")
112         sub.prop(md, "merge_distance", text="Distance")
113
114         if wide_ui:
115             col = split.column()
116         col.prop(md, "relative_offset")
117         sub = col.column()
118         sub.active = md.relative_offset
119         sub.prop(md, "relative_offset_displacement", text="")
120
121         col.separator()
122
123         col.prop(md, "add_offset_object")
124         sub = col.column()
125         sub.active = md.add_offset_object
126         sub.prop(md, "offset_object", text="")
127
128         layout.separator()
129
130         col = layout.column()
131         col.prop(md, "start_cap")
132         col.prop(md, "end_cap")
133
134     def BEVEL(self, layout, ob, md, wide_ui):
135         split = layout.split()
136
137         col = split.column()
138         col.prop(md, "width")
139
140         if wide_ui:
141             col = split.column()
142         col.prop(md, "only_vertices")
143
144         layout.label(text="Limit Method:")
145         layout.row().prop(md, "limit_method", expand=True)
146         if md.limit_method == 'ANGLE':
147             layout.prop(md, "angle")
148         elif md.limit_method == 'WEIGHT':
149             layout.row().prop(md, "edge_weight_method", expand=True)
150
151     def BOOLEAN(self, layout, ob, md, wide_ui):
152         split = layout.split()
153
154         col = split.column()
155         col.label(text="Operation:")
156         col.prop(md, "operation", text="")
157
158         if wide_ui:
159             col = split.column()
160         col.label(text="Object:")
161         col.prop(md, "object", text="")
162
163     def BUILD(self, layout, ob, md, wide_ui):
164         split = layout.split()
165
166         col = split.column()
167         col.prop(md, "frame_start")
168         col.prop(md, "length")
169
170         if wide_ui:
171             col = split.column()
172         col.prop(md, "randomize")
173         sub = col.column()
174         sub.active = md.randomize
175         sub.prop(md, "seed")
176
177     def CAST(self, layout, ob, md, wide_ui):
178         split = layout.split(percentage=0.25)
179
180         if wide_ui:
181             split.label(text="Cast Type:")
182             split.prop(md, "cast_type", text="")
183         else:
184             layout.prop(md, "cast_type", text="")
185
186         split = layout.split(percentage=0.25)
187
188         col = split.column()
189         col.prop(md, "x")
190         col.prop(md, "y")
191         col.prop(md, "z")
192
193         col = split.column()
194         col.prop(md, "factor")
195         col.prop(md, "radius")
196         col.prop(md, "size")
197         col.prop(md, "from_radius")
198
199         split = layout.split()
200
201         col = split.column()
202         col.label(text="Vertex Group:")
203         col.prop_object(md, "vertex_group", ob, "vertex_groups", text="")
204         if wide_ui:
205             col = split.column()
206         col.label(text="Control Object:")
207         col.prop(md, "object", text="")
208         if md.object:
209             col.prop(md, "use_transform")
210
211     def CLOTH(self, layout, ob, md, wide_ui):
212         layout.label(text="See Cloth panel.")
213
214     def COLLISION(self, layout, ob, md, wide_ui):
215         layout.label(text="See Collision panel.")
216
217     def CURVE(self, layout, ob, md, wide_ui):
218         split = layout.split()
219
220         col = split.column()
221         col.label(text="Object:")
222         col.prop(md, "object", text="")
223         if wide_ui:
224             col = split.column()
225         col.label(text="Vertex Group:")
226         col.prop_object(md, "vertex_group", ob, "vertex_groups", text="")
227         layout.label(text="Deformation Axis:")
228         layout.row().prop(md, "deform_axis", expand=True)
229
230     def DECIMATE(self, layout, ob, md, wide_ui):
231         layout.prop(md, "ratio")
232         layout.label(text="Face Count: %s" % str(md.face_count))
233
234     def DISPLACE(self, layout, ob, md, wide_ui):
235         split = layout.split()
236
237         col = split.column()
238         col.label(text="Texture:")
239         col.prop(md, "texture", text="")
240         col.label(text="Vertex Group:")
241         col.prop_object(md, "vertex_group", ob, "vertex_groups", text="")
242
243         if wide_ui:
244             col = split.column()
245         col.label(text="Direction:")
246         col.prop(md, "direction", text="")
247         col.label(text="Texture Coordinates:")
248         col.prop(md, "texture_coordinates", text="")
249         if md.texture_coordinates == 'OBJECT':
250             layout.prop(md, "texture_coordinate_object", text="Object")
251         elif md.texture_coordinates == 'UV' and ob.type == 'MESH':
252             layout.prop_object(md, "uv_layer", ob.data, "uv_textures")
253
254         layout.separator()
255
256         split = layout.split()
257
258         col = split.column()
259         col.prop(md, "midlevel")
260
261         if wide_ui:
262             col = split.column()
263         col.prop(md, "strength")
264
265     def EDGE_SPLIT(self, layout, ob, md, wide_ui):
266         split = layout.split()
267
268         col = split.column()
269         col.prop(md, "use_edge_angle", text="Edge Angle")
270         sub = col.column()
271         sub.active = md.use_edge_angle
272         sub.prop(md, "split_angle")
273
274         if wide_ui:
275             col = split.column()
276         col.prop(md, "use_sharp", text="Sharp Edges")
277
278     def EXPLODE(self, layout, ob, md, wide_ui):
279         split = layout.split()
280
281         col = split.column()
282         col.label(text="Vertex group:")
283         col.prop_object(md, "vertex_group", ob, "vertex_groups", text="")
284         sub = col.column()
285         sub.active = bool(md.vertex_group)
286         sub.prop(md, "protect")
287
288         if wide_ui:
289             col = split.column()
290         col.prop(md, "split_edges")
291         col.prop(md, "unborn")
292         col.prop(md, "alive")
293         col.prop(md, "dead")
294         col.prop(md, "size")
295
296         layout.operator("object.explode_refresh", text="Refresh")
297
298     def FLUID_SIMULATION(self, layout, ob, md, wide_ui):
299         layout.label(text="See Fluid panel.")
300
301     def HOOK(self, layout, ob, md, wide_ui):
302         split = layout.split()
303
304         col = split.column()
305         col.label(text="Object:")
306         col.prop(md, "object", text="")
307         if md.object and md.object.type == 'ARMATURE':
308             col.label(text="Bone:")
309             col.prop_object(md, "subtarget", md.object.data, "bones", text="")
310         if wide_ui:
311             col = split.column()
312         col.label(text="Vertex Group:")
313         col.prop_object(md, "vertex_group", ob, "vertex_groups", text="")
314
315         layout.separator()
316
317         split = layout.split()
318
319         col = split.column()
320         col.prop(md, "falloff")
321         col.prop(md, "force", slider=True)
322         if wide_ui:
323             col = split.column()
324         else:
325             col.separator()
326         col.operator("object.hook_reset", text="Reset")
327         col.operator("object.hook_recenter", text="Recenter")
328
329         if ob.mode == 'EDIT':
330             layout.separator()
331             row = layout.row()
332             row.operator("object.hook_select", text="Select")
333             row.operator("object.hook_assign", text="Assign")
334
335     def LATTICE(self, layout, ob, md, wide_ui):
336         split = layout.split()
337
338         col = split.column()
339         col.label(text="Object:")
340         col.prop(md, "object", text="")
341
342         if wide_ui:
343             col = split.column()
344         col.label(text="Vertex Group:")
345         col.prop_object(md, "vertex_group", ob, "vertex_groups", text="")
346
347     def MASK(self, layout, ob, md, wide_ui):
348         split = layout.split()
349
350         col = split.column()
351         col.label(text="Mode:")
352         col.prop(md, "mode", text="")
353         if wide_ui:
354             col = split.column()
355         if md.mode == 'ARMATURE':
356             col.label(text="Armature:")
357             col.prop(md, "armature", text="")
358         elif md.mode == 'VERTEX_GROUP':
359             col.label(text="Vertex Group:")
360             col.prop_object(md, "vertex_group", ob, "vertex_groups", text="")
361
362         sub = col.column()
363         sub.active = bool(md.vertex_group)
364         sub.prop(md, "invert")
365
366     def MESH_DEFORM(self, layout, ob, md, wide_ui):
367         split = layout.split()
368         col = split.column()
369         sub = col.column()
370         sub.label(text="Object:")
371         sub.prop(md, "object", text="")
372         sub.active = not md.is_bound
373         if wide_ui:
374             col = split.column()
375         col.label(text="Vertex Group:")
376         col.prop_object(md, "vertex_group", ob, "vertex_groups", text="")
377
378         sub = col.column()
379         sub.active = bool(md.vertex_group)
380         sub.prop(md, "invert")
381
382         layout.separator()
383
384         if md.is_bound:
385             layout.operator("object.meshdeform_bind", text="Unbind")
386         else:
387             layout.operator("object.meshdeform_bind", text="Bind")
388
389             split = layout.split()
390
391             col = split.column()
392             col.prop(md, "precision")
393
394             if wide_ui:
395                 col = split.column()
396             col.prop(md, "dynamic")
397
398     def MIRROR(self, layout, ob, md, wide_ui):
399         layout.prop(md, "merge_limit")
400         if wide_ui:
401             split = layout.split(percentage=0.25)
402         else:
403             split = layout.split(percentage=0.4)
404
405         col = split.column()
406         col.label(text="Axis:")
407         col.prop(md, "x")
408         col.prop(md, "y")
409         col.prop(md, "z")
410
411         if wide_ui:
412             col = split.column()
413         else:
414             subsplit = layout.split()
415             col = subsplit.column()
416         col.label(text="Options:")
417         col.prop(md, "clip", text="Clipping")
418         col.prop(md, "mirror_vertex_groups", text="Vertex Groups")
419
420         col = split.column()
421         col.label(text="Textures:")
422         col.prop(md, "mirror_u", text="U")
423         col.prop(md, "mirror_v", text="V")
424
425         col = layout.column()
426         col.label(text="Mirror Object:")
427         col.prop(md, "mirror_object", text="")
428
429     def MULTIRES(self, layout, ob, md, wide_ui):
430         if wide_ui:
431             layout.row().prop(md, "subdivision_type", expand=True)
432         else:
433             layout.row().prop(md, "subdivision_type", text="")
434
435         split = layout.split()
436         col = split.column()
437         col.prop(md, "levels", text="Preview")
438         col.prop(md, "sculpt_levels", text="Sculpt")
439         col.prop(md, "render_levels", text="Render")
440         col.prop(bpy.context.tool_settings.sculpt, "fast_navigate")
441
442         if wide_ui:
443             col = split.column()
444
445         col.enabled = ob.mode != 'EDIT'
446         col.operator("object.multires_subdivide", text="Subdivide")
447         col.operator("object.multires_higher_levels_delete", text="Delete Higher")
448         col.operator("object.multires_reshape", text="Reshape")
449         col.prop(md, "optimal_display")
450
451         layout.separator()
452
453         col = layout.column()
454         row = col.row()
455         if md.external:
456             row.operator("object.multires_external_pack", text="Pack External")
457             row.label()
458             row = col.row()
459             row.prop(md, "filepath", text="")
460         else:
461             row.operator("object.multires_external_save", text="Save External...")
462             row.label()
463
464     def NAVMESH(self, layout, ob, md, wide_ui):
465         layout = self.layout
466
467     def PARTICLE_INSTANCE(self, layout, ob, md, wide_ui):
468         layout.prop(md, "object")
469         layout.prop(md, "particle_system_number", text="Particle System")
470
471         split = layout.split()
472         col = split.column()
473         col.label(text="Create From:")
474         col.prop(md, "normal")
475         col.prop(md, "children")
476         col.prop(md, "size")
477
478         if wide_ui:
479             col = split.column()
480         col.label(text="Show Particles When:")
481         col.prop(md, "alive")
482         col.prop(md, "unborn")
483         col.prop(md, "dead")
484
485         layout.separator()
486
487         layout.prop(md, "use_path", text="Create Along Paths")
488
489         split = layout.split()
490         split.active = md.use_path
491         col = split.column()
492         col.row().prop(md, "axis", expand=True)
493         col.prop(md, "keep_shape")
494
495         if wide_ui:
496             col = split.column()
497         col.prop(md, "position", slider=True)
498         col.prop(md, "random_position", text="Random", slider=True)
499
500     def PARTICLE_SYSTEM(self, layout, ob, md, wide_ui):
501         layout.label(text="See Particle panel.")
502
503     def SCREW(self, layout, ob, md, wide_ui):
504         split = layout.split()
505
506         col = split.column()
507         col.prop(md, "axis")
508         col.prop(md, "object", text="AxisOb")
509         col.prop(md, "angle")
510         col.prop(md, "steps")
511         col.prop(md, "render_steps")
512
513         if wide_ui:
514             col = split.column()
515         row = col.row()
516         row.active = (md.object is None or md.use_object_screw_offset == False)
517         row.prop(md, "screw_offset")
518         row = col.row()
519         row.active = (md.object is not None)
520         row.prop(md, "use_object_screw_offset")
521         col.prop(md, "use_normal_calculate")
522         col.prop(md, "use_normal_flip")
523         col.prop(md, "iterations")
524
525     def SHRINKWRAP(self, layout, ob, md, wide_ui):
526         split = layout.split()
527         col = split.column()
528         col.label(text="Target:")
529         col.prop(md, "target", text="")
530         if wide_ui:
531             col = split.column()
532         col.label(text="Vertex Group:")
533         col.prop_object(md, "vertex_group", ob, "vertex_groups", text="")
534
535         split = layout.split()
536
537         col = split.column()
538         col.prop(md, "offset")
539         col.prop(md, "subsurf_levels")
540
541         if wide_ui:
542             col = split.column()
543             col.label(text="Mode:")
544         col.prop(md, "mode", text="")
545
546         if wide_ui:
547             split = layout.split(percentage=0.25)
548         else:
549             split = layout.split(percentage=0.35)
550         col = split.column()
551
552         if md.mode == 'PROJECT':
553             col.label(text="Axis:")
554             col.prop(md, "x")
555             col.prop(md, "y")
556             col.prop(md, "z")
557
558             col = split.column()
559             col.label(text="Direction:")
560             col.prop(md, "negative")
561             col.prop(md, "positive")
562
563             if wide_ui:
564                 col = split.column()
565             else:
566                 subsplit = layout.split()
567                 col = subsplit.column()
568             col.label(text="Cull Faces:")
569             col.prop(md, "cull_front_faces", text="Front")
570             col.prop(md, "cull_back_faces", text="Back")
571
572             layout.label(text="Auxiliary Target:")
573             layout.prop(md, "auxiliary_target", text="")
574
575         elif md.mode == 'NEAREST_SURFACEPOINT':
576             layout.prop(md, "keep_above_surface")
577
578     def SIMPLE_DEFORM(self, layout, ob, md, wide_ui):
579         split = layout.split()
580
581         col = split.column()
582         col.label(text="Mode:")
583         col.prop(md, "mode", text="")
584
585         if wide_ui:
586             col = split.column()
587         col.label(text="Vertex Group:")
588         col.prop_object(md, "vertex_group", ob, "vertex_groups", text="")
589
590         split = layout.split()
591
592         col = split.column()
593         col.label(text="Origin:")
594         col.prop(md, "origin", text="")
595         sub = col.column()
596         sub.active = (md.origin != "")
597         sub.prop(md, "relative")
598
599         if wide_ui:
600             col = split.column()
601         col.label(text="Deform:")
602         col.prop(md, "factor")
603         col.prop(md, "limits", slider=True)
604         if md.mode in ('TAPER', 'STRETCH'):
605             col.prop(md, "lock_x_axis")
606             col.prop(md, "lock_y_axis")
607
608     def SMOKE(self, layout, ob, md, wide_ui):
609         layout.label(text="See Smoke panel.")
610
611     def SMOOTH(self, layout, ob, md, wide_ui):
612         split = layout.split(percentage=0.25)
613
614         col = split.column()
615         col.label(text="Axis:")
616         col.prop(md, "x")
617         col.prop(md, "y")
618         col.prop(md, "z")
619
620         col = split.column()
621         col.prop(md, "factor")
622         col.prop(md, "repeat")
623         col.label(text="Vertex Group:")
624         col.prop_object(md, "vertex_group", ob, "vertex_groups", text="")
625
626     def SOFT_BODY(self, layout, ob, md, wide_ui):
627         layout.label(text="See Soft Body panel.")
628
629     def SOLIDIFY(self, layout, ob, md, wide_ui):
630
631         split = layout.split()
632
633         col = split.column()
634         col.prop(md, "thickness")
635         col.prop_object(md, "vertex_group", ob, "vertex_groups", text="")
636
637         col.label(text="Crease:")
638         col.prop(md, "edge_crease_inner", text="Inner")
639         col.prop(md, "edge_crease_outer", text="Outer")
640         col.prop(md, "edge_crease_rim", text="Rim")
641
642         if wide_ui:
643             col = split.column()
644
645         col.prop(md, "offset")
646         colsub = col.column()
647         colsub.active = (md.vertex_group is not "")
648         colsub.prop(md, "invert", text="Invert")
649
650         col.prop(md, "use_even_offset")
651         col.prop(md, "use_quality_normals")
652
653         col.prop(md, "use_rim")
654         colsub = col.column()
655         colsub.active = md.use_rim
656         colsub.prop(md, "use_rim_material")
657
658         # col = layout.column()
659         # col.label(text="Vertex Group:")
660         # col.prop_object(md, "vertex_group", ob, "vertex_groups", text="")
661
662     def SUBSURF(self, layout, ob, md, wide_ui):
663         if wide_ui:
664             layout.row().prop(md, "subdivision_type", expand=True)
665         else:
666             layout.row().prop(md, "subdivision_type", text="")
667
668         split = layout.split()
669         col = split.column()
670         col.label(text="Subdivisions:")
671         col.prop(md, "levels", text="View")
672         col.prop(md, "render_levels", text="Render")
673
674         if wide_ui:
675             col = split.column()
676         col.label(text="Options:")
677         col.prop(md, "subsurf_uv")
678         col.prop(md, "optimal_display")
679
680     def SURFACE(self, layout, ob, md, wide_ui):
681         layout.label(text="See Fields panel.")
682
683     def UV_PROJECT(self, layout, ob, md, wide_ui):
684         if ob.type == 'MESH':
685             split = layout.split()
686
687             col = split.column()
688             col.label(text="Image:")
689             col.prop(md, "image", text="")
690
691             if wide_ui:
692                 col = split.column()
693             col.label(text="UV Layer:")
694             col.prop_object(md, "uv_layer", ob.data, "uv_textures", text="")
695
696             split = layout.split()
697             col = split.column()
698             col.prop(md, "override_image")
699             col.prop(md, "num_projectors", text="Projectors")
700             for proj in md.projectors:
701                 col.prop(proj, "object", text="")
702
703             if wide_ui:
704                 col = split.column()
705             sub = col.column(align=True)
706             sub.prop(md, "aspect_x", text="Aspect X")
707             sub.prop(md, "aspect_y", text="Aspect Y")
708
709             sub = col.column(align=True)
710             sub.prop(md, "scale_x", text="Scale X")
711             sub.prop(md, "scale_y", text="Scale Y")
712
713     def WAVE(self, layout, ob, md, wide_ui):
714         split = layout.split()
715
716         col = split.column()
717         col.label(text="Motion:")
718         col.prop(md, "x")
719         col.prop(md, "y")
720         col.prop(md, "cyclic")
721
722         if wide_ui:
723             col = split.column()
724         col.prop(md, "normals")
725         sub = col.column()
726         sub.active = md.normals
727         sub.prop(md, "x_normal", text="X")
728         sub.prop(md, "y_normal", text="Y")
729         sub.prop(md, "z_normal", text="Z")
730
731         split = layout.split()
732
733         col = split.column()
734         col.label(text="Time:")
735         sub = col.column(align=True)
736         sub.prop(md, "time_offset", text="Offset")
737         sub.prop(md, "lifetime", text="Life")
738         col.prop(md, "damping_time", text="Damping")
739
740         if wide_ui:
741             col = split.column()
742         col.label(text="Position:")
743         sub = col.column(align=True)
744         sub.prop(md, "start_position_x", text="X")
745         sub.prop(md, "start_position_y", text="Y")
746         col.prop(md, "falloff_radius", text="Falloff")
747
748         layout.separator()
749
750         layout.prop(md, "start_position_object")
751         layout.prop_object(md, "vertex_group", ob, "vertex_groups")
752         layout.prop(md, "texture")
753         layout.prop(md, "texture_coordinates")
754         if md.texture_coordinates == 'MAP_UV' and ob.type == 'MESH':
755             layout.prop_object(md, "uv_layer", ob.data, "uv_textures")
756         elif md.texture_coordinates == 'OBJECT':
757             layout.prop(md, "texture_coordinates_object")
758
759         layout.separator()
760
761         split = layout.split()
762
763         col = split.column()
764         col.prop(md, "speed", slider=True)
765         col.prop(md, "height", slider=True)
766
767         if wide_ui:
768             col = split.column()
769         col.prop(md, "width", slider=True)
770         col.prop(md, "narrowness", slider=True)
771
772
773 classes = [
774     DATA_PT_modifiers]
775
776
777 def register():
778     register = bpy.types.register
779     for cls in classes:
780         register(cls)
781
782
783 def unregister():
784     unregister = bpy.types.unregister
785     for cls in classes:
786         unregister(cls)
787
788 if __name__ == "__main__":
789     register()