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