Sculpt Branch:
[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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
16 #
17 # ##### END GPL LICENSE BLOCK #####
18
19 # <pep8 compliant>
20 import bpy
21
22 narrowui = 180
23
24
25 class DataButtonsPanel(bpy.types.Panel):
26     bl_space_type = 'PROPERTIES'
27     bl_region_type = 'WINDOW'
28     bl_context = "modifier"
29
30
31 class DATA_PT_modifiers(DataButtonsPanel):
32     bl_label = "Modifiers"
33
34     def draw(self, context):
35         layout = self.layout
36
37         ob = context.object
38         wide_ui = context.region.width > narrowui
39
40         row = layout.row()
41         row.operator_menu_enum("object.modifier_add", "type")
42         if wide_ui:
43             row.label()
44
45         for md in ob.modifiers:
46             box = layout.template_modifier(md)
47             if box:
48                 # match enum type to our functions, avoids a lookup table.
49                 getattr(self, md.type)(box, ob, md, wide_ui)
50
51     # the mt.type enum is (ab)used for a lookup on function names
52     # ...to avoid lengthy if statements
53     # so each type must have a function here.
54
55     def ARMATURE(self, layout, ob, md, wide_ui):
56         split = layout.split()
57
58         col = split.column()
59         col.label(text="Object:")
60         col.prop(md, "object", text="")
61
62         if wide_ui:
63             col = split.column()
64         col.label(text="Vertex Group::")
65         col.prop_object(md, "vertex_group", ob, "vertex_groups", text="")
66         sub = col.column()
67         sub.active = bool(md.vertex_group)
68         sub.prop(md, "invert")
69
70         split = layout.split()
71
72         col = split.column()
73         col.label(text="Bind To:")
74         col.prop(md, "use_vertex_groups", text="Vertex Groups")
75         col.prop(md, "use_bone_envelopes", text="Bone Envelopes")
76
77         if wide_ui:
78             col = split.column()
79         col.label(text="Deformation:")
80         col.prop(md, "quaternion")
81         col.prop(md, "multi_modifier")
82
83     def ARRAY(self, layout, ob, md, wide_ui):
84         if wide_ui:
85             layout.prop(md, "fit_type")
86         else:
87             layout.prop(md, "fit_type", text="")
88
89
90         if md.fit_type == 'FIXED_COUNT':
91             layout.prop(md, "count")
92         elif md.fit_type == 'FIT_LENGTH':
93             layout.prop(md, "length")
94         elif md.fit_type == 'FIT_CURVE':
95             layout.prop(md, "curve")
96
97         layout.separator()
98
99         split = layout.split()
100
101         col = split.column()
102         col.prop(md, "constant_offset")
103         sub = col.column()
104         sub.active = md.constant_offset
105         sub.prop(md, "constant_offset_displacement", text="")
106
107         col.separator()
108
109         col.prop(md, "merge_adjacent_vertices", text="Merge")
110         sub = col.column()
111         sub.active = md.merge_adjacent_vertices
112         sub.prop(md, "merge_end_vertices", text="First Last")
113         sub.prop(md, "merge_distance", text="Distance")
114
115         if wide_ui:
116             col = split.column()
117         col.prop(md, "relative_offset")
118         sub = col.column()
119         sub.active = md.relative_offset
120         sub.prop(md, "relative_offset_displacement", text="")
121
122         col.separator()
123
124         col.prop(md, "add_offset_object")
125         sub = col.column()
126         sub.active = md.add_offset_object
127         sub.prop(md, "offset_object", text="")
128
129         layout.separator()
130
131         col = layout.column()
132         col.prop(md, "start_cap")
133         col.prop(md, "end_cap")
134
135     def BEVEL(self, layout, ob, md, wide_ui):
136         split = layout.split()
137
138         col = split.column()
139         col.prop(md, "width")
140
141         if wide_ui:
142             col = split.column()
143         col.prop(md, "only_vertices")
144
145         layout.label(text="Limit Method:")
146         layout.row().prop(md, "limit_method", expand=True)
147         if md.limit_method == 'ANGLE':
148             layout.prop(md, "angle")
149         elif md.limit_method == 'WEIGHT':
150             layout.row().prop(md, "edge_weight_method", expand=True)
151
152     def BOOLEAN(self, layout, ob, md, wide_ui):
153         split = layout.split()
154
155         col = split.column()
156         col.label(text="Operation:")
157         col.prop(md, "operation", text="")
158
159         if wide_ui:
160             col = split.column()
161         col.label(text="Object:")
162         col.prop(md, "object", text="")
163
164     def BUILD(self, layout, ob, md, wide_ui):
165         split = layout.split()
166
167         col = split.column()
168         col.prop(md, "start")
169         col.prop(md, "length")
170
171         if wide_ui:
172             col = split.column()
173         col.prop(md, "randomize")
174         sub = col.column()
175         sub.active = md.randomize
176         sub.prop(md, "seed")
177
178     def CAST(self, layout, ob, md, wide_ui):
179         split = layout.split(percentage=0.25)
180
181         if wide_ui:
182             split.label(text="Cast Type:")
183             split.prop(md, "cast_type", text="")
184         else:
185             layout.prop(md, "cast_type", text="")
186
187         split = layout.split(percentage=0.25)
188
189         col = split.column()
190         col.prop(md, "x")
191         col.prop(md, "y")
192         col.prop(md, "z")
193
194         col = split.column()
195         col.prop(md, "factor")
196         col.prop(md, "radius")
197         col.prop(md, "size")
198         col.prop(md, "from_radius")
199
200         split = layout.split()
201
202         col = split.column()
203         col.label(text="Vertex Group:")
204         col.prop_object(md, "vertex_group", ob, "vertex_groups", text="")
205         if wide_ui:
206             col = split.column()
207         col.label(text="Control Object:")
208         col.prop(md, "object", text="")
209         if md.object:
210             col.prop(md, "use_transform")
211
212     def CLOTH(self, layout, ob, md, wide_ui):
213         layout.label(text="See Cloth panel.")
214
215     def COLLISION(self, layout, ob, md, wide_ui):
216         layout.label(text="See Collision panel.")
217
218     def CURVE(self, layout, ob, md, wide_ui):
219         split = layout.split()
220
221         col = split.column()
222         col.label(text="Object:")
223         col.prop(md, "object", text="")
224         if wide_ui:
225             col = split.column()
226         col.label(text="Vertex Group:")
227         col.prop_object(md, "vertex_group", ob, "vertex_groups", text="")
228         layout.label(text="Deformation Axis:")
229         layout.row().prop(md, "deform_axis", expand=True)
230
231     def DECIMATE(self, layout, ob, md, wide_ui):
232         layout.prop(md, "ratio")
233         layout.prop(md, "face_count")
234
235     def DISPLACE(self, layout, ob, md, wide_ui):
236         split = layout.split()
237
238         col = split.column()
239         col.label(text="Texture:")
240         col.prop(md, "texture", text="")
241         col.label(text="Vertex Group:")
242         col.prop_object(md, "vertex_group", ob, "vertex_groups", text="")
243
244         if wide_ui:
245             col = split.column()
246         col.label(text="Direction:")
247         col.prop(md, "direction", text="")
248         col.label(text="Texture Coordinates:")
249         col.prop(md, "texture_coordinates", text="")
250         if md.texture_coordinates == 'OBJECT':
251             layout.prop(md, "texture_coordinate_object", text="Object")
252         elif md.texture_coordinates == 'UV' and ob.type == 'MESH':
253             layout.prop_object(md, "uv_layer", ob.data, "uv_textures")
254
255         layout.separator()
256
257         split = layout.split()
258
259         col = split.column()
260         col.prop(md, "midlevel")
261
262         if wide_ui:
263             col = split.column()
264         col.prop(md, "strength")
265
266     def EDGE_SPLIT(self, layout, ob, md, wide_ui):
267         split = layout.split()
268
269         col = split.column()
270         col.prop(md, "use_edge_angle", text="Edge Angle")
271         sub = col.column()
272         sub.active = md.use_edge_angle
273         sub.prop(md, "split_angle")
274
275         if wide_ui:
276             col = split.column()
277         col.prop(md, "use_sharp", text="Sharp Edges")
278
279     def EXPLODE(self, layout, ob, md, wide_ui):
280         split = layout.split()
281
282         col = split.column()
283         col.label(text="Vertex group:")
284         col.prop_object(md, "vertex_group", ob, "vertex_groups", text="")
285         sub = col.column()
286         sub.active = bool(md.vertex_group)
287         sub.prop(md, "protect")
288
289         if wide_ui:
290             col = split.column()
291         col.prop(md, "split_edges")
292         col.prop(md, "unborn")
293         col.prop(md, "alive")
294         col.prop(md, "dead")
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         col.label(text="Vertex Group:")
356         if md.mode == 'ARMATURE':
357             col.prop(md, "armature", text="")
358         elif md.mode == 'VERTEX_GROUP':
359             col.prop_object(md, "vertex_group", ob, "vertex_groups", text="")
360
361         sub = col.column()
362         sub.active = bool(md.vertex_group)
363         sub.prop(md, "invert")
364
365     def MESH_DEFORM(self, layout, ob, md, wide_ui):
366         split = layout.split()
367         col = split.column()
368         sub = col.column()
369         sub.label(text="Object:")
370         sub.prop(md, "object", text="")
371         sub.prop(md, "mode", 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             if md.mode == 'VOLUME':
390                 split = layout.split()
391
392                 col = split.column()
393                 col.prop(md, "precision")
394
395                 if wide_ui:
396                     col = split.column()
397                 col.prop(md, "dynamic")
398
399     def MIRROR(self, layout, ob, md, wide_ui):
400         layout.prop(md, "merge_limit")
401         if wide_ui:
402             split = layout.split(percentage=0.25)
403         else:
404             split = layout.split(percentage=0.4)
405
406         col = split.column()
407         col.label(text="Axis:")
408         col.prop(md, "x")
409         col.prop(md, "y")
410         col.prop(md, "z")
411
412         if wide_ui:
413             col = split.column()
414         else:
415             subsplit = layout.split()
416             col = subsplit.column()
417         col.label(text="Options:")
418         col.prop(md, "clip", text="Clipping")
419         col.prop(md, "mirror_vertex_groups", text="Vertex Groups")
420
421         col = split.column()
422         col.label(text="Textures:")
423         col.prop(md, "mirror_u", text="U")
424         col.prop(md, "mirror_v", text="V")
425
426         col = layout.column()
427         col.label(text="Mirror Object:")
428         col.prop(md, "mirror_object", text="")
429
430     def MULTIRES(self, layout, ob, md, wide_ui):
431         if wide_ui:
432             layout.row().prop(md, "subdivision_type", expand=True)
433         else:
434             layout.row().prop(md, "subdivision_type", text="")
435
436         split = layout.split()
437         col = split.column()
438         col.prop(md, "levels", text="Preview")
439         col.prop(md, "sculpt_levels", text="Sculpt")
440         col.prop(md, "render_levels", text="Render")
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.prop(md, "optimal_display")
449
450         layout.separator()
451
452         col = layout.column()
453         row = col.row()
454         if md.external:
455             row.operator("object.multires_pack_external", text="Pack External")
456             row.label()
457             row = col.row()
458             row.prop(md, "filename", text="")
459         else:
460             row.operator("object.multires_save_external", text="Save External...")
461             row.label()
462
463     def PARTICLE_INSTANCE(self, layout, ob, md, wide_ui):
464         layout.prop(md, "object")
465         layout.prop(md, "particle_system_number", text="Particle System")
466
467         split = layout.split()
468         col = split.column()
469         col.label(text="Create From:")
470         col.prop(md, "normal")
471         col.prop(md, "children")
472         col.prop(md, "size")
473
474         if wide_ui:
475             col = split.column()
476         col.label(text="Show Particles When:")
477         col.prop(md, "alive")
478         col.prop(md, "unborn")
479         col.prop(md, "dead")
480
481         layout.separator()
482
483         layout.prop(md, "path", text="Create Along Paths")
484
485         split = layout.split()
486         split.active = md.path
487         col = split.column()
488         col.row().prop(md, "axis", expand=True)
489         col.prop(md, "keep_shape")
490
491         if wide_ui:
492             col = split.column()
493         col.prop(md, "position", slider=True)
494         col.prop(md, "random_position", text="Random", slider=True)
495
496     def PARTICLE_SYSTEM(self, layout, ob, md, wide_ui):
497         layout.label(text="See Particle panel.")
498
499     def SHRINKWRAP(self, layout, ob, md, wide_ui):
500         split = layout.split()
501         col = split.column()
502         col.label(text="Target:")
503         col.prop(md, "target", text="")
504         if wide_ui:
505             col = split.column()
506         col.label(text="Vertex Group:")
507         col.prop_object(md, "vertex_group", ob, "vertex_groups", text="")
508
509         split = layout.split()
510
511         col = split.column()
512         col.prop(md, "offset")
513         col.prop(md, "subsurf_levels")
514
515         if wide_ui:
516             col = split.column()
517             col.label(text="Mode:")
518         col.prop(md, "mode", text="")
519
520         if wide_ui:
521             split = layout.split(percentage=0.25)
522         else:
523             split = layout.split(percentage=0.35)
524         col = split.column()
525
526         if md.mode == 'PROJECT':
527             col.label(text="Axis:")
528             col.prop(md, "x")
529             col.prop(md, "y")
530             col.prop(md, "z")
531
532             col = split.column()
533             col.label(text="Direction:")
534             col.prop(md, "negative")
535             col.prop(md, "positive")
536
537             if wide_ui:
538                 col = split.column()
539             else:
540                 subsplit = layout.split()
541                 col = subsplit.column()
542             col.label(text="Cull Faces:")
543             col.prop(md, "cull_front_faces", text="Front")
544             col.prop(md, "cull_back_faces", text="Back")
545
546             layout.label(text="Auxiliary Target:")
547             layout.prop(md, "auxiliary_target", text="")
548
549         elif md.mode == 'NEAREST_SURFACEPOINT':
550             layout.prop(md, "keep_above_surface")
551
552     def SIMPLE_DEFORM(self, layout, ob, md, wide_ui):
553         split = layout.split()
554
555         col = split.column()
556         col.label(text="Mode:")
557         col.prop(md, "mode", text="")
558
559         if wide_ui:
560             col = split.column()
561         col.label(text="Vertex Group:")
562         col.prop_object(md, "vertex_group", ob, "vertex_groups", text="")
563
564         split = layout.split()
565
566         col = split.column()
567         col.label(text="Origin:")
568         col.prop(md, "origin", text="")
569         sub = col.column()
570         sub.active = (md.origin != "")
571         sub.prop(md, "relative")
572
573         if wide_ui:
574             col = split.column()
575         col.label(text="Deform:")
576         col.prop(md, "factor")
577         col.prop(md, "limits", slider=True)
578         if md.mode in ('TAPER', 'STRETCH'):
579             col.prop(md, "lock_x_axis")
580             col.prop(md, "lock_y_axis")
581
582     def SMOKE(self, layout, ob, md, wide_ui):
583         layout.label(text="See Smoke panel.")
584
585     def SMOOTH(self, layout, ob, md, wide_ui):
586         split = layout.split(percentage=0.25)
587
588         col = split.column()
589         col.label(text="Axis:")
590         col.prop(md, "x")
591         col.prop(md, "y")
592         col.prop(md, "z")
593
594         col = split.column()
595         col.prop(md, "factor")
596         col.prop(md, "repeat")
597         col.label(text="Vertex Group:")
598         col.prop_object(md, "vertex_group", ob, "vertex_groups", text="")
599
600     def SOFT_BODY(self, layout, ob, md, wide_ui):
601         layout.label(text="See Soft Body panel.")
602
603     def SUBSURF(self, layout, ob, md, wide_ui):
604         if wide_ui:
605             layout.row().prop(md, "subdivision_type", expand=True)
606         else:
607             layout.row().prop(md, "subdivision_type", text="")
608
609         split = layout.split()
610         col = split.column()
611         col.label(text="Subdivisions:")
612         col.prop(md, "levels", text="View")
613         col.prop(md, "render_levels", text="Render")
614
615         if wide_ui:
616             col = split.column()
617         col.label(text="Options:")
618         col.prop(md, "optimal_display")
619
620     def SURFACE(self, layout, ob, md, wide_ui):
621         layout.label(text="See Fields panel.")
622
623     def UV_PROJECT(self, layout, ob, md, wide_ui):
624         if ob.type == 'MESH':
625             split = layout.split()
626             col = split.column()
627             col.label(text="UV Layer:")
628             col.prop_object(md, "uv_layer", ob.data, "uv_textures", text="")
629
630             if wide_ui:
631                 col = split.column()
632             col.label(text="Image:")
633             col.prop(md, "image", text="")
634
635             split = layout.split()
636             col = split.column()
637             col.prop(md, "override_image")
638             col.prop(md, "num_projectors", text="Projectors")
639             for proj in md.projectors:
640                 col.prop(proj, "object", text="")
641
642             if wide_ui:
643                 col = split.column()
644             sub = col.column(align=True)
645             sub.label(text="Aspect Ratio:")
646             sub.prop(md, "horizontal_aspect_ratio", text="Horizontal")
647             sub.prop(md, "vertical_aspect_ratio", text="Vertical")
648
649     def WAVE(self, layout, ob, md, wide_ui):
650         split = layout.split()
651
652         col = split.column()
653         col.label(text="Motion:")
654         col.prop(md, "x")
655         col.prop(md, "y")
656         col.prop(md, "cyclic")
657
658         if wide_ui:
659             col = split.column()
660         col.prop(md, "normals")
661         sub = col.column()
662         sub.active = md.normals
663         sub.prop(md, "x_normal", text="X")
664         sub.prop(md, "y_normal", text="Y")
665         sub.prop(md, "z_normal", text="Z")
666
667         split = layout.split()
668
669         col = split.column()
670         col.label(text="Time:")
671         sub = col.column(align=True)
672         sub.prop(md, "time_offset", text="Offset")
673         sub.prop(md, "lifetime", text="Life")
674         col.prop(md, "damping_time", text="Damping")
675
676         if wide_ui:
677             col = split.column()
678         col.label(text="Position:")
679         sub = col.column(align=True)
680         sub.prop(md, "start_position_x", text="X")
681         sub.prop(md, "start_position_y", text="Y")
682         col.prop(md, "falloff_radius", text="Falloff")
683
684         layout.separator()
685
686         layout.prop(md, "start_position_object")
687         layout.prop_object(md, "vertex_group", ob, "vertex_groups")
688         layout.prop(md, "texture")
689         layout.prop(md, "texture_coordinates")
690         if md.texture_coordinates == 'MAP_UV' and ob.type == 'MESH':
691             layout.prop_object(md, "uv_layer", ob.data, "uv_textures")
692         elif md.texture_coordinates == 'OBJECT':
693             layout.prop(md, "texture_coordinates_object")
694
695         layout.separator()
696
697         split = layout.split()
698
699         col = split.column()
700         col.prop(md, "speed", slider=True)
701         col.prop(md, "height", slider=True)
702
703         if wide_ui:
704             col = split.column()
705         col.prop(md, "width", slider=True)
706         col.prop(md, "narrowness", slider=True)
707
708 bpy.types.register(DATA_PT_modifiers)