Merge branch 'master' into blender2.8
[blender.git] / release / scripts / startup / bl_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 from bpy.types import Panel
22 from bpy.app.translations import pgettext_iface as iface_
23
24
25 class ModifierButtonsPanel:
26     bl_space_type = 'PROPERTIES'
27     bl_region_type = 'WINDOW'
28     bl_context = "modifier"
29     bl_options = {'HIDE_HEADER'}
30
31
32 class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
33     bl_label = "Modifiers"
34
35     def draw(self, context):
36         layout = self.layout
37
38         ob = context.object
39
40         layout.operator_menu_enum("object.modifier_add", "type")
41
42         for md in ob.modifiers:
43             box = layout.template_modifier(md)
44             if box:
45                 # match enum type to our functions, avoids a lookup table.
46                 getattr(self, md.type)(box, ob, md)
47
48     # the mt.type enum is (ab)used for a lookup on function names
49     # ...to avoid lengthy if statements
50     # so each type must have a function here.
51
52     def ARMATURE(self, layout, ob, md):
53         split = layout.split()
54
55         col = split.column()
56         col.label(text="Object:")
57         col.prop(md, "object", text="")
58         col.prop(md, "use_deform_preserve_volume")
59
60         col = split.column()
61         col.label(text="Bind To:")
62         col.prop(md, "use_vertex_groups", text="Vertex Groups")
63         col.prop(md, "use_bone_envelopes", text="Bone Envelopes")
64
65         layout.separator()
66
67         split = layout.split()
68
69         row = split.row(align=True)
70         row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
71         sub = row.row(align=True)
72         sub.active = bool(md.vertex_group)
73         sub.prop(md, "invert_vertex_group", text="", icon='ARROW_LEFTRIGHT')
74
75         split.prop(md, "use_multi_modifier")
76
77     def ARRAY(self, layout, ob, md):
78         layout.prop(md, "fit_type")
79
80         if md.fit_type == 'FIXED_COUNT':
81             layout.prop(md, "count")
82         elif md.fit_type == 'FIT_LENGTH':
83             layout.prop(md, "fit_length")
84         elif md.fit_type == 'FIT_CURVE':
85             layout.prop(md, "curve")
86
87         layout.separator()
88
89         split = layout.split()
90
91         col = split.column()
92         col.prop(md, "use_constant_offset")
93         sub = col.column()
94         sub.active = md.use_constant_offset
95         sub.prop(md, "constant_offset_displace", text="")
96
97         col.separator()
98
99         col.prop(md, "use_merge_vertices", text="Merge")
100         sub = col.column()
101         sub.active = md.use_merge_vertices
102         sub.prop(md, "use_merge_vertices_cap", text="First Last")
103         sub.prop(md, "merge_threshold", text="Distance")
104
105         col = split.column()
106         col.prop(md, "use_relative_offset")
107         sub = col.column()
108         sub.active = md.use_relative_offset
109         sub.prop(md, "relative_offset_displace", text="")
110
111         col.separator()
112
113         col.prop(md, "use_object_offset")
114         sub = col.column()
115         sub.active = md.use_object_offset
116         sub.prop(md, "offset_object", text="")
117
118         layout.separator()
119
120         layout.prop(md, "start_cap")
121         layout.prop(md, "end_cap")
122
123     def BEVEL(self, layout, ob, md):
124         split = layout.split()
125
126         col = split.column()
127         col.prop(md, "width")
128         col.prop(md, "segments")
129         col.prop(md, "profile")
130         col.prop(md, "material")
131
132         col = split.column()
133         col.prop(md, "use_only_vertices")
134         col.prop(md, "use_clamp_overlap")
135         col.prop(md, "loop_slide")
136
137         layout.label(text="Limit Method:")
138         layout.row().prop(md, "limit_method", expand=True)
139         if md.limit_method == 'ANGLE':
140             layout.prop(md, "angle_limit")
141         elif md.limit_method == 'VGROUP':
142             layout.label(text="Vertex Group:")
143             layout.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
144
145         layout.label(text="Width Method:")
146         layout.row().prop(md, "offset_type", expand=True)
147
148     def BOOLEAN(self, layout, ob, md):
149         split = layout.split()
150
151         col = split.column()
152         col.label(text="Operation:")
153         col.prop(md, "operation", text="")
154
155         col = split.column()
156         col.label(text="Object:")
157         col.prop(md, "object", text="")
158
159         split = layout.split()
160         split.column().label(text="Solver:")
161         split.column().prop(md, "solver", text="")
162
163         if md.solver == 'BMESH':
164             layout.prop(md, "double_threshold")
165
166     def BUILD(self, layout, ob, md):
167         split = layout.split()
168
169         col = split.column()
170         col.prop(md, "frame_start")
171         col.prop(md, "frame_duration")
172         col.prop(md, "use_reverse")
173
174         col = split.column()
175         col.prop(md, "use_random_order")
176         sub = col.column()
177         sub.active = md.use_random_order
178         sub.prop(md, "seed")
179
180     def MESH_CACHE(self, layout, ob, md):
181         layout.prop(md, "cache_format")
182         layout.prop(md, "filepath")
183
184         if md.cache_format == 'ABC':
185             layout.prop(md, "sub_object")
186
187         layout.label(text="Evaluation:")
188         layout.prop(md, "factor", slider=True)
189         layout.prop(md, "deform_mode")
190         layout.prop(md, "interpolation")
191
192         layout.label(text="Time Mapping:")
193
194         row = layout.row()
195         row.prop(md, "time_mode", expand=True)
196         row = layout.row()
197         row.prop(md, "play_mode", expand=True)
198         if md.play_mode == 'SCENE':
199             layout.prop(md, "frame_start")
200             layout.prop(md, "frame_scale")
201         else:
202             time_mode = md.time_mode
203             if time_mode == 'FRAME':
204                 layout.prop(md, "eval_frame")
205             elif time_mode == 'TIME':
206                 layout.prop(md, "eval_time")
207             elif time_mode == 'FACTOR':
208                 layout.prop(md, "eval_factor")
209
210         layout.label(text="Axis Mapping:")
211         split = layout.split(percentage=0.5, align=True)
212         split.alert = (md.forward_axis[-1] == md.up_axis[-1])
213         split.label("Forward/Up Axis:")
214         split.prop(md, "forward_axis", text="")
215         split.prop(md, "up_axis", text="")
216         split = layout.split(percentage=0.5)
217         split.label(text="Flip Axis:")
218         row = split.row()
219         row.prop(md, "flip_axis")
220
221     def MESH_SEQUENCE_CACHE(self, layout, ob, md):
222         layout.label(text="Cache File Properties:")
223         box = layout.box()
224         box.template_cache_file(md, "cache_file")
225
226         cache_file = md.cache_file
227
228         layout.label(text="Modifier Properties:")
229         box = layout.box()
230
231         if cache_file is not None:
232             box.prop_search(md, "object_path", cache_file, "object_paths")
233
234         if ob.type == 'MESH':
235             box.row().prop(md, "read_data")
236
237     def CAST(self, layout, ob, md):
238         split = layout.split(percentage=0.25)
239
240         split.label(text="Cast Type:")
241         split.prop(md, "cast_type", text="")
242
243         split = layout.split(percentage=0.25)
244
245         col = split.column()
246         col.prop(md, "use_x")
247         col.prop(md, "use_y")
248         col.prop(md, "use_z")
249
250         col = split.column()
251         col.prop(md, "factor")
252         col.prop(md, "radius")
253         col.prop(md, "size")
254         col.prop(md, "use_radius_as_size")
255
256         split = layout.split()
257
258         col = split.column()
259         col.label(text="Vertex Group:")
260         col.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
261         col = split.column()
262         col.label(text="Control Object:")
263         col.prop(md, "object", text="")
264         if md.object:
265             col.prop(md, "use_transform")
266
267     def CLOTH(self, layout, ob, md):
268         layout.label(text="Settings are inside the Physics tab")
269
270     def COLLISION(self, layout, ob, md):
271         layout.label(text="Settings are inside the Physics tab")
272
273     def CURVE(self, layout, ob, md):
274         split = layout.split()
275
276         col = split.column()
277         col.label(text="Object:")
278         col.prop(md, "object", text="")
279         col = split.column()
280         col.label(text="Vertex Group:")
281         col.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
282         layout.label(text="Deformation Axis:")
283         layout.row().prop(md, "deform_axis", expand=True)
284
285     def DECIMATE(self, layout, ob, md):
286         decimate_type = md.decimate_type
287
288         row = layout.row()
289         row.prop(md, "decimate_type", expand=True)
290
291         if decimate_type == 'COLLAPSE':
292             has_vgroup = bool(md.vertex_group)
293             layout.prop(md, "ratio")
294
295             split = layout.split()
296
297             col = split.column()
298             row = col.row(align=True)
299             row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
300             row.prop(md, "invert_vertex_group", text="", icon='ARROW_LEFTRIGHT')
301
302             layout_info = col
303
304             col = split.column()
305             row = col.row()
306             row.active = has_vgroup
307             row.prop(md, "vertex_group_factor")
308
309             col.prop(md, "use_collapse_triangulate")
310             row = col.split(percentage=0.75)
311             row.prop(md, "use_symmetry")
312             row.prop(md, "symmetry_axis", text="")
313
314         elif decimate_type == 'UNSUBDIV':
315             layout.prop(md, "iterations")
316             layout_info = layout
317         else:  # decimate_type == 'DISSOLVE':
318             layout.prop(md, "angle_limit")
319             layout.prop(md, "use_dissolve_boundaries")
320             layout.label("Delimit:")
321             row = layout.row()
322             row.prop(md, "delimit")
323             layout_info = layout
324
325         layout_info.label(text=iface_("Faces: %d") % md.face_count, translate=False)
326
327     def DISPLACE(self, layout, ob, md):
328         has_texture = (md.texture is not None)
329
330         col = layout.column(align=True)
331         col.label(text="Texture:")
332         col.template_ID(md, "texture", new="texture.new")
333
334         split = layout.split()
335
336         col = split.column(align=True)
337         col.label(text="Direction:")
338         col.prop(md, "direction", text="")
339         col.label(text="Vertex Group:")
340         col.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
341
342         col = split.column(align=True)
343         col.active = has_texture
344         col.label(text="Texture Coordinates:")
345         col.prop(md, "texture_coords", text="")
346         if md.texture_coords == 'OBJECT':
347             col.label(text="Object:")
348             col.prop(md, "texture_coords_object", text="")
349         elif md.texture_coords == 'UV' and ob.type == 'MESH':
350             col.label(text="UV Map:")
351             col.prop_search(md, "uv_layer", ob.data, "uv_textures", text="")
352
353         layout.separator()
354
355         row = layout.row()
356         row.prop(md, "mid_level")
357         row.prop(md, "strength")
358
359     def DYNAMIC_PAINT(self, layout, ob, md):
360         layout.label(text="Settings are inside the Physics tab")
361
362     def EDGE_SPLIT(self, layout, ob, md):
363         split = layout.split()
364
365         col = split.column()
366         col.prop(md, "use_edge_angle", text="Edge Angle")
367         sub = col.column()
368         sub.active = md.use_edge_angle
369         sub.prop(md, "split_angle")
370
371         split.prop(md, "use_edge_sharp", text="Sharp Edges")
372
373     def EXPLODE(self, layout, ob, md):
374         split = layout.split()
375
376         col = split.column()
377         col.label(text="Vertex group:")
378         col.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
379         sub = col.column()
380         sub.active = bool(md.vertex_group)
381         sub.prop(md, "protect")
382         col.label(text="Particle UV")
383         col.prop_search(md, "particle_uv", ob.data, "uv_textures", text="")
384
385         col = split.column()
386         col.prop(md, "use_edge_cut")
387         col.prop(md, "show_unborn")
388         col.prop(md, "show_alive")
389         col.prop(md, "show_dead")
390         col.prop(md, "use_size")
391
392         layout.operator("object.explode_refresh", text="Refresh")
393
394     def FLUID_SIMULATION(self, layout, ob, md):
395         layout.label(text="Settings are inside the Physics tab")
396
397     def HOOK(self, layout, ob, md):
398         use_falloff = (md.falloff_type != 'NONE')
399         split = layout.split()
400
401         col = split.column()
402         col.label(text="Object:")
403         col.prop(md, "object", text="")
404         if md.object and md.object.type == 'ARMATURE':
405             col.label(text="Bone:")
406             col.prop_search(md, "subtarget", md.object.data, "bones", text="")
407         col = split.column()
408         col.label(text="Vertex Group:")
409         col.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
410
411         layout.separator()
412
413         row = layout.row(align=True)
414         if use_falloff:
415             row.prop(md, "falloff_radius")
416         row.prop(md, "strength", slider=True)
417         layout.prop(md, "falloff_type")
418
419         col = layout.column()
420         if use_falloff:
421             if md.falloff_type == 'CURVE':
422                 col.template_curve_mapping(md, "falloff_curve")
423
424         split = layout.split()
425
426         col = split.column()
427         col.prop(md, "use_falloff_uniform")
428
429         if ob.mode == 'EDIT':
430             row = col.row(align=True)
431             row.operator("object.hook_reset", text="Reset")
432             row.operator("object.hook_recenter", text="Recenter")
433
434             row = layout.row(align=True)
435             row.operator("object.hook_select", text="Select")
436             row.operator("object.hook_assign", text="Assign")
437
438     def LAPLACIANDEFORM(self, layout, ob, md):
439         is_bind = md.is_bind
440
441         layout.prop(md, "iterations")
442
443         row = layout.row()
444         row.active = not is_bind
445         row.label(text="Anchors Vertex Group:")
446
447         row = layout.row()
448         row.enabled = not is_bind
449         row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
450
451         layout.separator()
452
453         row = layout.row()
454         row.enabled = bool(md.vertex_group)
455         row.operator("object.laplaciandeform_bind", text="Unbind" if is_bind else "Bind")
456
457     def LAPLACIANSMOOTH(self, layout, ob, md):
458         layout.prop(md, "iterations")
459
460         split = layout.split(percentage=0.25)
461
462         col = split.column()
463         col.label(text="Axis:")
464         col.prop(md, "use_x")
465         col.prop(md, "use_y")
466         col.prop(md, "use_z")
467
468         col = split.column()
469         col.label(text="Lambda:")
470         col.prop(md, "lambda_factor", text="Factor")
471         col.prop(md, "lambda_border", text="Border")
472
473         col.separator()
474         col.prop(md, "use_volume_preserve")
475         col.prop(md, "use_normalized")
476
477         layout.label(text="Vertex Group:")
478         layout.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
479
480     def LATTICE(self, layout, ob, md):
481         split = layout.split()
482
483         col = split.column()
484         col.label(text="Object:")
485         col.prop(md, "object", text="")
486
487         col = split.column()
488         col.label(text="Vertex Group:")
489         col.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
490
491         layout.separator()
492         layout.prop(md, "strength", slider=True)
493
494     def MASK(self, layout, ob, md):
495         split = layout.split()
496
497         col = split.column()
498         col.label(text="Mode:")
499         col.prop(md, "mode", text="")
500
501         col = split.column()
502         if md.mode == 'ARMATURE':
503             col.label(text="Armature:")
504             row = col.row(align=True)
505             row.prop(md, "armature", text="")
506             sub = row.row(align=True)
507             sub.active = (md.armature is not None)
508             sub.prop(md, "invert_vertex_group", text="", icon='ARROW_LEFTRIGHT')
509         elif md.mode == 'VERTEX_GROUP':
510             col.label(text="Vertex Group:")
511             row = col.row(align=True)
512             row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
513             sub = row.row(align=True)
514             sub.active = bool(md.vertex_group)
515             sub.prop(md, "invert_vertex_group", text="", icon='ARROW_LEFTRIGHT')
516
517     def MESH_DEFORM(self, layout, ob, md):
518         split = layout.split()
519
520         col = split.column()
521         col.enabled = not md.is_bound
522         col.label(text="Object:")
523         col.prop(md, "object", text="")
524
525         col = split.column()
526         col.label(text="Vertex Group:")
527         row = col.row(align=True)
528         row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
529         sub = row.row(align=True)
530         sub.active = bool(md.vertex_group)
531         sub.prop(md, "invert_vertex_group", text="", icon='ARROW_LEFTRIGHT')
532
533         layout.separator()
534         row = layout.row()
535         row.enabled = not md.is_bound
536         row.prop(md, "precision")
537         row.prop(md, "use_dynamic_bind")
538
539         layout.separator()
540         if md.is_bound:
541             layout.operator("object.meshdeform_bind", text="Unbind")
542         else:
543             layout.operator("object.meshdeform_bind", text="Bind")
544
545     def MIRROR(self, layout, ob, md):
546         split = layout.split(percentage=0.25)
547
548         col = split.column()
549         col.label(text="Axis:")
550         col.prop(md, "use_x")
551         col.prop(md, "use_y")
552         col.prop(md, "use_z")
553
554         col = split.column()
555         col.label(text="Options:")
556         col.prop(md, "use_mirror_merge", text="Merge")
557         col.prop(md, "use_clip", text="Clipping")
558         col.prop(md, "use_mirror_vertex_groups", text="Vertex Groups")
559
560         col = split.column()
561         col.label(text="Textures:")
562         col.prop(md, "use_mirror_u", text="U")
563         col.prop(md, "use_mirror_v", text="V")
564
565         col = layout.column()
566
567         if md.use_mirror_merge is True:
568             col.prop(md, "merge_threshold")
569         col.label(text="Mirror Object:")
570         col.prop(md, "mirror_object", text="")
571
572     def MULTIRES(self, layout, ob, md):
573         layout.row().prop(md, "subdivision_type", expand=True)
574
575         split = layout.split()
576         col = split.column()
577         col.prop(md, "levels", text="Preview")
578         col.prop(md, "sculpt_levels", text="Sculpt")
579         col.prop(md, "render_levels", text="Render")
580
581         col = split.column()
582
583         col.enabled = ob.mode != 'EDIT'
584         col.operator("object.multires_subdivide", text="Subdivide")
585         col.operator("object.multires_higher_levels_delete", text="Delete Higher")
586         col.operator("object.multires_reshape", text="Reshape")
587         col.operator("object.multires_base_apply", text="Apply Base")
588         col.prop(md, "use_subsurf_uv")
589         col.prop(md, "show_only_control_edges")
590
591         layout.separator()
592
593         col = layout.column()
594         row = col.row()
595         if md.is_external:
596             row.operator("object.multires_external_pack", text="Pack External")
597             row.label()
598             row = col.row()
599             row.prop(md, "filepath", text="")
600         else:
601             row.operator("object.multires_external_save", text="Save External...")
602             row.label()
603
604     def OCEAN(self, layout, ob, md):
605         if not bpy.app.build_options.mod_oceansim:
606             layout.label("Built without OceanSim modifier")
607             return
608
609         layout.prop(md, "geometry_mode")
610
611         if md.geometry_mode == 'GENERATE':
612             row = layout.row()
613             row.prop(md, "repeat_x")
614             row.prop(md, "repeat_y")
615
616         layout.separator()
617
618         split = layout.split()
619
620         col = split.column()
621         col.prop(md, "time")
622         col.prop(md, "depth")
623         col.prop(md, "random_seed")
624
625         col = split.column()
626         col.prop(md, "resolution")
627         col.prop(md, "size")
628         col.prop(md, "spatial_size")
629
630         layout.label("Waves:")
631
632         split = layout.split()
633
634         col = split.column()
635         col.prop(md, "choppiness")
636         col.prop(md, "wave_scale", text="Scale")
637         col.prop(md, "wave_scale_min")
638         col.prop(md, "wind_velocity")
639
640         col = split.column()
641         col.prop(md, "wave_alignment", text="Alignment")
642         sub = col.column()
643         sub.active = (md.wave_alignment > 0.0)
644         sub.prop(md, "wave_direction", text="Direction")
645         sub.prop(md, "damping")
646
647         layout.separator()
648
649         layout.prop(md, "use_normals")
650
651         split = layout.split()
652
653         col = split.column()
654         col.prop(md, "use_foam")
655         sub = col.row()
656         sub.active = md.use_foam
657         sub.prop(md, "foam_coverage", text="Coverage")
658
659         col = split.column()
660         col.active = md.use_foam
661         col.label("Foam Data Layer Name:")
662         col.prop(md, "foam_layer_name", text="")
663
664         layout.separator()
665
666         if md.is_cached:
667             layout.operator("object.ocean_bake", text="Free Bake").free = True
668         else:
669             layout.operator("object.ocean_bake").free = False
670
671         split = layout.split()
672         split.enabled = not md.is_cached
673
674         col = split.column(align=True)
675         col.prop(md, "frame_start", text="Start")
676         col.prop(md, "frame_end", text="End")
677
678         col = split.column(align=True)
679         col.label(text="Cache path:")
680         col.prop(md, "filepath", text="")
681
682         split = layout.split()
683         split.enabled = not md.is_cached
684
685         col = split.column()
686         col.active = md.use_foam
687         col.prop(md, "bake_foam_fade")
688
689         col = split.column()
690
691     def SCREW(self, layout, ob, md):
692         split = layout.split()
693
694         col = split.column()
695         col.prop(md, "axis")
696         col.prop(md, "object", text="AxisOb")
697         col.prop(md, "angle")
698         col.prop(md, "steps")
699         col.prop(md, "render_steps")
700         col.prop(md, "use_smooth_shade")
701
702         col = split.column()
703         row = col.row()
704         row.active = (md.object is None or md.use_object_screw_offset is False)
705         row.prop(md, "screw_offset")
706         row = col.row()
707         row.active = (md.object is not None)
708         row.prop(md, "use_object_screw_offset")
709         col.prop(md, "use_normal_calculate")
710         col.prop(md, "use_normal_flip")
711         col.prop(md, "iterations")
712         col.prop(md, "use_stretch_u")
713         col.prop(md, "use_stretch_v")
714
715     def SHRINKWRAP(self, layout, ob, md):
716         split = layout.split()
717         col = split.column()
718         col.label(text="Target:")
719         col.prop(md, "target", text="")
720         col = split.column()
721         col.label(text="Vertex Group:")
722         row = col.row(align=True)
723         row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
724         row.prop(md, "invert_vertex_group", text="", icon='ARROW_LEFTRIGHT')
725
726         split = layout.split()
727
728         col = split.column()
729         col.prop(md, "offset")
730
731         col = split.column()
732         col.label(text="Mode:")
733         col.prop(md, "wrap_method", text="")
734
735         if md.wrap_method == 'PROJECT':
736             split = layout.split()
737             col = split.column()
738             col.prop(md, "subsurf_levels")
739             col = split.column()
740
741             col.prop(md, "project_limit", text="Limit")
742             split = layout.split(percentage=0.25)
743
744             col = split.column()
745             col.label(text="Axis:")
746             col.prop(md, "use_project_x")
747             col.prop(md, "use_project_y")
748             col.prop(md, "use_project_z")
749
750             col = split.column()
751             col.label(text="Direction:")
752             col.prop(md, "use_negative_direction")
753             col.prop(md, "use_positive_direction")
754
755             col = split.column()
756             col.label(text="Cull Faces:")
757             col.prop(md, "cull_face", expand=True)
758
759             layout.prop(md, "auxiliary_target")
760
761         elif md.wrap_method == 'NEAREST_SURFACEPOINT':
762             layout.prop(md, "use_keep_above_surface")
763
764     def SIMPLE_DEFORM(self, layout, ob, md):
765
766         layout.row().prop(md, "deform_method", expand=True)
767
768         split = layout.split()
769
770         col = split.column()
771         col.label(text="Vertex Group:")
772         row = col.row(align=True)
773         row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
774         row.prop(md, "invert_vertex_group", text="", icon='ARROW_LEFTRIGHT')
775
776         split = layout.split()
777
778         col = split.column()
779         col.label(text="Axis, Origin:")
780         col.prop(md, "origin", text="")
781
782         if md.deform_method in {'TAPER', 'STRETCH', 'TWIST'}:
783             col.label(text="Lock:")
784             col.prop(md, "lock_x")
785             col.prop(md, "lock_y")
786
787         col = split.column()
788         col.label(text="Deform:")
789         if md.deform_method in {'TAPER', 'STRETCH'}:
790             col.prop(md, "factor")
791         else:
792             col.prop(md, "angle")
793         col.prop(md, "limits", slider=True)
794
795     def SMOKE(self, layout, ob, md):
796         layout.label(text="Settings are inside the Physics tab")
797
798     def SMOOTH(self, layout, ob, md):
799         split = layout.split(percentage=0.25)
800
801         col = split.column()
802         col.label(text="Axis:")
803         col.prop(md, "use_x")
804         col.prop(md, "use_y")
805         col.prop(md, "use_z")
806
807         col = split.column()
808         col.prop(md, "factor")
809         col.prop(md, "iterations")
810         col.label(text="Vertex Group:")
811         col.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
812
813     def SOFT_BODY(self, layout, ob, md):
814         layout.label(text="Settings are inside the Physics tab")
815
816     def SOLIDIFY(self, layout, ob, md):
817         split = layout.split()
818
819         col = split.column()
820         col.prop(md, "thickness")
821         col.prop(md, "thickness_clamp")
822
823         col.separator()
824
825         row = col.row(align=True)
826         row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
827         sub = row.row(align=True)
828         sub.active = bool(md.vertex_group)
829         sub.prop(md, "invert_vertex_group", text="", icon='ARROW_LEFTRIGHT')
830
831         sub = col.row()
832         sub.active = bool(md.vertex_group)
833         sub.prop(md, "thickness_vertex_group", text="Factor")
834
835         col.label(text="Crease:")
836         col.prop(md, "edge_crease_inner", text="Inner")
837         col.prop(md, "edge_crease_outer", text="Outer")
838         col.prop(md, "edge_crease_rim", text="Rim")
839
840         col = split.column()
841
842         col.prop(md, "offset")
843         col.prop(md, "use_flip_normals")
844
845         col.prop(md, "use_even_offset")
846         col.prop(md, "use_quality_normals")
847         col.prop(md, "use_rim")
848         col_rim = col.column()
849         col_rim.active = md.use_rim
850         col_rim.prop(md, "use_rim_only")
851
852         col.separator()
853
854         col.label(text="Material Index Offset:")
855
856         sub = col.column()
857         row = sub.split(align=True, percentage=0.4)
858         row.prop(md, "material_offset", text="")
859         row = row.row(align=True)
860         row.active = md.use_rim
861         row.prop(md, "material_offset_rim", text="Rim")
862
863     def SUBSURF(self, layout, ob, md):
864         layout.row().prop(md, "subdivision_type", expand=True)
865
866         split = layout.split()
867         col = split.column()
868
869         engine = bpy.context.scene.render.engine
870         if engine == "CYCLES" and md == ob.modifiers[-1] and bpy.context.scene.cycles.feature_set == "EXPERIMENTAL":
871             col.label(text="Preview:")
872             col.prop(md, "levels", text="Levels")
873             col.label(text="Render:")
874             col.prop(ob.cycles, "use_adaptive_subdivision", text="Adaptive")
875             if ob.cycles.use_adaptive_subdivision:
876                 col.prop(ob.cycles, "dicing_rate")
877             else:
878                 col.prop(md, "render_levels", text="Levels")
879         else:
880             col.label(text="Subdivisions:")
881             col.prop(md, "levels", text="View")
882             col.prop(md, "render_levels", text="Render")
883
884         col = split.column()
885         col.label(text="Options:")
886         col.prop(md, "use_subsurf_uv")
887         col.prop(md, "show_only_control_edges")
888         if hasattr(md, "use_opensubdiv"):
889             col.prop(md, "use_opensubdiv")
890
891     def SURFACE(self, layout, ob, md):
892         layout.label(text="Settings are inside the Physics tab")
893
894     def UV_PROJECT(self, layout, ob, md):
895         split = layout.split()
896
897         col = split.column()
898         col.label(text="Image:")
899         col.prop(md, "image", text="")
900
901         col = split.column()
902         col.label(text="UV Map:")
903         col.prop_search(md, "uv_layer", ob.data, "uv_textures", text="")
904
905         split = layout.split()
906         col = split.column()
907         col.prop(md, "use_image_override")
908         col.prop(md, "projector_count", text="Projectors")
909         for proj in md.projectors:
910             col.prop(proj, "object", text="")
911
912         col = split.column()
913         sub = col.column(align=True)
914         sub.prop(md, "aspect_x", text="Aspect X")
915         sub.prop(md, "aspect_y", text="Aspect Y")
916
917         sub = col.column(align=True)
918         sub.prop(md, "scale_x", text="Scale X")
919         sub.prop(md, "scale_y", text="Scale Y")
920
921     def WARP(self, layout, ob, md):
922         use_falloff = (md.falloff_type != 'NONE')
923         split = layout.split()
924
925         col = split.column()
926         col.label(text="From:")
927         col.prop(md, "object_from", text="")
928
929         col.prop(md, "use_volume_preserve")
930
931         col = split.column()
932         col.label(text="To:")
933         col.prop(md, "object_to", text="")
934         col.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
935
936         col = layout.column()
937
938         row = col.row(align=True)
939         row.prop(md, "strength")
940         if use_falloff:
941             row.prop(md, "falloff_radius")
942
943         col.prop(md, "falloff_type")
944         if use_falloff:
945             if md.falloff_type == 'CURVE':
946                 col.template_curve_mapping(md, "falloff_curve")
947
948         # 2 new columns
949         split = layout.split()
950         col = split.column()
951         col.label(text="Texture:")
952         col.template_ID(md, "texture", new="texture.new")
953
954         col = split.column()
955         col.label(text="Texture Coordinates:")
956         col.prop(md, "texture_coords", text="")
957
958         if md.texture_coords == 'OBJECT':
959             layout.prop(md, "texture_coords_object", text="Object")
960         elif md.texture_coords == 'UV' and ob.type == 'MESH':
961             layout.prop_search(md, "uv_layer", ob.data, "uv_textures")
962
963     def WAVE(self, layout, ob, md):
964         split = layout.split()
965
966         col = split.column()
967         col.label(text="Motion:")
968         col.prop(md, "use_x")
969         col.prop(md, "use_y")
970         col.prop(md, "use_cyclic")
971
972         col = split.column()
973         col.prop(md, "use_normal")
974         sub = col.column()
975         sub.active = md.use_normal
976         sub.prop(md, "use_normal_x", text="X")
977         sub.prop(md, "use_normal_y", text="Y")
978         sub.prop(md, "use_normal_z", text="Z")
979
980         split = layout.split()
981
982         col = split.column()
983         col.label(text="Time:")
984         sub = col.column(align=True)
985         sub.prop(md, "time_offset", text="Offset")
986         sub.prop(md, "lifetime", text="Life")
987         col.prop(md, "damping_time", text="Damping")
988
989         col = split.column()
990         col.label(text="Position:")
991         sub = col.column(align=True)
992         sub.prop(md, "start_position_x", text="X")
993         sub.prop(md, "start_position_y", text="Y")
994         col.prop(md, "falloff_radius", text="Falloff")
995
996         layout.separator()
997
998         layout.prop(md, "start_position_object")
999         layout.prop_search(md, "vertex_group", ob, "vertex_groups")
1000         split = layout.split(percentage=0.33)
1001         col = split.column()
1002         col.label(text="Texture")
1003         col = split.column()
1004         col.template_ID(md, "texture", new="texture.new")
1005         layout.prop(md, "texture_coords")
1006         if md.texture_coords == 'UV' and ob.type == 'MESH':
1007             layout.prop_search(md, "uv_layer", ob.data, "uv_textures")
1008         elif md.texture_coords == 'OBJECT':
1009             layout.prop(md, "texture_coords_object")
1010
1011         layout.separator()
1012
1013         split = layout.split()
1014
1015         col = split.column()
1016         col.prop(md, "speed", slider=True)
1017         col.prop(md, "height", slider=True)
1018
1019         col = split.column()
1020         col.prop(md, "width", slider=True)
1021         col.prop(md, "narrowness", slider=True)
1022
1023     def REMESH(self, layout, ob, md):
1024         layout.prop(md, "mode")
1025
1026         row = layout.row()
1027         row.prop(md, "octree_depth")
1028         row.prop(md, "scale")
1029
1030         if md.mode == 'SHARP':
1031             layout.prop(md, "sharpness")
1032
1033         layout.prop(md, "use_smooth_shade")
1034         layout.prop(md, "use_remove_disconnected")
1035         row = layout.row()
1036         row.active = md.use_remove_disconnected
1037         row.prop(md, "threshold")
1038
1039     @staticmethod
1040     def vertex_weight_mask(layout, ob, md):
1041         layout.label(text="Influence/Mask Options:")
1042
1043         split = layout.split(percentage=0.4)
1044         split.label(text="Global Influence:")
1045         split.prop(md, "mask_constant", text="")
1046
1047         if not md.mask_texture:
1048             split = layout.split(percentage=0.4)
1049             split.label(text="Vertex Group Mask:")
1050             split.prop_search(md, "mask_vertex_group", ob, "vertex_groups", text="")
1051
1052         if not md.mask_vertex_group:
1053             split = layout.split(percentage=0.4)
1054             split.label(text="Texture Mask:")
1055             split.template_ID(md, "mask_texture", new="texture.new")
1056             if md.mask_texture:
1057                 split = layout.split()
1058
1059                 col = split.column()
1060                 col.label(text="Texture Coordinates:")
1061                 col.prop(md, "mask_tex_mapping", text="")
1062
1063                 col = split.column()
1064                 col.label(text="Use Channel:")
1065                 col.prop(md, "mask_tex_use_channel", text="")
1066
1067                 if md.mask_tex_mapping == 'OBJECT':
1068                     layout.prop(md, "mask_tex_map_object", text="Object")
1069                 elif md.mask_tex_mapping == 'UV' and ob.type == 'MESH':
1070                     layout.prop_search(md, "mask_tex_uv_layer", ob.data, "uv_textures")
1071
1072     def VERTEX_WEIGHT_EDIT(self, layout, ob, md):
1073         split = layout.split()
1074
1075         col = split.column()
1076         col.label(text="Vertex Group:")
1077         col.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
1078
1079         col.label(text="Default Weight:")
1080         col.prop(md, "default_weight", text="")
1081
1082         col = split.column()
1083         col.prop(md, "use_add")
1084         sub = col.column()
1085         sub.active = md.use_add
1086         sub.prop(md, "add_threshold")
1087
1088         col = col.column()
1089         col.prop(md, "use_remove")
1090         sub = col.column()
1091         sub.active = md.use_remove
1092         sub.prop(md, "remove_threshold")
1093
1094         layout.separator()
1095
1096         layout.prop(md, "falloff_type")
1097         if md.falloff_type == 'CURVE':
1098             layout.template_curve_mapping(md, "map_curve")
1099
1100         # Common mask options
1101         layout.separator()
1102         self.vertex_weight_mask(layout, ob, md)
1103
1104     def VERTEX_WEIGHT_MIX(self, layout, ob, md):
1105         split = layout.split()
1106
1107         col = split.column()
1108         col.label(text="Vertex Group A:")
1109         col.prop_search(md, "vertex_group_a", ob, "vertex_groups", text="")
1110         col.label(text="Default Weight A:")
1111         col.prop(md, "default_weight_a", text="")
1112
1113         col.label(text="Mix Mode:")
1114         col.prop(md, "mix_mode", text="")
1115
1116         col = split.column()
1117         col.label(text="Vertex Group B:")
1118         col.prop_search(md, "vertex_group_b", ob, "vertex_groups", text="")
1119         col.label(text="Default Weight B:")
1120         col.prop(md, "default_weight_b", text="")
1121
1122         col.label(text="Mix Set:")
1123         col.prop(md, "mix_set", text="")
1124
1125         # Common mask options
1126         layout.separator()
1127         self.vertex_weight_mask(layout, ob, md)
1128
1129     def VERTEX_WEIGHT_PROXIMITY(self, layout, ob, md):
1130         split = layout.split()
1131
1132         col = split.column()
1133         col.label(text="Vertex Group:")
1134         col.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
1135
1136         col = split.column()
1137         col.label(text="Target Object:")
1138         col.prop(md, "target", text="")
1139
1140         split = layout.split()
1141
1142         col = split.column()
1143         col.label(text="Distance:")
1144         col.prop(md, "proximity_mode", text="")
1145         if md.proximity_mode == 'GEOMETRY':
1146             col.row().prop(md, "proximity_geometry")
1147
1148         col = split.column()
1149         col.label()
1150         col.prop(md, "min_dist")
1151         col.prop(md, "max_dist")
1152
1153         layout.separator()
1154         layout.prop(md, "falloff_type")
1155
1156         # Common mask options
1157         layout.separator()
1158         self.vertex_weight_mask(layout, ob, md)
1159
1160     def SKIN(self, layout, ob, md):
1161         row = layout.row()
1162         row.operator("object.skin_armature_create", text="Create Armature")
1163         row.operator("mesh.customdata_skin_add")
1164
1165         layout.separator()
1166
1167         row = layout.row(align=True)
1168         row.prop(md, "branch_smoothing")
1169         row.prop(md, "use_smooth_shade")
1170
1171         split = layout.split()
1172
1173         col = split.column()
1174         col.label(text="Selected Vertices:")
1175         sub = col.column(align=True)
1176         sub.operator("object.skin_loose_mark_clear", text="Mark Loose").action = 'MARK'
1177         sub.operator("object.skin_loose_mark_clear", text="Clear Loose").action = 'CLEAR'
1178
1179         sub = col.column()
1180         sub.operator("object.skin_root_mark", text="Mark Root")
1181         sub.operator("object.skin_radii_equalize", text="Equalize Radii")
1182
1183         col = split.column()
1184         col.label(text="Symmetry Axes:")
1185         col.prop(md, "use_x_symmetry")
1186         col.prop(md, "use_y_symmetry")
1187         col.prop(md, "use_z_symmetry")
1188
1189     def TRIANGULATE(self, layout, ob, md):
1190         row = layout.row()
1191
1192         col = row.column()
1193         col.label(text="Quad Method:")
1194         col.prop(md, "quad_method", text="")
1195         col = row.column()
1196         col.label(text="Ngon Method:")
1197         col.prop(md, "ngon_method", text="")
1198
1199     def UV_WARP(self, layout, ob, md):
1200         split = layout.split()
1201         col = split.column()
1202         col.prop(md, "center")
1203
1204         col = split.column()
1205         col.label(text="UV Axis:")
1206         col.prop(md, "axis_u", text="")
1207         col.prop(md, "axis_v", text="")
1208
1209         split = layout.split()
1210         col = split.column()
1211         col.label(text="From:")
1212         col.prop(md, "object_from", text="")
1213
1214         col = split.column()
1215         col.label(text="To:")
1216         col.prop(md, "object_to", text="")
1217
1218         split = layout.split()
1219         col = split.column()
1220         obj = md.object_from
1221         if obj and obj.type == 'ARMATURE':
1222             col.label(text="Bone:")
1223             col.prop_search(md, "bone_from", obj.data, "bones", text="")
1224
1225         col = split.column()
1226         obj = md.object_to
1227         if obj and obj.type == 'ARMATURE':
1228             col.label(text="Bone:")
1229             col.prop_search(md, "bone_to", obj.data, "bones", text="")
1230
1231         split = layout.split()
1232
1233         col = split.column()
1234         col.label(text="Vertex Group:")
1235         col.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
1236
1237         col = split.column()
1238         col.label(text="UV Map:")
1239         col.prop_search(md, "uv_layer", ob.data, "uv_textures", text="")
1240
1241     def WIREFRAME(self, layout, ob, md):
1242         has_vgroup = bool(md.vertex_group)
1243
1244         split = layout.split()
1245
1246         col = split.column()
1247         col.prop(md, "thickness", text="Thickness")
1248
1249         row = col.row(align=True)
1250         row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
1251         sub = row.row(align=True)
1252         sub.active = has_vgroup
1253         sub.prop(md, "invert_vertex_group", text="", icon='ARROW_LEFTRIGHT')
1254         row = col.row(align=True)
1255         row.active = has_vgroup
1256         row.prop(md, "thickness_vertex_group", text="Factor")
1257
1258         col.prop(md, "use_crease", text="Crease Edges")
1259         col.prop(md, "crease_weight", text="Crease Weight")
1260
1261         col = split.column()
1262
1263         col.prop(md, "offset")
1264         col.prop(md, "use_even_offset", text="Even Thickness")
1265         col.prop(md, "use_relative_offset", text="Relative Thickness")
1266         col.prop(md, "use_boundary", text="Boundary")
1267         col.prop(md, "use_replace", text="Replace Original")
1268
1269         col.prop(md, "material_offset", text="Material Offset")
1270
1271     def DATA_TRANSFER(self, layout, ob, md):
1272         row = layout.row(align=True)
1273         row.prop(md, "object")
1274         sub = row.row(align=True)
1275         sub.active = bool(md.object)
1276         sub.prop(md, "use_object_transform", text="", icon='GROUP')
1277
1278         layout.separator()
1279
1280         split = layout.split(0.333)
1281         split.prop(md, "use_vert_data")
1282         use_vert = md.use_vert_data
1283         row = split.row()
1284         row.active = use_vert
1285         row.prop(md, "vert_mapping", text="")
1286         if use_vert:
1287             col = layout.column(align=True)
1288             split = col.split(0.333, align=True)
1289             sub = split.column(align=True)
1290             sub.prop(md, "data_types_verts")
1291             sub = split.column(align=True)
1292             row = sub.row(align=True)
1293             row.prop(md, "layers_vgroup_select_src", text="")
1294             row.label(icon='RIGHTARROW')
1295             row.prop(md, "layers_vgroup_select_dst", text="")
1296             row = sub.row(align=True)
1297             row.label("", icon='NONE')
1298
1299         layout.separator()
1300
1301         split = layout.split(0.333)
1302         split.prop(md, "use_edge_data")
1303         use_edge = md.use_edge_data
1304         row = split.row()
1305         row.active = use_edge
1306         row.prop(md, "edge_mapping", text="")
1307         if use_edge:
1308             col = layout.column(align=True)
1309             split = col.split(0.333, align=True)
1310             sub = split.column(align=True)
1311             sub.prop(md, "data_types_edges")
1312
1313         layout.separator()
1314
1315         split = layout.split(0.333)
1316         split.prop(md, "use_loop_data")
1317         use_loop = md.use_loop_data
1318         row = split.row()
1319         row.active = use_loop
1320         row.prop(md, "loop_mapping", text="")
1321         if use_loop:
1322             col = layout.column(align=True)
1323             split = col.split(0.333, align=True)
1324             sub = split.column(align=True)
1325             sub.prop(md, "data_types_loops")
1326             sub = split.column(align=True)
1327             row = sub.row(align=True)
1328             row.label("", icon='NONE')
1329             row = sub.row(align=True)
1330             row.prop(md, "layers_vcol_select_src", text="")
1331             row.label(icon='RIGHTARROW')
1332             row.prop(md, "layers_vcol_select_dst", text="")
1333             row = sub.row(align=True)
1334             row.prop(md, "layers_uv_select_src", text="")
1335             row.label(icon='RIGHTARROW')
1336             row.prop(md, "layers_uv_select_dst", text="")
1337             col.prop(md, "islands_precision")
1338
1339         layout.separator()
1340
1341         split = layout.split(0.333)
1342         split.prop(md, "use_poly_data")
1343         use_poly = md.use_poly_data
1344         row = split.row()
1345         row.active = use_poly
1346         row.prop(md, "poly_mapping", text="")
1347         if use_poly:
1348             col = layout.column(align=True)
1349             split = col.split(0.333, align=True)
1350             sub = split.column(align=True)
1351             sub.prop(md, "data_types_polys")
1352
1353         layout.separator()
1354
1355         split = layout.split()
1356         col = split.column()
1357         row = col.row(align=True)
1358         sub = row.row(align=True)
1359         sub.active = md.use_max_distance
1360         sub.prop(md, "max_distance")
1361         row.prop(md, "use_max_distance", text="", icon='STYLUS_PRESSURE')
1362
1363         col = split.column()
1364         col.prop(md, "ray_radius")
1365
1366         layout.separator()
1367
1368         split = layout.split()
1369         col = split.column()
1370         col.prop(md, "mix_mode")
1371         col.prop(md, "mix_factor")
1372
1373         col = split.column()
1374         row = col.row()
1375         row.active = bool(md.object)
1376         row.operator("object.datalayout_transfer", text="Generate Data Layers")
1377         row = col.row(align=True)
1378         row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
1379         sub = row.row(align=True)
1380         sub.active = bool(md.vertex_group)
1381         sub.prop(md, "invert_vertex_group", text="", icon='ARROW_LEFTRIGHT')
1382
1383     def NORMAL_EDIT(self, layout, ob, md):
1384         has_vgroup = bool(md.vertex_group)
1385         needs_object_offset = (((md.mode == 'RADIAL') and not md.target) or
1386                                ((md.mode == 'DIRECTIONAL') and md.use_direction_parallel))
1387
1388         row = layout.row()
1389         row.prop(md, "mode", expand=True)
1390
1391         split = layout.split()
1392
1393         col = split.column()
1394         col.prop(md, "target", text="")
1395         sub = col.column(align=True)
1396         sub.active = needs_object_offset
1397         sub.prop(md, "offset")
1398         row = col.row(align=True)
1399
1400         col = split.column()
1401         row = col.row()
1402         row.active = (md.mode == 'DIRECTIONAL')
1403         row.prop(md, "use_direction_parallel")
1404
1405         subcol = col.column(align=True)
1406         subcol.label("Mix Mode:")
1407         subcol.prop(md, "mix_mode", text="")
1408         subcol.prop(md, "mix_factor")
1409         row = subcol.row(align=True)
1410         row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
1411         sub = row.row(align=True)
1412         sub.active = has_vgroup
1413         sub.prop(md, "invert_vertex_group", text="", icon='ARROW_LEFTRIGHT')
1414         subcol.prop(md, "mix_limit")
1415
1416     def CORRECTIVE_SMOOTH(self, layout, ob, md):
1417         is_bind = md.is_bind
1418
1419         layout.prop(md, "factor", text="Factor")
1420         layout.prop(md, "iterations")
1421
1422         row = layout.row()
1423         row.prop(md, "smooth_type")
1424
1425         split = layout.split()
1426
1427         col = split.column()
1428         col.label(text="Vertex Group:")
1429         row = col.row(align=True)
1430         row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
1431         row.prop(md, "invert_vertex_group", text="", icon='ARROW_LEFTRIGHT')
1432
1433         col = split.column()
1434         col.prop(md, "use_only_smooth")
1435         col.prop(md, "use_pin_boundary")
1436
1437         layout.prop(md, "rest_source")
1438         if md.rest_source == 'BIND':
1439             layout.operator("object.correctivesmooth_bind", text="Unbind" if is_bind else "Bind")
1440
1441
1442 if __name__ == "__main__":  # only for live edit.
1443     bpy.utils.register_module(__name__)