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     @classmethod
36     def poll(cls, context):
37         ob = context.object
38         return ob and ob.type != 'GPENCIL'
39
40     def draw(self, context):
41         layout = self.layout
42
43         ob = context.object
44
45         layout.operator_menu_enum("object.modifier_add", "type")
46
47         for md in ob.modifiers:
48             box = layout.template_modifier(md)
49             if box:
50                 # match enum type to our functions, avoids a lookup table.
51                 getattr(self, md.type)(box, ob, md)
52
53     # the mt.type enum is (ab)used for a lookup on function names
54     # ...to avoid lengthy if statements
55     # so each type must have a function here.
56
57     def ARMATURE(self, layout, ob, md):
58         split = layout.split()
59
60         col = split.column()
61         col.label(text="Object:")
62         col.prop(md, "object", text="")
63         col.prop(md, "use_deform_preserve_volume")
64
65         col = split.column()
66         col.label(text="Bind To:")
67         col.prop(md, "use_vertex_groups", text="Vertex Groups")
68         col.prop(md, "use_bone_envelopes", text="Bone Envelopes")
69
70         layout.separator()
71
72         split = layout.split()
73
74         row = split.row(align=True)
75         row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
76         sub = row.row(align=True)
77         sub.active = bool(md.vertex_group)
78         sub.prop(md, "invert_vertex_group", text="", icon='ARROW_LEFTRIGHT')
79
80         split.prop(md, "use_multi_modifier")
81
82     def ARRAY(self, layout, ob, md):
83         layout.prop(md, "fit_type")
84
85         if md.fit_type == 'FIXED_COUNT':
86             layout.prop(md, "count")
87         elif md.fit_type == 'FIT_LENGTH':
88             layout.prop(md, "fit_length")
89         elif md.fit_type == 'FIT_CURVE':
90             layout.prop(md, "curve")
91
92         layout.separator()
93
94         split = layout.split()
95
96         col = split.column()
97         col.prop(md, "use_constant_offset")
98         sub = col.column()
99         sub.active = md.use_constant_offset
100         sub.prop(md, "constant_offset_displace", text="")
101
102         col.separator()
103
104         col.prop(md, "use_merge_vertices", text="Merge")
105         sub = col.column()
106         sub.active = md.use_merge_vertices
107         sub.prop(md, "use_merge_vertices_cap", text="First Last")
108         sub.prop(md, "merge_threshold", text="Distance")
109
110         col = split.column()
111         col.prop(md, "use_relative_offset")
112         sub = col.column()
113         sub.active = md.use_relative_offset
114         sub.prop(md, "relative_offset_displace", text="")
115
116         col.separator()
117
118         col.prop(md, "use_object_offset")
119         sub = col.column()
120         sub.active = md.use_object_offset
121         sub.prop(md, "offset_object", text="")
122
123         row = layout.row()
124         split = row.split()
125         col = split.column()
126         col.label(text="UVs:")
127         sub = col.column(align=True)
128         sub.prop(md, "offset_u")
129         sub.prop(md, "offset_v")
130         layout.separator()
131
132         layout.prop(md, "start_cap")
133         layout.prop(md, "end_cap")
134
135     def BEVEL(self, layout, ob, md):
136         split = layout.split()
137
138         col = split.column()
139         col.prop(md, "width")
140         col.prop(md, "segments")
141         col.prop(md, "profile")
142         col.prop(md, "material")
143
144         col = split.column()
145         col.prop(md, "use_only_vertices")
146         col.prop(md, "use_clamp_overlap")
147         col.prop(md, "loop_slide")
148         col.prop(md, "mark_seam")
149         col.prop(md, "mark_sharp")
150
151         layout.label(text="Limit Method:")
152         layout.row().prop(md, "limit_method", expand=True)
153         if md.limit_method == 'ANGLE':
154             layout.prop(md, "angle_limit")
155         elif md.limit_method == 'VGROUP':
156             layout.label(text="Vertex Group:")
157             layout.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
158
159         layout.label(text="Width Method:")
160         layout.row().prop(md, "offset_type", expand=True)
161
162         layout.label(text="Normal Mode")
163         layout.row().prop(md, "hnmode", expand=True)
164         layout.prop(md, "hn_strength")
165         layout.prop(md, "set_wn_strength")
166
167
168     def BOOLEAN(self, layout, ob, md):
169         split = layout.split()
170
171         col = split.column()
172         col.label(text="Operation:")
173         col.prop(md, "operation", text="")
174
175         col = split.column()
176         col.label(text="Object:")
177         col.prop(md, "object", text="")
178
179         layout.prop(md, "double_threshold")
180
181         if bpy.app.debug:
182             layout.prop(md, "debug_options")
183
184     def BUILD(self, layout, ob, md):
185         split = layout.split()
186
187         col = split.column()
188         col.prop(md, "frame_start")
189         col.prop(md, "frame_duration")
190         col.prop(md, "use_reverse")
191
192         col = split.column()
193         col.prop(md, "use_random_order")
194         sub = col.column()
195         sub.active = md.use_random_order
196         sub.prop(md, "seed")
197
198     def MESH_CACHE(self, layout, ob, md):
199         layout.prop(md, "cache_format")
200         layout.prop(md, "filepath")
201
202         if md.cache_format == 'ABC':
203             layout.prop(md, "sub_object")
204
205         layout.label(text="Evaluation:")
206         layout.prop(md, "factor", slider=True)
207         layout.prop(md, "deform_mode")
208         layout.prop(md, "interpolation")
209
210         layout.label(text="Time Mapping:")
211
212         row = layout.row()
213         row.prop(md, "time_mode", expand=True)
214         row = layout.row()
215         row.prop(md, "play_mode", expand=True)
216         if md.play_mode == 'SCENE':
217             layout.prop(md, "frame_start")
218             layout.prop(md, "frame_scale")
219         else:
220             time_mode = md.time_mode
221             if time_mode == 'FRAME':
222                 layout.prop(md, "eval_frame")
223             elif time_mode == 'TIME':
224                 layout.prop(md, "eval_time")
225             elif time_mode == 'FACTOR':
226                 layout.prop(md, "eval_factor")
227
228         layout.label(text="Axis Mapping:")
229         split = layout.split(percentage=0.5, align=True)
230         split.alert = (md.forward_axis[-1] == md.up_axis[-1])
231         split.label("Forward/Up Axis:")
232         split.prop(md, "forward_axis", text="")
233         split.prop(md, "up_axis", text="")
234         split = layout.split(percentage=0.5)
235         split.label(text="Flip Axis:")
236         row = split.row()
237         row.prop(md, "flip_axis")
238
239     def MESH_SEQUENCE_CACHE(self, layout, ob, md):
240         layout.label(text="Cache File Properties:")
241         box = layout.box()
242         box.template_cache_file(md, "cache_file")
243
244         cache_file = md.cache_file
245
246         layout.label(text="Modifier Properties:")
247         box = layout.box()
248
249         if cache_file is not None:
250             box.prop_search(md, "object_path", cache_file, "object_paths")
251
252         if ob.type == 'MESH':
253             box.row().prop(md, "read_data")
254
255     def CAST(self, layout, ob, md):
256         split = layout.split(percentage=0.25)
257
258         split.label(text="Cast Type:")
259         split.prop(md, "cast_type", text="")
260
261         split = layout.split(percentage=0.25)
262
263         col = split.column()
264         col.prop(md, "use_x")
265         col.prop(md, "use_y")
266         col.prop(md, "use_z")
267
268         col = split.column()
269         col.prop(md, "factor")
270         col.prop(md, "radius")
271         col.prop(md, "size")
272         col.prop(md, "use_radius_as_size")
273
274         split = layout.split()
275
276         col = split.column()
277         col.label(text="Vertex Group:")
278         col.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
279         col = split.column()
280         col.label(text="Control Object:")
281         col.prop(md, "object", text="")
282         if md.object:
283             col.prop(md, "use_transform")
284
285     def CLOTH(self, layout, ob, md):
286         layout.label(text="Settings are inside the Physics tab")
287
288     def COLLISION(self, layout, ob, md):
289         layout.label(text="Settings are inside the Physics tab")
290
291     def CURVE(self, layout, ob, md):
292         split = layout.split()
293
294         col = split.column()
295         col.label(text="Object:")
296         col.prop(md, "object", text="")
297         col = split.column()
298         col.label(text="Vertex Group:")
299         col.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
300         layout.label(text="Deformation Axis:")
301         layout.row().prop(md, "deform_axis", expand=True)
302
303     def DECIMATE(self, layout, ob, md):
304         decimate_type = md.decimate_type
305
306         row = layout.row()
307         row.prop(md, "decimate_type", expand=True)
308
309         if decimate_type == 'COLLAPSE':
310             has_vgroup = bool(md.vertex_group)
311             layout.prop(md, "ratio")
312
313             split = layout.split()
314
315             col = split.column()
316             row = col.row(align=True)
317             row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
318             row.prop(md, "invert_vertex_group", text="", icon='ARROW_LEFTRIGHT')
319
320             layout_info = col
321
322             col = split.column()
323             row = col.row()
324             row.active = has_vgroup
325             row.prop(md, "vertex_group_factor")
326
327             col.prop(md, "use_collapse_triangulate")
328             row = col.split(percentage=0.75)
329             row.prop(md, "use_symmetry")
330             row.prop(md, "symmetry_axis", text="")
331
332         elif decimate_type == 'UNSUBDIV':
333             layout.prop(md, "iterations")
334             layout_info = layout
335         else:  # decimate_type == 'DISSOLVE':
336             layout.prop(md, "angle_limit")
337             layout.prop(md, "use_dissolve_boundaries")
338             layout.label("Delimit:")
339             row = layout.row()
340             row.prop(md, "delimit")
341             layout_info = layout
342
343         layout_info.label(
344             text=iface_("Face Count: {:,}".format(md.face_count)),
345             translate=False,
346         )
347
348     def DISPLACE(self, layout, ob, md):
349         has_texture = (md.texture is not None)
350
351         col = layout.column(align=True)
352         col.label(text="Texture:")
353         col.template_ID(md, "texture", new="texture.new")
354
355         split = layout.split()
356
357         col = split.column(align=True)
358         col.label(text="Direction:")
359         col.prop(md, "direction", text="")
360         if md.direction in {'X', 'Y', 'Z', 'RGB_TO_XYZ'}:
361             col.label(text="Space:")
362             col.prop(md, "space", text="")
363         col.label(text="Vertex Group:")
364         col.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
365
366         col = split.column(align=True)
367         col.active = has_texture
368         col.label(text="Texture Coordinates:")
369         col.prop(md, "texture_coords", text="")
370         if md.texture_coords == 'OBJECT':
371             col.label(text="Object:")
372             col.prop(md, "texture_coords_object", text="")
373         elif md.texture_coords == 'UV' and ob.type == 'MESH':
374             col.label(text="UV Map:")
375             col.prop_search(md, "uv_layer", ob.data, "uv_layers", text="")
376
377         layout.separator()
378
379         row = layout.row()
380         row.prop(md, "mid_level")
381         row.prop(md, "strength")
382
383     def DYNAMIC_PAINT(self, layout, ob, md):
384         layout.label(text="Settings are inside the Physics tab")
385
386     def EDGE_SPLIT(self, layout, ob, md):
387         split = layout.split()
388
389         col = split.column()
390         col.prop(md, "use_edge_angle", text="Edge Angle")
391         sub = col.column()
392         sub.active = md.use_edge_angle
393         sub.prop(md, "split_angle")
394
395         split.prop(md, "use_edge_sharp", text="Sharp Edges")
396
397     def EXPLODE(self, layout, ob, md):
398         split = layout.split()
399
400         col = split.column()
401         col.label(text="Vertex Group:")
402         col.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
403         sub = col.column()
404         sub.active = bool(md.vertex_group)
405         sub.prop(md, "protect")
406         col.label(text="Particle UV")
407         col.prop_search(md, "particle_uv", ob.data, "uv_layers", text="")
408
409         col = split.column()
410         col.prop(md, "use_edge_cut")
411         col.prop(md, "show_unborn")
412         col.prop(md, "show_alive")
413         col.prop(md, "show_dead")
414         col.prop(md, "use_size")
415
416         layout.operator("object.explode_refresh", text="Refresh")
417
418     def FLUID_SIMULATION(self, layout, ob, md):
419         layout.label(text="Settings are inside the Physics tab")
420
421     def HOOK(self, layout, ob, md):
422         use_falloff = (md.falloff_type != 'NONE')
423         split = layout.split()
424
425         col = split.column()
426         col.label(text="Object:")
427         col.prop(md, "object", text="")
428         if md.object and md.object.type == 'ARMATURE':
429             col.label(text="Bone:")
430             col.prop_search(md, "subtarget", md.object.data, "bones", text="")
431         col = split.column()
432         col.label(text="Vertex Group:")
433         col.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
434
435         layout.separator()
436
437         row = layout.row(align=True)
438         if use_falloff:
439             row.prop(md, "falloff_radius")
440         row.prop(md, "strength", slider=True)
441         layout.prop(md, "falloff_type")
442
443         col = layout.column()
444         if use_falloff:
445             if md.falloff_type == 'CURVE':
446                 col.template_curve_mapping(md, "falloff_curve")
447
448         split = layout.split()
449
450         col = split.column()
451         col.prop(md, "use_falloff_uniform")
452
453         if ob.mode == 'EDIT':
454             row = col.row(align=True)
455             row.operator("object.hook_reset", text="Reset")
456             row.operator("object.hook_recenter", text="Recenter")
457
458             row = layout.row(align=True)
459             row.operator("object.hook_select", text="Select")
460             row.operator("object.hook_assign", text="Assign")
461
462     def LAPLACIANDEFORM(self, layout, ob, md):
463         is_bind = md.is_bind
464
465         layout.prop(md, "iterations")
466
467         row = layout.row()
468         row.active = not is_bind
469         row.label(text="Anchors Vertex Group:")
470
471         row = layout.row()
472         row.enabled = not is_bind
473         row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
474
475         layout.separator()
476
477         row = layout.row()
478         row.enabled = bool(md.vertex_group)
479         row.operator("object.laplaciandeform_bind", text="Unbind" if is_bind else "Bind")
480
481     def LAPLACIANSMOOTH(self, layout, ob, md):
482         layout.prop(md, "iterations")
483
484         split = layout.split(percentage=0.25)
485
486         col = split.column()
487         col.label(text="Axis:")
488         col.prop(md, "use_x")
489         col.prop(md, "use_y")
490         col.prop(md, "use_z")
491
492         col = split.column()
493         col.label(text="Lambda:")
494         col.prop(md, "lambda_factor", text="Factor")
495         col.prop(md, "lambda_border", text="Border")
496
497         col.separator()
498         col.prop(md, "use_volume_preserve")
499         col.prop(md, "use_normalized")
500
501         layout.label(text="Vertex Group:")
502         layout.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
503
504     def LATTICE(self, layout, ob, md):
505         split = layout.split()
506
507         col = split.column()
508         col.label(text="Object:")
509         col.prop(md, "object", text="")
510
511         col = split.column()
512         col.label(text="Vertex Group:")
513         col.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
514
515         layout.separator()
516         layout.prop(md, "strength", slider=True)
517
518     def MASK(self, layout, ob, md):
519         split = layout.split()
520
521         col = split.column()
522         col.label(text="Mode:")
523         col.prop(md, "mode", text="")
524
525         col = split.column()
526         if md.mode == 'ARMATURE':
527             col.label(text="Armature:")
528             row = col.row(align=True)
529             row.prop(md, "armature", text="")
530             sub = row.row(align=True)
531             sub.active = (md.armature is not None)
532             sub.prop(md, "invert_vertex_group", text="", icon='ARROW_LEFTRIGHT')
533         elif md.mode == 'VERTEX_GROUP':
534             col.label(text="Vertex Group:")
535             row = col.row(align=True)
536             row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
537             sub = row.row(align=True)
538             sub.active = bool(md.vertex_group)
539             sub.prop(md, "invert_vertex_group", text="", icon='ARROW_LEFTRIGHT')
540
541     def MESH_DEFORM(self, layout, ob, md):
542         split = layout.split()
543
544         col = split.column()
545         col.enabled = not md.is_bound
546         col.label(text="Object:")
547         col.prop(md, "object", text="")
548
549         col = split.column()
550         col.label(text="Vertex Group:")
551         row = col.row(align=True)
552         row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
553         sub = row.row(align=True)
554         sub.active = bool(md.vertex_group)
555         sub.prop(md, "invert_vertex_group", text="", icon='ARROW_LEFTRIGHT')
556
557         layout.separator()
558         row = layout.row()
559         row.enabled = not md.is_bound
560         row.prop(md, "precision")
561         row.prop(md, "use_dynamic_bind")
562
563         layout.separator()
564         if md.is_bound:
565             layout.operator("object.meshdeform_bind", text="Unbind")
566         else:
567             layout.operator("object.meshdeform_bind", text="Bind")
568
569     def MIRROR(self, layout, ob, md):
570         split = layout.split(percentage=0.25)
571
572         col = split.column()
573         col.label(text="Axis:")
574         col.prop(md, "use_x")
575         col.prop(md, "use_y")
576         col.prop(md, "use_z")
577
578         col = split.column()
579         col.label(text="Options:")
580         col.prop(md, "use_mirror_merge", text="Merge")
581         col.prop(md, "use_clip", text="Clipping")
582         col.prop(md, "use_mirror_vertex_groups", text="Vertex Groups")
583
584         col = split.column()
585         col.label(text="Textures:")
586         col.prop(md, "use_mirror_u", text="Flip U")
587         col.prop(md, "use_mirror_v", text="Flip V")
588
589         col = layout.column(align=True)
590
591         if md.use_mirror_u:
592             col.prop(md, "mirror_offset_u")
593
594         if md.use_mirror_v:
595             col.prop(md, "mirror_offset_v")
596
597         col = layout.column(align=True)
598         col.prop(md, "offset_u")
599         col.prop(md, "offset_v")
600
601         col = layout.column()
602
603         if md.use_mirror_merge is True:
604             col.prop(md, "merge_threshold")
605         col.label(text="Mirror Object:")
606         col.prop(md, "mirror_object", text="")
607
608     def MULTIRES(self, layout, ob, md):
609         layout.row().prop(md, "subdivision_type", expand=True)
610
611         split = layout.split()
612         col = split.column()
613         col.prop(md, "levels", text="Preview")
614         col.prop(md, "sculpt_levels", text="Sculpt")
615         col.prop(md, "render_levels", text="Render")
616
617         col = split.column()
618
619         col.enabled = ob.mode != 'EDIT'
620         col.operator("object.multires_subdivide", text="Subdivide")
621         col.operator("object.multires_higher_levels_delete", text="Delete Higher")
622         col.operator("object.multires_reshape", text="Reshape")
623         col.operator("object.multires_base_apply", text="Apply Base")
624         col.prop(md, "use_subsurf_uv")
625         col.prop(md, "show_only_control_edges")
626
627         layout.separator()
628
629         col = layout.column()
630         row = col.row()
631         if md.is_external:
632             row.operator("object.multires_external_pack", text="Pack External")
633             row.label()
634             row = col.row()
635             row.prop(md, "filepath", text="")
636         else:
637             row.operator("object.multires_external_save", text="Save External...")
638             row.label()
639
640     def OCEAN(self, layout, ob, md):
641         if not bpy.app.build_options.mod_oceansim:
642             layout.label("Built without OceanSim modifier")
643             return
644
645         layout.prop(md, "geometry_mode")
646
647         if md.geometry_mode == 'GENERATE':
648             row = layout.row()
649             row.prop(md, "repeat_x")
650             row.prop(md, "repeat_y")
651
652         layout.separator()
653
654         split = layout.split()
655
656         col = split.column()
657         col.prop(md, "time")
658         col.prop(md, "depth")
659         col.prop(md, "random_seed")
660
661         col = split.column()
662         col.prop(md, "resolution")
663         col.prop(md, "size")
664         col.prop(md, "spatial_size")
665
666         layout.label("Waves:")
667
668         split = layout.split()
669
670         col = split.column()
671         col.prop(md, "choppiness")
672         col.prop(md, "wave_scale", text="Scale")
673         col.prop(md, "wave_scale_min")
674         col.prop(md, "wind_velocity")
675
676         col = split.column()
677         col.prop(md, "wave_alignment", text="Alignment")
678         sub = col.column()
679         sub.active = (md.wave_alignment > 0.0)
680         sub.prop(md, "wave_direction", text="Direction")
681         sub.prop(md, "damping")
682
683         layout.separator()
684
685         layout.prop(md, "use_normals")
686
687         split = layout.split()
688
689         col = split.column()
690         col.prop(md, "use_foam")
691         sub = col.row()
692         sub.active = md.use_foam
693         sub.prop(md, "foam_coverage", text="Coverage")
694
695         col = split.column()
696         col.active = md.use_foam
697         col.label("Foam Data Layer Name:")
698         col.prop(md, "foam_layer_name", text="")
699
700         layout.separator()
701
702         if md.is_cached:
703             layout.operator("object.ocean_bake", text="Free Bake").free = True
704         else:
705             layout.operator("object.ocean_bake").free = False
706
707         split = layout.split()
708         split.enabled = not md.is_cached
709
710         col = split.column(align=True)
711         col.prop(md, "frame_start", text="Start")
712         col.prop(md, "frame_end", text="End")
713
714         col = split.column(align=True)
715         col.label(text="Cache path:")
716         col.prop(md, "filepath", text="")
717
718         split = layout.split()
719         split.enabled = not md.is_cached
720
721         col = split.column()
722         col.active = md.use_foam
723         col.prop(md, "bake_foam_fade")
724
725         col = split.column()
726
727     def PARTICLE_INSTANCE(self, layout, ob, md):
728         layout.prop(md, "object")
729         if md.object:
730             layout.prop_search(md, "particle_system", md.object, "particle_systems", text="Particle System")
731         else:
732             layout.prop(md, "particle_system_index", text="Particle System")
733
734         split = layout.split()
735         col = split.column()
736         col.label(text="Create From:")
737         layout.prop(md, "space", text="")
738         col.prop(md, "use_normal")
739         col.prop(md, "use_children")
740         col.prop(md, "use_size")
741
742         col = split.column()
743         col.label(text="Show Particles When:")
744         col.prop(md, "show_alive")
745         col.prop(md, "show_unborn")
746         col.prop(md, "show_dead")
747
748         row = layout.row(align=True)
749         row.prop(md, "particle_amount", text="Amount")
750         row.prop(md, "particle_offset", text="Offset")
751
752         row = layout.row(align=True)
753         row.prop(md, "axis", expand=True)
754
755         layout.separator()
756
757         layout.prop(md, "use_path", text="Create Along Paths")
758
759         col = layout.column()
760         col.active = md.use_path
761         col.prop(md, "use_preserve_shape")
762
763         row = col.row(align=True)
764         row.prop(md, "position", slider=True)
765         row.prop(md, "random_position", text="Random", slider=True)
766         row = col.row(align=True)
767         row.prop(md, "rotation", slider=True)
768         row.prop(md, "random_rotation", text="Random", slider=True)
769
770         layout.separator()
771
772         col = layout.column()
773         col.prop_search(md, "index_layer_name", ob.data, "vertex_colors", text="Index Layer")
774         col.prop_search(md, "value_layer_name", ob.data, "vertex_colors", text="Value Layer")
775
776     def PARTICLE_SYSTEM(self, layout, ob, md):
777         layout.label(text="Settings can be found inside the Particle context")
778
779     def SCREW(self, layout, ob, md):
780         split = layout.split()
781
782         col = split.column()
783         col.prop(md, "axis")
784         col.prop(md, "object", text="AxisOb")
785         col.prop(md, "angle")
786         col.prop(md, "steps")
787         col.prop(md, "render_steps")
788         col.prop(md, "use_smooth_shade")
789         col.prop(md, "use_merge_vertices")
790         sub = col.column()
791         sub.active = md.use_merge_vertices
792         sub.prop(md, "merge_threshold")
793
794         col = split.column()
795         row = col.row()
796         row.active = (md.object is None or md.use_object_screw_offset is False)
797         row.prop(md, "screw_offset")
798         row = col.row()
799         row.active = (md.object is not None)
800         row.prop(md, "use_object_screw_offset")
801         col.prop(md, "use_normal_calculate")
802         col.prop(md, "use_normal_flip")
803         col.prop(md, "iterations")
804         col.prop(md, "use_stretch_u")
805         col.prop(md, "use_stretch_v")
806
807     def SHRINKWRAP(self, layout, ob, md):
808         split = layout.split()
809         col = split.column()
810         col.label(text="Target:")
811         col.prop(md, "target", text="")
812         col = split.column()
813         col.label(text="Vertex Group:")
814         row = col.row(align=True)
815         row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
816         row.prop(md, "invert_vertex_group", text="", icon='ARROW_LEFTRIGHT')
817
818         split = layout.split()
819
820         col = split.column()
821         col.prop(md, "offset")
822
823         col = split.column()
824         col.label(text="Mode:")
825         col.prop(md, "wrap_method", text="")
826
827         if md.wrap_method == 'PROJECT':
828             split = layout.split()
829             col = split.column()
830             col.prop(md, "subsurf_levels")
831             col = split.column()
832
833             col.prop(md, "project_limit", text="Limit")
834             split = layout.split(percentage=0.25)
835
836             col = split.column()
837             col.label(text="Axis:")
838             col.prop(md, "use_project_x")
839             col.prop(md, "use_project_y")
840             col.prop(md, "use_project_z")
841
842             col = split.column()
843             col.label(text="Direction:")
844             col.prop(md, "use_negative_direction")
845             col.prop(md, "use_positive_direction")
846
847             col = split.column()
848             col.label(text="Cull Faces:")
849             col.prop(md, "cull_face", expand=True)
850
851             layout.prop(md, "auxiliary_target")
852
853         elif md.wrap_method == 'NEAREST_SURFACEPOINT':
854             layout.prop(md, "use_keep_above_surface")
855
856     def SIMPLE_DEFORM(self, layout, ob, md):
857
858         layout.row().prop(md, "deform_method", expand=True)
859
860         split = layout.split()
861
862         col = split.column()
863         col.label(text="Vertex Group:")
864         row = col.row(align=True)
865         row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
866         row.prop(md, "invert_vertex_group", text="", icon='ARROW_LEFTRIGHT')
867
868         split = layout.split()
869
870         col = split.column()
871         col.label(text="Axis, Origin:")
872         col.prop(md, "origin", text="")
873
874         col.prop(md, "deform_axis")
875
876         if md.deform_method in {'TAPER', 'STRETCH', 'TWIST'}:
877             row = col.row(align=True)
878             row.label(text="Lock:")
879             deform_axis = md.deform_axis
880             if deform_axis != 'X':
881                 row.prop(md, "lock_x")
882             if deform_axis != 'Y':
883                 row.prop(md, "lock_y")
884             if deform_axis != 'Z':
885                 row.prop(md, "lock_z")
886
887         col = split.column()
888         col.label(text="Deform:")
889         if md.deform_method in {'TAPER', 'STRETCH'}:
890             col.prop(md, "factor")
891         else:
892             col.prop(md, "angle")
893         col.prop(md, "limits", slider=True)
894
895     def SMOKE(self, layout, ob, md):
896         layout.label(text="Settings are inside the Physics tab")
897
898     def SMOOTH(self, layout, ob, md):
899         split = layout.split(percentage=0.25)
900
901         col = split.column()
902         col.label(text="Axis:")
903         col.prop(md, "use_x")
904         col.prop(md, "use_y")
905         col.prop(md, "use_z")
906
907         col = split.column()
908         col.prop(md, "factor")
909         col.prop(md, "iterations")
910         col.label(text="Vertex Group:")
911         col.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
912
913     def SOFT_BODY(self, layout, ob, md):
914         layout.label(text="Settings are inside the Physics tab")
915
916     def SOLIDIFY(self, layout, ob, md):
917         split = layout.split()
918
919         col = split.column()
920         col.prop(md, "thickness")
921         col.prop(md, "thickness_clamp")
922
923         col.separator()
924
925         row = col.row(align=True)
926         row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
927         sub = row.row(align=True)
928         sub.active = bool(md.vertex_group)
929         sub.prop(md, "invert_vertex_group", text="", icon='ARROW_LEFTRIGHT')
930
931         sub = col.row()
932         sub.active = bool(md.vertex_group)
933         sub.prop(md, "thickness_vertex_group", text="Factor")
934
935         col.label(text="Crease:")
936         col.prop(md, "edge_crease_inner", text="Inner")
937         col.prop(md, "edge_crease_outer", text="Outer")
938         col.prop(md, "edge_crease_rim", text="Rim")
939
940         col = split.column()
941
942         col.prop(md, "offset")
943         col.prop(md, "use_flip_normals")
944
945         col.prop(md, "use_even_offset")
946         col.prop(md, "use_quality_normals")
947         col.prop(md, "use_rim")
948         col_rim = col.column()
949         col_rim.active = md.use_rim
950         col_rim.prop(md, "use_rim_only")
951
952         col.separator()
953
954         col.label(text="Material Index Offset:")
955
956         sub = col.column()
957         row = sub.split(align=True, percentage=0.4)
958         row.prop(md, "material_offset", text="")
959         row = row.row(align=True)
960         row.active = md.use_rim
961         row.prop(md, "material_offset_rim", text="Rim")
962
963     def SUBSURF(self, layout, ob, md):
964         from bpy import context
965         layout.row().prop(md, "subdivision_type", expand=True)
966
967         split = layout.split()
968         col = split.column()
969
970         scene = context.scene
971         engine = context.engine
972         show_adaptive_options = (
973             engine == 'CYCLES' and md == ob.modifiers[-1] and
974             scene.cycles.feature_set == 'EXPERIMENTAL'
975         )
976         if show_adaptive_options:
977             col.label(text="View:")
978             col.prop(md, "levels", text="Levels")
979             col.label(text="Render:")
980             col.prop(ob.cycles, "use_adaptive_subdivision", text="Adaptive")
981             if ob.cycles.use_adaptive_subdivision:
982                 col.prop(ob.cycles, "dicing_rate")
983             else:
984                 col.prop(md, "render_levels", text="Levels")
985         else:
986             col.label(text="Subdivisions:")
987             col.prop(md, "levels", text="View")
988             col.prop(md, "render_levels", text="Render")
989
990         col = split.column()
991         col.label(text="Options:")
992
993         sub = col.column()
994         sub.active = (not show_adaptive_options) or (not ob.cycles.use_adaptive_subdivision)
995         sub.prop(md, "use_subsurf_uv")
996
997         col.prop(md, "show_only_control_edges")
998         if hasattr(md, "use_opensubdiv"):
999             col.prop(md, "use_opensubdiv")
1000
1001         if show_adaptive_options and ob.cycles.use_adaptive_subdivision:
1002             col = layout.column(align=True)
1003             col.scale_y = 0.6
1004             col.separator()
1005             col.label("Final Dicing Rate:")
1006             col.separator()
1007
1008             render = max(scene.cycles.dicing_rate * ob.cycles.dicing_rate, 0.1)
1009             preview = max(scene.cycles.preview_dicing_rate * ob.cycles.dicing_rate, 0.1)
1010             col.label(f"Render {render:10.2f} px, Preview {preview:10.2f} px")
1011
1012     def SURFACE(self, layout, ob, md):
1013         layout.label(text="Settings are inside the Physics tab")
1014
1015     def SURFACE_DEFORM(self, layout, ob, md):
1016         col = layout.column()
1017         col.active = not md.is_bound
1018
1019         col.prop(md, "target")
1020         col.prop(md, "falloff")
1021
1022         layout.separator()
1023
1024         col = layout.column()
1025
1026         if md.is_bound:
1027             col.operator("object.surfacedeform_bind", text="Unbind")
1028         else:
1029             col.active = md.target is not None
1030             col.operator("object.surfacedeform_bind", text="Bind")
1031
1032     def UV_PROJECT(self, layout, ob, md):
1033         split = layout.split()
1034         col = split.column()
1035         col.prop_search(md, "uv_layer", ob.data, "uv_layers")
1036         col.separator()
1037
1038         col.prop(md, "projector_count", text="Projectors")
1039         for proj in md.projectors:
1040             col.prop(proj, "object", text="")
1041
1042         col = split.column()
1043         sub = col.column(align=True)
1044         sub.prop(md, "aspect_x", text="Aspect X")
1045         sub.prop(md, "aspect_y", text="Aspect Y")
1046
1047         sub = col.column(align=True)
1048         sub.prop(md, "scale_x", text="Scale X")
1049         sub.prop(md, "scale_y", text="Scale Y")
1050
1051     def WARP(self, layout, ob, md):
1052         use_falloff = (md.falloff_type != 'NONE')
1053         split = layout.split()
1054
1055         col = split.column()
1056         col.label(text="From:")
1057         col.prop(md, "object_from", text="")
1058
1059         col.prop(md, "use_volume_preserve")
1060
1061         col = split.column()
1062         col.label(text="To:")
1063         col.prop(md, "object_to", text="")
1064         col.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
1065
1066         col = layout.column()
1067
1068         row = col.row(align=True)
1069         row.prop(md, "strength")
1070         if use_falloff:
1071             row.prop(md, "falloff_radius")
1072
1073         col.prop(md, "falloff_type")
1074         if use_falloff:
1075             if md.falloff_type == 'CURVE':
1076                 col.template_curve_mapping(md, "falloff_curve")
1077
1078         # 2 new columns
1079         split = layout.split()
1080         col = split.column()
1081         col.label(text="Texture:")
1082         col.template_ID(md, "texture", new="texture.new")
1083
1084         col = split.column()
1085         col.label(text="Texture Coordinates:")
1086         col.prop(md, "texture_coords", text="")
1087
1088         if md.texture_coords == 'OBJECT':
1089             layout.prop(md, "texture_coords_object", text="Object")
1090         elif md.texture_coords == 'UV' and ob.type == 'MESH':
1091             layout.prop_search(md, "uv_layer", ob.data, "uv_layers")
1092
1093     def WAVE(self, layout, ob, md):
1094         split = layout.split()
1095
1096         col = split.column()
1097         col.label(text="Motion:")
1098         col.prop(md, "use_x")
1099         col.prop(md, "use_y")
1100         col.prop(md, "use_cyclic")
1101
1102         col = split.column()
1103         col.prop(md, "use_normal")
1104         sub = col.column()
1105         sub.active = md.use_normal
1106         sub.prop(md, "use_normal_x", text="X")
1107         sub.prop(md, "use_normal_y", text="Y")
1108         sub.prop(md, "use_normal_z", text="Z")
1109
1110         split = layout.split()
1111
1112         col = split.column()
1113         col.label(text="Time:")
1114         sub = col.column(align=True)
1115         sub.prop(md, "time_offset", text="Offset")
1116         sub.prop(md, "lifetime", text="Life")
1117         col.prop(md, "damping_time", text="Damping")
1118
1119         col = split.column()
1120         col.label(text="Position:")
1121         sub = col.column(align=True)
1122         sub.prop(md, "start_position_x", text="X")
1123         sub.prop(md, "start_position_y", text="Y")
1124         col.prop(md, "falloff_radius", text="Falloff")
1125
1126         layout.separator()
1127
1128         layout.prop(md, "start_position_object")
1129         layout.prop_search(md, "vertex_group", ob, "vertex_groups")
1130         split = layout.split(percentage=0.33)
1131         col = split.column()
1132         col.label(text="Texture")
1133         col = split.column()
1134         col.template_ID(md, "texture", new="texture.new")
1135         layout.prop(md, "texture_coords")
1136         if md.texture_coords == 'UV' and ob.type == 'MESH':
1137             layout.prop_search(md, "uv_layer", ob.data, "uv_layers")
1138         elif md.texture_coords == 'OBJECT':
1139             layout.prop(md, "texture_coords_object")
1140
1141         layout.separator()
1142
1143         split = layout.split()
1144
1145         col = split.column()
1146         col.prop(md, "speed", slider=True)
1147         col.prop(md, "height", slider=True)
1148
1149         col = split.column()
1150         col.prop(md, "width", slider=True)
1151         col.prop(md, "narrowness", slider=True)
1152
1153     def REMESH(self, layout, ob, md):
1154         if not bpy.app.build_options.mod_remesh:
1155             layout.label("Built without Remesh modifier")
1156             return
1157
1158         layout.prop(md, "mode")
1159
1160         row = layout.row()
1161         row.prop(md, "octree_depth")
1162         row.prop(md, "scale")
1163
1164         if md.mode == 'SHARP':
1165             layout.prop(md, "sharpness")
1166
1167         layout.prop(md, "use_smooth_shade")
1168         layout.prop(md, "use_remove_disconnected")
1169         row = layout.row()
1170         row.active = md.use_remove_disconnected
1171         row.prop(md, "threshold")
1172
1173     @staticmethod
1174     def vertex_weight_mask(layout, ob, md):
1175         layout.label(text="Influence/Mask Options:")
1176
1177         split = layout.split(percentage=0.4)
1178         split.label(text="Global Influence:")
1179         split.prop(md, "mask_constant", text="")
1180
1181         if not md.mask_texture:
1182             split = layout.split(percentage=0.4)
1183             split.label(text="Vertex Group Mask:")
1184             split.prop_search(md, "mask_vertex_group", ob, "vertex_groups", text="")
1185
1186         if not md.mask_vertex_group:
1187             split = layout.split(percentage=0.4)
1188             split.label(text="Texture Mask:")
1189             split.template_ID(md, "mask_texture", new="texture.new")
1190             if md.mask_texture:
1191                 split = layout.split()
1192
1193                 col = split.column()
1194                 col.label(text="Texture Coordinates:")
1195                 col.prop(md, "mask_tex_mapping", text="")
1196
1197                 col = split.column()
1198                 col.label(text="Use Channel:")
1199                 col.prop(md, "mask_tex_use_channel", text="")
1200
1201                 if md.mask_tex_mapping == 'OBJECT':
1202                     layout.prop(md, "mask_tex_map_object", text="Object")
1203                 elif md.mask_tex_mapping == 'UV' and ob.type == 'MESH':
1204                     layout.prop_search(md, "mask_tex_uv_layer", ob.data, "uv_layers")
1205
1206     def VERTEX_WEIGHT_EDIT(self, layout, ob, md):
1207         split = layout.split()
1208
1209         col = split.column()
1210         col.label(text="Vertex Group:")
1211         col.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
1212
1213         col.label(text="Default Weight:")
1214         col.prop(md, "default_weight", text="")
1215
1216         col = split.column()
1217         col.prop(md, "use_add")
1218         sub = col.column()
1219         sub.active = md.use_add
1220         sub.prop(md, "add_threshold")
1221
1222         col = col.column()
1223         col.prop(md, "use_remove")
1224         sub = col.column()
1225         sub.active = md.use_remove
1226         sub.prop(md, "remove_threshold")
1227
1228         layout.separator()
1229
1230         layout.prop(md, "falloff_type")
1231         if md.falloff_type == 'CURVE':
1232             layout.template_curve_mapping(md, "map_curve")
1233
1234         # Common mask options
1235         layout.separator()
1236         self.vertex_weight_mask(layout, ob, md)
1237
1238     def VERTEX_WEIGHT_MIX(self, layout, ob, md):
1239         split = layout.split()
1240
1241         col = split.column()
1242         col.label(text="Vertex Group A:")
1243         col.prop_search(md, "vertex_group_a", ob, "vertex_groups", text="")
1244         col.label(text="Default Weight A:")
1245         col.prop(md, "default_weight_a", text="")
1246
1247         col.label(text="Mix Mode:")
1248         col.prop(md, "mix_mode", text="")
1249
1250         col = split.column()
1251         col.label(text="Vertex Group B:")
1252         col.prop_search(md, "vertex_group_b", ob, "vertex_groups", text="")
1253         col.label(text="Default Weight B:")
1254         col.prop(md, "default_weight_b", text="")
1255
1256         col.label(text="Mix Set:")
1257         col.prop(md, "mix_set", text="")
1258
1259         # Common mask options
1260         layout.separator()
1261         self.vertex_weight_mask(layout, ob, md)
1262
1263     def VERTEX_WEIGHT_PROXIMITY(self, layout, ob, md):
1264         split = layout.split()
1265
1266         col = split.column()
1267         col.label(text="Vertex Group:")
1268         col.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
1269
1270         col = split.column()
1271         col.label(text="Target Object:")
1272         col.prop(md, "target", text="")
1273
1274         split = layout.split()
1275
1276         col = split.column()
1277         col.label(text="Distance:")
1278         col.prop(md, "proximity_mode", text="")
1279         if md.proximity_mode == 'GEOMETRY':
1280             col.row().prop(md, "proximity_geometry")
1281
1282         col = split.column()
1283         col.label()
1284         col.prop(md, "min_dist")
1285         col.prop(md, "max_dist")
1286
1287         layout.separator()
1288         layout.prop(md, "falloff_type")
1289
1290         # Common mask options
1291         layout.separator()
1292         self.vertex_weight_mask(layout, ob, md)
1293
1294     def SKIN(self, layout, ob, md):
1295         row = layout.row()
1296         row.operator("object.skin_armature_create", text="Create Armature")
1297         row.operator("mesh.customdata_skin_add")
1298
1299         layout.separator()
1300
1301         row = layout.row(align=True)
1302         row.prop(md, "branch_smoothing")
1303         row.prop(md, "use_smooth_shade")
1304
1305         split = layout.split()
1306
1307         col = split.column()
1308         col.label(text="Selected Vertices:")
1309         sub = col.column(align=True)
1310         sub.operator("object.skin_loose_mark_clear", text="Mark Loose").action = 'MARK'
1311         sub.operator("object.skin_loose_mark_clear", text="Clear Loose").action = 'CLEAR'
1312
1313         sub = col.column()
1314         sub.operator("object.skin_root_mark", text="Mark Root")
1315         sub.operator("object.skin_radii_equalize", text="Equalize Radii")
1316
1317         col = split.column()
1318         col.label(text="Symmetry Axes:")
1319         col.prop(md, "use_x_symmetry")
1320         col.prop(md, "use_y_symmetry")
1321         col.prop(md, "use_z_symmetry")
1322
1323     def TRIANGULATE(self, layout, ob, md):
1324         row = layout.row()
1325
1326         col = row.column()
1327         col.label(text="Quad Method:")
1328         col.prop(md, "quad_method", text="")
1329         col = row.column()
1330         col.label(text="Ngon Method:")
1331         col.prop(md, "ngon_method", text="")
1332
1333     def UV_WARP(self, layout, ob, md):
1334         split = layout.split()
1335         col = split.column()
1336         col.prop(md, "center")
1337
1338         col = split.column()
1339         col.label(text="UV Axis:")
1340         col.prop(md, "axis_u", text="")
1341         col.prop(md, "axis_v", text="")
1342
1343         split = layout.split()
1344         col = split.column()
1345         col.label(text="From:")
1346         col.prop(md, "object_from", text="")
1347
1348         col = split.column()
1349         col.label(text="To:")
1350         col.prop(md, "object_to", text="")
1351
1352         split = layout.split()
1353         col = split.column()
1354         obj = md.object_from
1355         if obj and obj.type == 'ARMATURE':
1356             col.label(text="Bone:")
1357             col.prop_search(md, "bone_from", obj.data, "bones", text="")
1358
1359         col = split.column()
1360         obj = md.object_to
1361         if obj and obj.type == 'ARMATURE':
1362             col.label(text="Bone:")
1363             col.prop_search(md, "bone_to", obj.data, "bones", text="")
1364
1365         split = layout.split()
1366
1367         col = split.column()
1368         col.label(text="Vertex Group:")
1369         col.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
1370
1371         col = split.column()
1372         col.label(text="UV Map:")
1373         col.prop_search(md, "uv_layer", ob.data, "uv_layers", text="")
1374
1375     def WIREFRAME(self, layout, ob, md):
1376         has_vgroup = bool(md.vertex_group)
1377
1378         split = layout.split()
1379
1380         col = split.column()
1381         col.prop(md, "thickness", text="Thickness")
1382
1383         row = col.row(align=True)
1384         row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
1385         sub = row.row(align=True)
1386         sub.active = has_vgroup
1387         sub.prop(md, "invert_vertex_group", text="", icon='ARROW_LEFTRIGHT')
1388         row = col.row(align=True)
1389         row.active = has_vgroup
1390         row.prop(md, "thickness_vertex_group", text="Factor")
1391
1392         col.prop(md, "use_crease", text="Crease Edges")
1393         row = col.row()
1394         row.active = md.use_crease
1395         row.prop(md, "crease_weight", text="Crease Weight")
1396
1397         col = split.column()
1398
1399         col.prop(md, "offset")
1400         col.prop(md, "use_even_offset", text="Even Thickness")
1401         col.prop(md, "use_relative_offset", text="Relative Thickness")
1402         col.prop(md, "use_boundary", text="Boundary")
1403         col.prop(md, "use_replace", text="Replace Original")
1404
1405         col.prop(md, "material_offset", text="Material Offset")
1406
1407     def DATA_TRANSFER(self, layout, ob, md):
1408         row = layout.row(align=True)
1409         row.prop(md, "object")
1410         sub = row.row(align=True)
1411         sub.active = bool(md.object)
1412         sub.prop(md, "use_object_transform", text="", icon='GROUP')
1413
1414         layout.separator()
1415
1416         split = layout.split(0.333)
1417         split.prop(md, "use_vert_data")
1418         use_vert = md.use_vert_data
1419         row = split.row()
1420         row.active = use_vert
1421         row.prop(md, "vert_mapping", text="")
1422         if use_vert:
1423             col = layout.column(align=True)
1424             split = col.split(0.333, align=True)
1425             sub = split.column(align=True)
1426             sub.prop(md, "data_types_verts")
1427             sub = split.column(align=True)
1428             row = sub.row(align=True)
1429             row.prop(md, "layers_vgroup_select_src", text="")
1430             row.label(icon='RIGHTARROW')
1431             row.prop(md, "layers_vgroup_select_dst", text="")
1432             row = sub.row(align=True)
1433             row.label("", icon='NONE')
1434
1435         layout.separator()
1436
1437         split = layout.split(0.333)
1438         split.prop(md, "use_edge_data")
1439         use_edge = md.use_edge_data
1440         row = split.row()
1441         row.active = use_edge
1442         row.prop(md, "edge_mapping", text="")
1443         if use_edge:
1444             col = layout.column(align=True)
1445             split = col.split(0.333, align=True)
1446             sub = split.column(align=True)
1447             sub.prop(md, "data_types_edges")
1448
1449         layout.separator()
1450
1451         split = layout.split(0.333)
1452         split.prop(md, "use_loop_data")
1453         use_loop = md.use_loop_data
1454         row = split.row()
1455         row.active = use_loop
1456         row.prop(md, "loop_mapping", text="")
1457         if use_loop:
1458             col = layout.column(align=True)
1459             split = col.split(0.333, align=True)
1460             sub = split.column(align=True)
1461             sub.prop(md, "data_types_loops")
1462             sub = split.column(align=True)
1463             row = sub.row(align=True)
1464             row.label("", icon='NONE')
1465             row = sub.row(align=True)
1466             row.prop(md, "layers_vcol_select_src", text="")
1467             row.label(icon='RIGHTARROW')
1468             row.prop(md, "layers_vcol_select_dst", text="")
1469             row = sub.row(align=True)
1470             row.prop(md, "layers_uv_select_src", text="")
1471             row.label(icon='RIGHTARROW')
1472             row.prop(md, "layers_uv_select_dst", text="")
1473             col.prop(md, "islands_precision")
1474
1475         layout.separator()
1476
1477         split = layout.split(0.333)
1478         split.prop(md, "use_poly_data")
1479         use_poly = md.use_poly_data
1480         row = split.row()
1481         row.active = use_poly
1482         row.prop(md, "poly_mapping", text="")
1483         if use_poly:
1484             col = layout.column(align=True)
1485             split = col.split(0.333, align=True)
1486             sub = split.column(align=True)
1487             sub.prop(md, "data_types_polys")
1488
1489         layout.separator()
1490
1491         split = layout.split()
1492         col = split.column()
1493         row = col.row(align=True)
1494         sub = row.row(align=True)
1495         sub.active = md.use_max_distance
1496         sub.prop(md, "max_distance")
1497         row.prop(md, "use_max_distance", text="", icon='STYLUS_PRESSURE')
1498
1499         col = split.column()
1500         col.prop(md, "ray_radius")
1501
1502         layout.separator()
1503
1504         split = layout.split()
1505         col = split.column()
1506         col.prop(md, "mix_mode")
1507         col.prop(md, "mix_factor")
1508
1509         col = split.column()
1510         row = col.row()
1511         row.active = bool(md.object)
1512         row.operator("object.datalayout_transfer", text="Generate Data Layers")
1513         row = col.row(align=True)
1514         row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
1515         sub = row.row(align=True)
1516         sub.active = bool(md.vertex_group)
1517         sub.prop(md, "invert_vertex_group", text="", icon='ARROW_LEFTRIGHT')
1518
1519     def NORMAL_EDIT(self, layout, ob, md):
1520         has_vgroup = bool(md.vertex_group)
1521         do_polynors_fix = not md.no_polynors_fix
1522         needs_object_offset = (((md.mode == 'RADIAL') and not md.target) or
1523                                ((md.mode == 'DIRECTIONAL') and md.use_direction_parallel))
1524
1525         row = layout.row()
1526         row.prop(md, "mode", expand=True)
1527
1528         split = layout.split()
1529
1530         col = split.column()
1531         col.prop(md, "target", text="")
1532         sub = col.column(align=True)
1533         sub.active = needs_object_offset
1534         sub.prop(md, "offset")
1535         row = col.row(align=True)
1536
1537         col = split.column()
1538         row = col.row()
1539         row.active = (md.mode == 'DIRECTIONAL')
1540         row.prop(md, "use_direction_parallel")
1541
1542         subcol = col.column(align=True)
1543         subcol.label("Mix Mode:")
1544         subcol.prop(md, "mix_mode", text="")
1545         subcol.prop(md, "mix_factor")
1546         row = subcol.row(align=True)
1547         row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
1548         sub = row.row(align=True)
1549         sub.active = has_vgroup
1550         sub.prop(md, "invert_vertex_group", text="", icon='ARROW_LEFTRIGHT')
1551         row = subcol.row(align=True)
1552         row.prop(md, "mix_limit")
1553         row.prop(md, "no_polynors_fix", text="", icon='UNLOCKED' if do_polynors_fix else 'LOCKED')
1554
1555     def CORRECTIVE_SMOOTH(self, layout, ob, md):
1556         is_bind = md.is_bind
1557
1558         layout.prop(md, "factor", text="Factor")
1559         layout.prop(md, "iterations")
1560
1561         row = layout.row()
1562         row.prop(md, "smooth_type")
1563
1564         split = layout.split()
1565
1566         col = split.column()
1567         col.label(text="Vertex Group:")
1568         row = col.row(align=True)
1569         row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
1570         row.prop(md, "invert_vertex_group", text="", icon='ARROW_LEFTRIGHT')
1571
1572         col = split.column()
1573         col.prop(md, "use_only_smooth")
1574         col.prop(md, "use_pin_boundary")
1575
1576         layout.prop(md, "rest_source")
1577         if md.rest_source == 'BIND':
1578             layout.operator("object.correctivesmooth_bind", text="Unbind" if is_bind else "Bind")
1579
1580     def WEIGHTED_NORMAL(self, layout, ob, md):
1581         layout.label("Weighting Mode:")
1582         split = layout.split(align=True)
1583         col = split.column(align=True)
1584         col.prop(md, "mode", text="")
1585         col.prop(md, "weight", text="Weight")
1586         col.prop(md, "keep_sharp")
1587
1588         col = split.column(align=True)
1589         row = col.row(align=True)
1590         row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
1591         row.active = bool(md.vertex_group)
1592         row.prop(md, "invert_vertex_group", text="", icon='ARROW_LEFTRIGHT')
1593         col.prop(md, "thresh", text="Threshold")
1594         col.prop(md, "face_influence")
1595
1596
1597 class DATA_PT_gpencil_modifiers(ModifierButtonsPanel, Panel):
1598     bl_label = "Modifiers"
1599
1600     @classmethod
1601     def poll(cls, context):
1602         ob = context.object
1603         return ob and ob.type == 'GPENCIL'
1604
1605     def draw(self, context):
1606         layout = self.layout
1607
1608         ob = context.object
1609
1610         layout.operator_menu_enum("object.gpencil_modifier_add", "type")
1611
1612         for md in ob.grease_pencil_modifiers:
1613             box = layout.template_greasepencil_modifier(md)
1614             if box:
1615                 # match enum type to our functions, avoids a lookup table.
1616                 getattr(self, md.type)(box, ob, md)
1617
1618     # the mt.type enum is (ab)used for a lookup on function names
1619     # ...to avoid lengthy if statements
1620     # so each type must have a function here.
1621
1622     def GP_NOISE(self, layout, ob, md):
1623         gpd = ob.data
1624         split = layout.split()
1625
1626         col = split.column()
1627         row = col.row(align=True)
1628         row.prop(md, "factor")
1629         row.prop(md, "random", text="", icon="TIME", toggle=True)
1630         row = col.row()
1631         row.enabled = md.random
1632         row.prop(md, "step")
1633         col.prop(md, "full_stroke")
1634         col.prop(md, "move_extreme")
1635
1636         col = split.column()
1637         col.label("Layer:")
1638         row = col.row(align=True)
1639         row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
1640         row.prop(md, "invert_layers", text="", icon="ARROW_LEFTRIGHT")
1641
1642         col.label("Vertex Group:")
1643         row = col.row(align=True)
1644         row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
1645         row.prop(md, "invert_vertex", text="", icon="ARROW_LEFTRIGHT")
1646
1647         row = col.row(align=True)
1648         row.prop(md, "pass_index", text="Pass")
1649         row.prop(md, "invert_pass", text="", icon="ARROW_LEFTRIGHT")
1650
1651         row = layout.row(align=True)
1652         row.label("Affect:")
1653         row = layout.row(align=True)
1654         row.prop(md, "affect_position", text="Position", icon='MESH_DATA', toggle=True)
1655         row.prop(md, "affect_strength", text="Strength", icon='COLOR', toggle=True)
1656         row.prop(md, "affect_thickness", text="Thickness", icon='LINE_DATA', toggle=True)
1657         row.prop(md, "affect_uv", text="UV", icon='MOD_UVPROJECT', toggle=True)
1658
1659     def GP_SMOOTH(self, layout, ob, md):
1660         gpd = ob.data
1661         row = layout.row(align=False)
1662         row.prop(md, "factor")
1663         row.prop(md, "step")
1664
1665         split = layout.split()
1666         col = split.column()
1667         col.label("Layer:")
1668         row = col.row(align=True)
1669         row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
1670         row.prop(md, "invert_layers", text="", icon="ARROW_LEFTRIGHT")
1671
1672         col = split.column()
1673         col.label("Vertex Group:")
1674         row = col.row(align=True)
1675         row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
1676         row.prop(md, "invert_vertex", text="", icon="ARROW_LEFTRIGHT")
1677
1678         row = col.row(align=True)
1679         row.prop(md, "pass_index", text="Pass")
1680         row.prop(md, "invert_pass", text="", icon="ARROW_LEFTRIGHT")
1681
1682         row = layout.row(align=True)
1683         row.label("Affect:")
1684         row = layout.row(align=True)
1685         row.prop(md, "affect_position", text="Position", icon='MESH_DATA', toggle=True)
1686         row.prop(md, "affect_strength", text="Strength", icon='COLOR', toggle=True)
1687         row.prop(md, "affect_thickness", text="Thickness", icon='LINE_DATA', toggle=True)
1688         row.prop(md, "affect_uv", text="UV", icon='MOD_UVPROJECT', toggle=True)
1689
1690     def GP_SUBDIV(self, layout, ob, md):
1691         gpd = ob.data
1692         split = layout.split()
1693
1694         col = split.column()
1695         row = col.row(align=True)
1696         row.prop(md, "level")
1697         row.prop(md, "simple", text="", icon="PARTICLE_POINT")
1698         row = col.row(align=True)
1699         row.prop(md, "pass_index", text="Pass")
1700         row.prop(md, "invert_pass", text="", icon="ARROW_LEFTRIGHT")
1701
1702         col = split.column()
1703         col.label("Layer:")
1704         row = col.row(align=True)
1705         row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
1706         row.prop(md, "invert_layers", text="", icon="ARROW_LEFTRIGHT")
1707
1708     def GP_SIMPLIFY(self, layout, ob, md):
1709         gpd = ob.data
1710
1711         row = layout.row()
1712         row.prop(md, "mode")
1713
1714         split = layout.split()
1715
1716         col = split.column()
1717         col.label("Settings:")
1718         row = col.row(align=True)
1719         row.enabled = md.mode == 'FIXED'
1720         row.prop(md, "step")
1721
1722         row = col.row(align=True)
1723         row.enabled = not md.mode == 'FIXED'
1724         row.prop(md, "factor")
1725
1726         col = split.column()
1727         col.label("Layer:")
1728         row = col.row(align=True)
1729         row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
1730
1731         row = col.row(align=True)
1732         row.prop(md, "pass_index", text="Pass")
1733         row.prop(md, "invert_pass", text="", icon="ARROW_LEFTRIGHT")
1734
1735     def GP_THICK(self, layout, ob, md):
1736         gpd = ob.data
1737         split = layout.split()
1738
1739         col = split.column()
1740         row = col.row(align=True)
1741         row.prop(md, "thickness")
1742         row = col.row(align=True)
1743         row.prop(md, "pass_index", text="Pass")
1744         row.prop(md, "invert_pass", text="", icon="ARROW_LEFTRIGHT")
1745
1746         col.prop(md, "normalize_thickness")
1747
1748         col = split.column()
1749         col.label("Layer:")
1750         row = col.row(align=True)
1751         row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
1752         row.prop(md, "invert_layers", text="", icon="ARROW_LEFTRIGHT")
1753
1754         col.label("Vertex Group:")
1755         row = col.row(align=True)
1756         row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
1757         row.prop(md, "invert_vertex", text="", icon="ARROW_LEFTRIGHT")
1758
1759         if not md.normalize_thickness:
1760             split = layout.split()
1761             col = split.column()
1762             col.prop(md, "use_custom_curve")
1763
1764             if md.use_custom_curve:
1765                 col.template_curve_mapping(md, "curve")
1766
1767     def GP_TINT(self, layout, ob, md):
1768         gpd = ob.data
1769         split = layout.split()
1770
1771         col = split.column()
1772         col.prop(md, "color")
1773         col.prop(md, "factor")
1774
1775         col = split.column()
1776         col.label("Layer:")
1777         row = col.row(align=True)
1778         row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
1779         row.prop(md, "invert_layers", text="", icon="ARROW_LEFTRIGHT")
1780         row = col.row(align=True)
1781         row.prop(md, "pass_index", text="Pass")
1782         row.prop(md, "invert_pass", text="", icon="ARROW_LEFTRIGHT")
1783
1784         row = layout.row()
1785         row.prop(md, "create_materials")
1786         row.prop(md, "modify_color")
1787         
1788
1789     def GP_COLOR(self, layout, ob, md):
1790         gpd = ob.data
1791         split = layout.split()
1792
1793         col = split.column()
1794         col.label("Color:")
1795         col.prop(md, "hue", text="H")
1796         col.prop(md, "saturation", text="S")
1797         col.prop(md, "value", text="V")
1798
1799         col = split.column()
1800         col.label("Layer:")
1801         row = col.row(align=True)
1802         row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
1803         row.prop(md, "invert_layers", text="", icon="ARROW_LEFTRIGHT")
1804         row = col.row(align=True)
1805         row.prop(md, "pass_index", text="Pass")
1806         row.prop(md, "invert_pass", text="", icon="ARROW_LEFTRIGHT")
1807
1808         row = layout.row()
1809         row.prop(md, "create_materials")
1810         row.prop(md, "modify_color")
1811
1812     def GP_OPACITY(self, layout, ob, md):
1813         gpd = ob.data
1814         split = layout.split()
1815
1816         col = split.column()
1817         col.label("Opacity:")
1818         col.prop(md, "factor")
1819
1820         col = split.column()
1821         col.label("Layer:")
1822         row = col.row(align=True)
1823         row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
1824         row.prop(md, "invert_layers", text="", icon="ARROW_LEFTRIGHT")
1825
1826         col.label("Vertex Group:")
1827         row = col.row(align=True)
1828         row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
1829         row.prop(md, "invert_vertex", text="", icon="ARROW_LEFTRIGHT")
1830
1831         row = col.row(align=True)
1832         row.prop(md, "pass_index", text="Pass")
1833         row.prop(md, "invert_pass", text="", icon="ARROW_LEFTRIGHT")
1834         
1835         row = layout.row()
1836         row.prop(md, "create_materials")
1837         row.prop(md, "modify_color")
1838
1839     def GP_INSTANCE(self, layout, ob, md):
1840         gpd = ob.data
1841
1842         col = layout.column()
1843         col.prop(md, "count")
1844         col.prop(md, "use_make_objects")
1845
1846         split = layout.split()
1847         col = split.column()
1848         col.label("Offset:")
1849         col.prop(md, "offset", text="")
1850
1851         col = split.column()
1852         col.label("Shift:")
1853         col.prop(md, "shift", text="")
1854         row = col.row(align=True)
1855         row.prop(md, "lock_axis", expand=True)
1856
1857         split = layout.split()
1858         col = split.column()
1859         col.label("Rotation:")
1860         col.prop(md, "rotation", text="")
1861         col.separator()
1862         row = col.row(align=True)
1863         row.prop(md, "random_rot", text="", icon="TIME", toggle=True)
1864         row.prop(md, "rot_factor", text="")
1865
1866         col = split.column()
1867         col.label("Scale:")
1868         col.prop(md, "scale", text="")
1869         col.separator()
1870         row = col.row(align=True)
1871         row.prop(md, "random_scale", text="", icon="TIME", toggle=True)
1872         row.prop(md, "scale_factor", text="")
1873
1874         split = layout.split()
1875         col = split.column()
1876         col.label("Layer:")
1877         row = col.row(align=True)
1878         row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
1879         row.prop(md, "invert_layers", text="", icon="ARROW_LEFTRIGHT")
1880         row = col.row(align=True)
1881         row.prop(md, "pass_index", text="Pass")
1882         row.prop(md, "invert_pass", text="", icon="ARROW_LEFTRIGHT")
1883
1884     def GP_BUILD(self, layout, ob, md):
1885         gpd = ob.data
1886
1887         split = layout.split()
1888
1889         col = split.column()
1890         col.prop(md, "mode")
1891         if md.mode == 'CONCURRENT':
1892             col.prop(md, "concurrent_time_alignment")
1893         else:
1894             col.separator()  # For spacing
1895             col.separator()
1896         col.separator()
1897
1898         col.prop(md, "transition")
1899         sub = col.column(align=True)
1900         sub.prop(md, "start_delay")
1901         sub.prop(md, "length")
1902
1903         col = split.column(align=True)
1904         col.prop(md, "use_restrict_frame_range")
1905         sub = col.column(align=True)
1906         sub.active = md.use_restrict_frame_range
1907         sub.prop(md, "frame_start", text="Start")
1908         sub.prop(md, "frame_end", text="End")
1909         col.separator()
1910
1911         col.label("Layer:")
1912         row = col.row(align=True)
1913         row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
1914         row.prop(md, "invert_layers", text="", icon="ARROW_LEFTRIGHT")
1915
1916     def GP_LATTICE(self, layout, ob, md):
1917         gpd = ob.data
1918         split = layout.split()
1919
1920         col = split.column()
1921         col.label(text="Object:")
1922         col.prop(md, "object", text="")
1923
1924         col = split.column()
1925         col.label("Layer:")
1926         row = col.row(align=True)
1927         row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
1928         row.prop(md, "invert_layers", text="", icon="ARROW_LEFTRIGHT")
1929
1930         col.label("Vertex Group:")
1931         row = col.row(align=True)
1932         row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
1933         row.prop(md, "invert_vertex", text="", icon="ARROW_LEFTRIGHT")
1934
1935         row = col.row(align=True)
1936         row.prop(md, "pass_index", text="Pass")
1937         row.prop(md, "invert_pass", text="", icon="ARROW_LEFTRIGHT")
1938
1939         layout.separator()
1940         layout.prop(md, "strength", slider=True)
1941
1942     def GP_MIRROR(self, layout, ob, md):
1943         gpd = ob.data
1944
1945         row = layout.row(align=True)
1946         row.prop(md, "x_axis")
1947         row.prop(md, "y_axis")
1948         row.prop(md, "z_axis")
1949
1950         # GPXX: Not implemented yet
1951         # layout.separator()
1952         # layout.prop(md, "clip")
1953
1954         layout.label("Layer:")
1955         row = layout.row(align=True)
1956         row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
1957         row.prop(md, "invert_layers", text="", icon="ARROW_LEFTRIGHT")
1958
1959         row = layout.row(align=True)
1960         row.prop(md, "pass_index", text="Pass")
1961         row.prop(md, "invert_pass", text="", icon="ARROW_LEFTRIGHT")
1962
1963         layout.label(text="Object:")
1964         layout.prop(md, "object", text="")
1965
1966     def GP_HOOK(self, layout, ob, md):
1967         gpd = ob.data
1968         split = layout.split()
1969
1970         col = split.column()
1971         col.label(text="Object:")
1972         col.prop(md, "object", text="")
1973         if md.object and md.object.type == 'ARMATURE':
1974             col.label(text="Bone:")
1975             col.prop_search(md, "subtarget", md.object.data, "bones", text="")
1976
1977         col = split.column()
1978         col.label("Layer:")
1979         row = col.row(align=True)
1980         row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
1981         row.prop(md, "invert_layers", text="", icon="ARROW_LEFTRIGHT")
1982
1983         col.label("Vertex Group:")
1984         row = col.row(align=True)
1985         row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
1986         row.prop(md, "invert_vertex", text="", icon="ARROW_LEFTRIGHT")
1987
1988         row = col.row(align=True)
1989         row.prop(md, "pass_index", text="Pass")
1990         row.prop(md, "invert_pass", text="", icon="ARROW_LEFTRIGHT")
1991
1992         use_falloff = (md.falloff_type != 'NONE')
1993         split = layout.split()
1994
1995         layout.separator()
1996
1997         row = layout.row(align=True)
1998         if use_falloff:
1999             row.prop(md, "falloff_radius")
2000         row.prop(md, "strength", slider=True)
2001         layout.prop(md, "falloff_type")
2002
2003         col = layout.column()
2004         if use_falloff:
2005             if md.falloff_type == 'CURVE':
2006                 col.template_curve_mapping(md, "falloff_curve")
2007
2008         split = layout.split()
2009
2010         col = split.column()
2011         col.prop(md, "use_falloff_uniform")
2012
2013     def GP_OFFSET(self, layout, ob, md):
2014         gpd = ob.data
2015         split = layout.split()
2016
2017         col = split.column()
2018         col.prop(md, "location")
2019         col.prop(md, "scale")
2020
2021         col = split.column()
2022         col.prop(md, "rotation")
2023
2024         col.label("Layer:")
2025         row = col.row(align=True)
2026         row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
2027         row.prop(md, "invert_layers", text="", icon="ARROW_LEFTRIGHT")
2028
2029         col.label("Vertex Group:")
2030         row = col.row(align=True)
2031         row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
2032         row.prop(md, "invert_vertex", text="", icon="ARROW_LEFTRIGHT")
2033
2034         row = col.row(align=True)
2035         row.prop(md, "pass_index", text="Pass")
2036         row.prop(md, "invert_pass", text="", icon="ARROW_LEFTRIGHT")
2037
2038
2039 classes = (
2040     DATA_PT_modifiers,
2041     DATA_PT_gpencil_modifiers,
2042 )
2043
2044 if __name__ == "__main__":  # only for live edit.
2045     from bpy.utils import register_class
2046     for cls in classes:
2047         register_class(cls)