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