59bf820560e804dc39c25ba6ddf0680000374ce5
[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
662         layout.separator()
663
664         col = layout.column()
665         row = col.row()
666         if md.is_external:
667             row.operator("object.multires_external_pack", text="Pack External")
668             row.label()
669             row = col.row()
670             row.prop(md, "filepath", text="")
671         else:
672             row.operator("object.multires_external_save", text="Save External...")
673             row.label()
674
675     def OCEAN(self, layout, ob, md):
676         if not bpy.app.build_options.mod_oceansim:
677             layout.label(text="Built without OceanSim modifier")
678             return
679
680         layout.prop(md, "geometry_mode")
681
682         if md.geometry_mode == 'GENERATE':
683             row = layout.row()
684             row.prop(md, "repeat_x")
685             row.prop(md, "repeat_y")
686
687         layout.separator()
688
689         split = layout.split()
690
691         col = split.column()
692         col.prop(md, "time")
693         col.prop(md, "depth")
694         col.prop(md, "random_seed")
695
696         col = split.column()
697         col.prop(md, "resolution")
698         col.prop(md, "size")
699         col.prop(md, "spatial_size")
700
701         layout.label(text="Waves:")
702
703         split = layout.split()
704
705         col = split.column()
706         col.prop(md, "choppiness")
707         col.prop(md, "wave_scale", text="Scale")
708         col.prop(md, "wave_scale_min")
709         col.prop(md, "wind_velocity")
710
711         col = split.column()
712         col.prop(md, "wave_alignment", text="Alignment")
713         sub = col.column()
714         sub.active = (md.wave_alignment > 0.0)
715         sub.prop(md, "wave_direction", text="Direction")
716         sub.prop(md, "damping")
717
718         layout.separator()
719
720         layout.prop(md, "use_normals")
721
722         split = layout.split()
723
724         col = split.column()
725         col.prop(md, "use_foam")
726         sub = col.row()
727         sub.active = md.use_foam
728         sub.prop(md, "foam_coverage", text="Coverage")
729
730         col = split.column()
731         col.active = md.use_foam
732         col.label(text="Foam Data Layer Name:")
733         col.prop(md, "foam_layer_name", text="")
734
735         layout.separator()
736
737         if md.is_cached:
738             layout.operator("object.ocean_bake", text="Delete Bake").free = True
739         else:
740             layout.operator("object.ocean_bake").free = False
741
742         split = layout.split()
743         split.enabled = not md.is_cached
744
745         col = split.column(align=True)
746         col.prop(md, "frame_start", text="Start")
747         col.prop(md, "frame_end", text="End")
748
749         col = split.column(align=True)
750         col.label(text="Cache path:")
751         col.prop(md, "filepath", text="")
752
753         split = layout.split()
754         split.enabled = not md.is_cached
755
756         col = split.column()
757         col.active = md.use_foam
758         col.prop(md, "bake_foam_fade")
759
760         col = split.column()
761
762     def PARTICLE_INSTANCE(self, layout, ob, md):
763         layout.prop(md, "object")
764         if md.object:
765             layout.prop_search(md, "particle_system", md.object, "particle_systems", text="Particle System")
766         else:
767             layout.prop(md, "particle_system_index", text="Particle System")
768
769         split = layout.split()
770         col = split.column()
771         col.label(text="Create From:")
772         layout.prop(md, "space", text="")
773         col.prop(md, "use_normal")
774         col.prop(md, "use_children")
775         col.prop(md, "use_size")
776
777         col = split.column()
778         col.label(text="Show Particles When:")
779         col.prop(md, "show_alive")
780         col.prop(md, "show_unborn")
781         col.prop(md, "show_dead")
782
783         row = layout.row(align=True)
784         row.prop(md, "particle_amount", text="Amount")
785         row.prop(md, "particle_offset", text="Offset")
786
787         row = layout.row(align=True)
788         row.prop(md, "axis", expand=True)
789
790         layout.separator()
791
792         layout.prop(md, "use_path", text="Create Along Paths")
793
794         col = layout.column()
795         col.active = md.use_path
796         col.prop(md, "use_preserve_shape")
797
798         row = col.row(align=True)
799         row.prop(md, "position", slider=True)
800         row.prop(md, "random_position", text="Random", slider=True)
801         row = col.row(align=True)
802         row.prop(md, "rotation", slider=True)
803         row.prop(md, "random_rotation", text="Random", slider=True)
804
805         layout.separator()
806
807         col = layout.column()
808         col.prop_search(md, "index_layer_name", ob.data, "vertex_colors", text="Index Layer")
809         col.prop_search(md, "value_layer_name", ob.data, "vertex_colors", text="Value Layer")
810
811     def PARTICLE_SYSTEM(self, layout, ob, md):
812         layout.label(text="Settings can be found inside the Particle context")
813
814     def SCREW(self, layout, ob, md):
815         split = layout.split()
816
817         col = split.column()
818         col.prop(md, "axis")
819         col.prop(md, "object", text="AxisOb")
820         col.prop(md, "angle")
821         col.prop(md, "steps")
822         col.prop(md, "render_steps")
823         col.prop(md, "use_smooth_shade")
824         col.prop(md, "use_merge_vertices")
825         sub = col.column()
826         sub.active = md.use_merge_vertices
827         sub.prop(md, "merge_threshold")
828
829         col = split.column()
830         row = col.row()
831         row.active = (md.object is None or md.use_object_screw_offset is False)
832         row.prop(md, "screw_offset")
833         row = col.row()
834         row.active = (md.object is not None)
835         row.prop(md, "use_object_screw_offset")
836         col.prop(md, "use_normal_calculate")
837         col.prop(md, "use_normal_flip")
838         col.prop(md, "iterations")
839         col.prop(md, "use_stretch_u")
840         col.prop(md, "use_stretch_v")
841
842     def SHRINKWRAP(self, layout, ob, md):
843         split = layout.split()
844         col = split.column()
845         col.label(text="Target:")
846         col.prop(md, "target", text="")
847         col = split.column()
848         col.label(text="Vertex Group:")
849         row = col.row(align=True)
850         row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
851         row.prop(md, "invert_vertex_group", text="", icon='ARROW_LEFTRIGHT')
852
853         split = layout.split()
854
855         col = split.column()
856         col.prop(md, "offset")
857
858         col = split.column()
859         col.label(text="Mode:")
860         col.prop(md, "wrap_method", text="")
861
862         if md.wrap_method in {'PROJECT', 'NEAREST_SURFACEPOINT', 'TARGET_PROJECT'}:
863             col.prop(md, "wrap_mode", text="")
864
865         if md.wrap_method == 'PROJECT':
866             split = layout.split()
867             col = split.column()
868             col.prop(md, "subsurf_levels")
869             col = split.column()
870
871             col.prop(md, "project_limit", text="Limit")
872             split = layout.split(factor=0.25)
873
874             col = split.column()
875             col.label(text="Axis:")
876             col.prop(md, "use_project_x")
877             col.prop(md, "use_project_y")
878             col.prop(md, "use_project_z")
879
880             col = split.column()
881             col.label(text="Direction:")
882             col.prop(md, "use_negative_direction")
883             col.prop(md, "use_positive_direction")
884
885             subcol = col.column()
886             subcol.active = md.use_negative_direction and md.cull_face != 'OFF'
887             subcol.prop(md, "use_invert_cull")
888
889             col = split.column()
890             col.label(text="Cull Faces:")
891             col.prop(md, "cull_face", expand=True)
892
893             layout.prop(md, "auxiliary_target")
894
895     def SIMPLE_DEFORM(self, layout, ob, md):
896
897         layout.row().prop(md, "deform_method", expand=True)
898
899         split = layout.split()
900
901         col = split.column()
902         col.label(text="Vertex Group:")
903         row = col.row(align=True)
904         row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
905         row.prop(md, "invert_vertex_group", text="", icon='ARROW_LEFTRIGHT')
906
907         split = layout.split()
908
909         col = split.column()
910         col.label(text="Axis, Origin:")
911         col.prop(md, "origin", text="")
912
913         col.prop(md, "deform_axis")
914
915         if md.deform_method in {'TAPER', 'STRETCH', 'TWIST'}:
916             row = col.row(align=True)
917             row.label(text="Lock:")
918             deform_axis = md.deform_axis
919             if deform_axis != 'X':
920                 row.prop(md, "lock_x")
921             if deform_axis != 'Y':
922                 row.prop(md, "lock_y")
923             if deform_axis != 'Z':
924                 row.prop(md, "lock_z")
925
926         col = split.column()
927         col.label(text="Deform:")
928         if md.deform_method in {'TAPER', 'STRETCH'}:
929             col.prop(md, "factor")
930         else:
931             col.prop(md, "angle")
932         col.prop(md, "limits", slider=True)
933
934     def SMOKE(self, layout, ob, md):
935         layout.label(text="Settings are inside the Physics tab")
936
937     def SMOOTH(self, layout, ob, md):
938         split = layout.split(factor=0.25)
939
940         col = split.column()
941         col.label(text="Axis:")
942         col.prop(md, "use_x")
943         col.prop(md, "use_y")
944         col.prop(md, "use_z")
945
946         col = split.column()
947         col.prop(md, "factor")
948         col.prop(md, "iterations")
949         col.label(text="Vertex Group:")
950         col.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
951
952     def SOFT_BODY(self, layout, ob, md):
953         layout.label(text="Settings are inside the Physics tab")
954
955     def SOLIDIFY(self, layout, ob, md):
956         split = layout.split()
957
958         col = split.column()
959         col.prop(md, "thickness")
960         col.prop(md, "thickness_clamp")
961
962         col.separator()
963
964         row = col.row(align=True)
965         row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
966         sub = row.row(align=True)
967         sub.active = bool(md.vertex_group)
968         sub.prop(md, "invert_vertex_group", text="", icon='ARROW_LEFTRIGHT')
969
970         sub = col.row()
971         sub.active = bool(md.vertex_group)
972         sub.prop(md, "thickness_vertex_group", text="Factor")
973
974         col.label(text="Crease:")
975         col.prop(md, "edge_crease_inner", text="Inner")
976         col.prop(md, "edge_crease_outer", text="Outer")
977         col.prop(md, "edge_crease_rim", text="Rim")
978
979         col = split.column()
980
981         col.prop(md, "offset")
982         col.prop(md, "use_flip_normals")
983
984         col.prop(md, "use_even_offset")
985         col.prop(md, "use_quality_normals")
986         col.prop(md, "use_rim")
987         col_rim = col.column()
988         col_rim.active = md.use_rim
989         col_rim.prop(md, "use_rim_only")
990
991         col.separator()
992
993         col.label(text="Material Index Offset:")
994
995         sub = col.column()
996         row = sub.split(factor=0.4, align=True)
997         row.prop(md, "material_offset", text="")
998         row = row.row(align=True)
999         row.active = md.use_rim
1000         row.prop(md, "material_offset_rim", text="Rim")
1001
1002     def SUBSURF(self, layout, ob, md):
1003         from bpy import context
1004         layout.row().prop(md, "subdivision_type", expand=True)
1005
1006         split = layout.split()
1007         col = split.column()
1008
1009         scene = context.scene
1010         engine = context.engine
1011         show_adaptive_options = (
1012             engine == 'CYCLES' and md == ob.modifiers[-1] and
1013             scene.cycles.feature_set == 'EXPERIMENTAL'
1014         )
1015         if show_adaptive_options:
1016             col.label(text="View:")
1017             col.prop(md, "levels", text="Levels")
1018             col.label(text="Render:")
1019             col.prop(ob.cycles, "use_adaptive_subdivision", text="Adaptive")
1020             if ob.cycles.use_adaptive_subdivision:
1021                 col.prop(ob.cycles, "dicing_rate")
1022             else:
1023                 col.prop(md, "render_levels", text="Levels")
1024         else:
1025             col.label(text="Subdivisions:")
1026             col.prop(md, "levels", text="View")
1027             col.prop(md, "render_levels", text="Render")
1028             col.prop(md, "quality")
1029
1030         col = split.column()
1031         col.label(text="Options:")
1032
1033         sub = col.column()
1034         sub.active = (not show_adaptive_options) or (not ob.cycles.use_adaptive_subdivision)
1035         sub.prop(md, "uv_smooth", text="")
1036
1037         col.prop(md, "show_only_control_edges")
1038
1039         if show_adaptive_options and ob.cycles.use_adaptive_subdivision:
1040             col = layout.column(align=True)
1041             col.scale_y = 0.6
1042             col.separator()
1043             col.label(text="Final Dicing Rate:")
1044             col.separator()
1045
1046             render = max(scene.cycles.dicing_rate * ob.cycles.dicing_rate, 0.1)
1047             preview = max(scene.cycles.preview_dicing_rate * ob.cycles.dicing_rate, 0.1)
1048             col.label(text=f"Render {render:.2f} px, Preview {preview:.2f} px")
1049
1050     def SURFACE(self, layout, ob, md):
1051         layout.label(text="Settings are inside the Physics tab")
1052
1053     def SURFACE_DEFORM(self, layout, ob, md):
1054         col = layout.column()
1055         col.active = not md.is_bound
1056
1057         col.prop(md, "target")
1058         col.prop(md, "falloff")
1059
1060         layout.separator()
1061
1062         col = layout.column()
1063
1064         if md.is_bound:
1065             col.operator("object.surfacedeform_bind", text="Unbind")
1066         else:
1067             col.active = md.target is not None
1068             col.operator("object.surfacedeform_bind", text="Bind")
1069
1070     def UV_PROJECT(self, layout, ob, md):
1071         split = layout.split()
1072         col = split.column()
1073         col.prop_search(md, "uv_layer", ob.data, "uv_layers")
1074         col.separator()
1075
1076         col.prop(md, "projector_count", text="Projectors")
1077         for proj in md.projectors:
1078             col.prop(proj, "object", text="")
1079
1080         col = split.column()
1081         sub = col.column(align=True)
1082         sub.prop(md, "aspect_x", text="Aspect X")
1083         sub.prop(md, "aspect_y", text="Aspect Y")
1084
1085         sub = col.column(align=True)
1086         sub.prop(md, "scale_x", text="Scale X")
1087         sub.prop(md, "scale_y", text="Scale Y")
1088
1089     def WARP(self, layout, ob, md):
1090         use_falloff = (md.falloff_type != 'NONE')
1091         split = layout.split()
1092
1093         col = split.column()
1094         col.label(text="From:")
1095         col.prop(md, "object_from", text="")
1096
1097         col.prop(md, "use_volume_preserve")
1098
1099         col = split.column()
1100         col.label(text="To:")
1101         col.prop(md, "object_to", text="")
1102         col.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
1103
1104         col = layout.column()
1105
1106         row = col.row(align=True)
1107         row.prop(md, "strength")
1108         if use_falloff:
1109             row.prop(md, "falloff_radius")
1110
1111         col.prop(md, "falloff_type")
1112         if use_falloff:
1113             if md.falloff_type == 'CURVE':
1114                 col.template_curve_mapping(md, "falloff_curve")
1115
1116         # 2 new columns
1117         split = layout.split()
1118         col = split.column()
1119         col.label(text="Texture:")
1120         col.template_ID(md, "texture", new="texture.new")
1121
1122         col = split.column()
1123         col.label(text="Texture Coordinates:")
1124         col.prop(md, "texture_coords", text="")
1125
1126         if md.texture_coords == 'OBJECT':
1127             layout.prop(md, "texture_coords_object", text="Object")
1128         elif md.texture_coords == 'UV' and ob.type == 'MESH':
1129             layout.prop_search(md, "uv_layer", ob.data, "uv_layers")
1130
1131     def WAVE(self, layout, ob, md):
1132         split = layout.split()
1133
1134         col = split.column()
1135         col.label(text="Motion:")
1136         col.prop(md, "use_x")
1137         col.prop(md, "use_y")
1138         col.prop(md, "use_cyclic")
1139
1140         col = split.column()
1141         col.prop(md, "use_normal")
1142         sub = col.column()
1143         sub.active = md.use_normal
1144         sub.prop(md, "use_normal_x", text="X")
1145         sub.prop(md, "use_normal_y", text="Y")
1146         sub.prop(md, "use_normal_z", text="Z")
1147
1148         split = layout.split()
1149
1150         col = split.column()
1151         col.label(text="Time:")
1152         sub = col.column(align=True)
1153         sub.prop(md, "time_offset", text="Offset")
1154         sub.prop(md, "lifetime", text="Life")
1155         col.prop(md, "damping_time", text="Damping")
1156
1157         col = split.column()
1158         col.label(text="Position:")
1159         sub = col.column(align=True)
1160         sub.prop(md, "start_position_x", text="X")
1161         sub.prop(md, "start_position_y", text="Y")
1162         col.prop(md, "falloff_radius", text="Falloff")
1163
1164         layout.separator()
1165
1166         layout.prop(md, "start_position_object")
1167         layout.prop_search(md, "vertex_group", ob, "vertex_groups")
1168         split = layout.split(factor=0.33)
1169         col = split.column()
1170         col.label(text="Texture")
1171         col = split.column()
1172         col.template_ID(md, "texture", new="texture.new")
1173         layout.prop(md, "texture_coords")
1174         if md.texture_coords == 'UV' and ob.type == 'MESH':
1175             layout.prop_search(md, "uv_layer", ob.data, "uv_layers")
1176         elif md.texture_coords == 'OBJECT':
1177             layout.prop(md, "texture_coords_object")
1178
1179         layout.separator()
1180
1181         split = layout.split()
1182
1183         col = split.column()
1184         col.prop(md, "speed", slider=True)
1185         col.prop(md, "height", slider=True)
1186
1187         col = split.column()
1188         col.prop(md, "width", slider=True)
1189         col.prop(md, "narrowness", slider=True)
1190
1191     def REMESH(self, layout, ob, md):
1192         if not bpy.app.build_options.mod_remesh:
1193             layout.label(text="Built without Remesh modifier")
1194             return
1195
1196         layout.prop(md, "mode")
1197
1198         row = layout.row()
1199         row.prop(md, "octree_depth")
1200         row.prop(md, "scale")
1201
1202         if md.mode == 'SHARP':
1203             layout.prop(md, "sharpness")
1204
1205         layout.prop(md, "use_smooth_shade")
1206         layout.prop(md, "use_remove_disconnected")
1207         row = layout.row()
1208         row.active = md.use_remove_disconnected
1209         row.prop(md, "threshold")
1210
1211     @staticmethod
1212     def vertex_weight_mask(layout, ob, md):
1213         layout.label(text="Influence/Mask Options:")
1214
1215         split = layout.split(factor=0.4)
1216         split.label(text="Global Influence:")
1217         split.prop(md, "mask_constant", text="")
1218
1219         if not md.mask_texture:
1220             split = layout.split(factor=0.4)
1221             split.label(text="Vertex Group Mask:")
1222             split.prop_search(md, "mask_vertex_group", ob, "vertex_groups", text="")
1223
1224         if not md.mask_vertex_group:
1225             split = layout.split(factor=0.4)
1226             split.label(text="Texture Mask:")
1227             split.template_ID(md, "mask_texture", new="texture.new")
1228             if md.mask_texture:
1229                 split = layout.split()
1230
1231                 col = split.column()
1232                 col.label(text="Texture Coordinates:")
1233                 col.prop(md, "mask_tex_mapping", text="")
1234
1235                 col = split.column()
1236                 col.label(text="Use Channel:")
1237                 col.prop(md, "mask_tex_use_channel", text="")
1238
1239                 if md.mask_tex_mapping == 'OBJECT':
1240                     layout.prop(md, "mask_tex_map_object", text="Object")
1241                 elif md.mask_tex_mapping == 'UV' and ob.type == 'MESH':
1242                     layout.prop_search(md, "mask_tex_uv_layer", ob.data, "uv_layers")
1243
1244     def VERTEX_WEIGHT_EDIT(self, layout, ob, md):
1245         split = layout.split()
1246
1247         col = split.column()
1248         col.label(text="Vertex Group:")
1249         col.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
1250
1251         col.label(text="Default Weight:")
1252         col.prop(md, "default_weight", text="")
1253
1254         col = split.column()
1255         col.prop(md, "use_add")
1256         sub = col.column()
1257         sub.active = md.use_add
1258         sub.prop(md, "add_threshold")
1259
1260         col = col.column()
1261         col.prop(md, "use_remove")
1262         sub = col.column()
1263         sub.active = md.use_remove
1264         sub.prop(md, "remove_threshold")
1265
1266         layout.separator()
1267
1268         layout.prop(md, "falloff_type")
1269         if md.falloff_type == 'CURVE':
1270             layout.template_curve_mapping(md, "map_curve")
1271
1272         # Common mask options
1273         layout.separator()
1274         self.vertex_weight_mask(layout, ob, md)
1275
1276     def VERTEX_WEIGHT_MIX(self, layout, ob, md):
1277         split = layout.split()
1278
1279         col = split.column()
1280         col.label(text="Vertex Group A:")
1281         col.prop_search(md, "vertex_group_a", ob, "vertex_groups", text="")
1282         col.label(text="Default Weight A:")
1283         col.prop(md, "default_weight_a", text="")
1284
1285         col.label(text="Mix Mode:")
1286         col.prop(md, "mix_mode", text="")
1287
1288         col = split.column()
1289         col.label(text="Vertex Group B:")
1290         col.prop_search(md, "vertex_group_b", ob, "vertex_groups", text="")
1291         col.label(text="Default Weight B:")
1292         col.prop(md, "default_weight_b", text="")
1293
1294         col.label(text="Mix Set:")
1295         col.prop(md, "mix_set", text="")
1296
1297         # Common mask options
1298         layout.separator()
1299         self.vertex_weight_mask(layout, ob, md)
1300
1301     def VERTEX_WEIGHT_PROXIMITY(self, layout, ob, md):
1302         split = layout.split()
1303
1304         col = split.column()
1305         col.label(text="Vertex Group:")
1306         col.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
1307
1308         col = split.column()
1309         col.label(text="Target Object:")
1310         col.prop(md, "target", text="")
1311
1312         split = layout.split()
1313
1314         col = split.column()
1315         col.label(text="Distance:")
1316         col.prop(md, "proximity_mode", text="")
1317         if md.proximity_mode == 'GEOMETRY':
1318             col.row().prop(md, "proximity_geometry")
1319
1320         col = split.column()
1321         col.label()
1322         col.prop(md, "min_dist")
1323         col.prop(md, "max_dist")
1324
1325         layout.separator()
1326         layout.prop(md, "falloff_type")
1327
1328         # Common mask options
1329         layout.separator()
1330         self.vertex_weight_mask(layout, ob, md)
1331
1332     def SKIN(self, layout, ob, md):
1333         row = layout.row()
1334         row.operator("object.skin_armature_create", text="Create Armature")
1335         row.operator("mesh.customdata_skin_add")
1336
1337         layout.separator()
1338
1339         row = layout.row(align=True)
1340         row.prop(md, "branch_smoothing")
1341         row.prop(md, "use_smooth_shade")
1342
1343         split = layout.split()
1344
1345         col = split.column()
1346         col.label(text="Selected Vertices:")
1347         sub = col.column(align=True)
1348         sub.operator("object.skin_loose_mark_clear", text="Mark Loose").action = 'MARK'
1349         sub.operator("object.skin_loose_mark_clear", text="Clear Loose").action = 'CLEAR'
1350
1351         sub = col.column()
1352         sub.operator("object.skin_root_mark", text="Mark Root")
1353         sub.operator("object.skin_radii_equalize", text="Equalize Radii")
1354
1355         col = split.column()
1356         col.label(text="Symmetry Axes:")
1357         col.prop(md, "use_x_symmetry")
1358         col.prop(md, "use_y_symmetry")
1359         col.prop(md, "use_z_symmetry")
1360
1361     def TRIANGULATE(self, layout, ob, md):
1362         row = layout.row()
1363
1364         col = row.column()
1365         col.label(text="Quad Method:")
1366         col.prop(md, "quad_method", text="")
1367         col.prop(md, "keep_custom_normals")
1368         col = row.column()
1369         col.label(text="Ngon Method:")
1370         col.prop(md, "ngon_method", text="")
1371         col.label(text="Minimum Vertices:")
1372         col.prop(md, "min_vertices", text="")
1373
1374     def UV_WARP(self, layout, ob, md):
1375         split = layout.split()
1376         col = split.column()
1377         col.prop(md, "center")
1378
1379         col = split.column()
1380         col.label(text="UV Axis:")
1381         col.prop(md, "axis_u", text="")
1382         col.prop(md, "axis_v", text="")
1383
1384         split = layout.split()
1385         col = split.column()
1386         col.label(text="From:")
1387         col.prop(md, "object_from", text="")
1388
1389         col = split.column()
1390         col.label(text="To:")
1391         col.prop(md, "object_to", text="")
1392
1393         split = layout.split()
1394         col = split.column()
1395         obj = md.object_from
1396         if obj and obj.type == 'ARMATURE':
1397             col.label(text="Bone:")
1398             col.prop_search(md, "bone_from", obj.data, "bones", text="")
1399
1400         col = split.column()
1401         obj = md.object_to
1402         if obj and obj.type == 'ARMATURE':
1403             col.label(text="Bone:")
1404             col.prop_search(md, "bone_to", obj.data, "bones", text="")
1405
1406         split = layout.split()
1407
1408         col = split.column()
1409         col.label(text="Vertex Group:")
1410         col.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
1411
1412         col = split.column()
1413         col.label(text="UV Map:")
1414         col.prop_search(md, "uv_layer", ob.data, "uv_layers", text="")
1415
1416     def WIREFRAME(self, layout, ob, md):
1417         has_vgroup = bool(md.vertex_group)
1418
1419         split = layout.split()
1420
1421         col = split.column()
1422         col.prop(md, "thickness", text="Thickness")
1423
1424         row = col.row(align=True)
1425         row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
1426         sub = row.row(align=True)
1427         sub.active = has_vgroup
1428         sub.prop(md, "invert_vertex_group", text="", icon='ARROW_LEFTRIGHT')
1429         row = col.row(align=True)
1430         row.active = has_vgroup
1431         row.prop(md, "thickness_vertex_group", text="Factor")
1432
1433         col.prop(md, "use_crease", text="Crease Edges")
1434         row = col.row()
1435         row.active = md.use_crease
1436         row.prop(md, "crease_weight", text="Crease Weight")
1437
1438         col = split.column()
1439
1440         col.prop(md, "offset")
1441         col.prop(md, "use_even_offset", text="Even Thickness")
1442         col.prop(md, "use_relative_offset", text="Relative Thickness")
1443         col.prop(md, "use_boundary", text="Boundary")
1444         col.prop(md, "use_replace", text="Replace Original")
1445
1446         col.prop(md, "material_offset", text="Material Offset")
1447
1448     def DATA_TRANSFER(self, layout, ob, md):
1449         row = layout.row(align=True)
1450         row.prop(md, "object")
1451         sub = row.row(align=True)
1452         sub.active = bool(md.object)
1453         sub.prop(md, "use_object_transform", text="", icon='GROUP')
1454
1455         layout.separator()
1456
1457         split = layout.split(factor=0.333)
1458         split.prop(md, "use_vert_data")
1459         use_vert = md.use_vert_data
1460         row = split.row()
1461         row.active = use_vert
1462         row.prop(md, "vert_mapping", text="")
1463         if use_vert:
1464             col = layout.column(align=True)
1465             split = col.split(factor=0.333, align=True)
1466             sub = split.column(align=True)
1467             sub.prop(md, "data_types_verts")
1468             sub = split.column(align=True)
1469             row = sub.row(align=True)
1470             row.prop(md, "layers_vgroup_select_src", text="")
1471             row.label(icon='RIGHTARROW')
1472             row.prop(md, "layers_vgroup_select_dst", text="")
1473             row = sub.row(align=True)
1474             row.label(text="", icon='NONE')
1475
1476         layout.separator()
1477
1478         split = layout.split(factor=0.333)
1479         split.prop(md, "use_edge_data")
1480         use_edge = md.use_edge_data
1481         row = split.row()
1482         row.active = use_edge
1483         row.prop(md, "edge_mapping", text="")
1484         if use_edge:
1485             col = layout.column(align=True)
1486             split = col.split(factor=0.333, align=True)
1487             sub = split.column(align=True)
1488             sub.prop(md, "data_types_edges")
1489
1490         layout.separator()
1491
1492         split = layout.split(factor=0.333)
1493         split.prop(md, "use_loop_data")
1494         use_loop = md.use_loop_data
1495         row = split.row()
1496         row.active = use_loop
1497         row.prop(md, "loop_mapping", text="")
1498         if use_loop:
1499             col = layout.column(align=True)
1500             split = col.split(factor=0.333, align=True)
1501             sub = split.column(align=True)
1502             sub.prop(md, "data_types_loops")
1503             sub = split.column(align=True)
1504             row = sub.row(align=True)
1505             row.label(text="", icon='NONE')
1506             row = sub.row(align=True)
1507             row.prop(md, "layers_vcol_select_src", text="")
1508             row.label(icon='RIGHTARROW')
1509             row.prop(md, "layers_vcol_select_dst", text="")
1510             row = sub.row(align=True)
1511             row.prop(md, "layers_uv_select_src", text="")
1512             row.label(icon='RIGHTARROW')
1513             row.prop(md, "layers_uv_select_dst", text="")
1514             col.prop(md, "islands_precision")
1515
1516         layout.separator()
1517
1518         split = layout.split(factor=0.333)
1519         split.prop(md, "use_poly_data")
1520         use_poly = md.use_poly_data
1521         row = split.row()
1522         row.active = use_poly
1523         row.prop(md, "poly_mapping", text="")
1524         if use_poly:
1525             col = layout.column(align=True)
1526             split = col.split(factor=0.333, align=True)
1527             sub = split.column(align=True)
1528             sub.prop(md, "data_types_polys")
1529
1530         layout.separator()
1531
1532         split = layout.split()
1533         col = split.column()
1534         row = col.row(align=True)
1535         sub = row.row(align=True)
1536         sub.active = md.use_max_distance
1537         sub.prop(md, "max_distance")
1538         row.prop(md, "use_max_distance", text="", icon='STYLUS_PRESSURE')
1539
1540         col = split.column()
1541         col.prop(md, "ray_radius")
1542
1543         layout.separator()
1544
1545         split = layout.split()
1546         col = split.column()
1547         col.prop(md, "mix_mode")
1548         col.prop(md, "mix_factor")
1549
1550         col = split.column()
1551         row = col.row()
1552         row.active = bool(md.object)
1553         row.operator("object.datalayout_transfer", text="Generate Data Layers")
1554         row = col.row(align=True)
1555         row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
1556         sub = row.row(align=True)
1557         sub.active = bool(md.vertex_group)
1558         sub.prop(md, "invert_vertex_group", text="", icon='ARROW_LEFTRIGHT')
1559
1560     def NORMAL_EDIT(self, layout, ob, md):
1561         has_vgroup = bool(md.vertex_group)
1562         do_polynors_fix = not md.no_polynors_fix
1563         needs_object_offset = (((md.mode == 'RADIAL') and not md.target) or
1564                                ((md.mode == 'DIRECTIONAL') and md.use_direction_parallel))
1565
1566         row = layout.row()
1567         row.prop(md, "mode", expand=True)
1568
1569         split = layout.split()
1570
1571         col = split.column()
1572         col.prop(md, "target", text="")
1573         sub = col.column(align=True)
1574         sub.active = needs_object_offset
1575         sub.prop(md, "offset")
1576         row = col.row(align=True)
1577
1578         col = split.column()
1579         row = col.row()
1580         row.active = (md.mode == 'DIRECTIONAL')
1581         row.prop(md, "use_direction_parallel")
1582
1583         subcol = col.column(align=True)
1584         subcol.label(text="Mix Mode:")
1585         subcol.prop(md, "mix_mode", text="")
1586         subcol.prop(md, "mix_factor")
1587         row = subcol.row(align=True)
1588         row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
1589         sub = row.row(align=True)
1590         sub.active = has_vgroup
1591         sub.prop(md, "invert_vertex_group", text="", icon='ARROW_LEFTRIGHT')
1592         row = subcol.row(align=True)
1593         row.prop(md, "mix_limit")
1594         row.prop(md, "no_polynors_fix", text="", icon='UNLOCKED' if do_polynors_fix else 'LOCKED')
1595
1596     def CORRECTIVE_SMOOTH(self, layout, ob, md):
1597         is_bind = md.is_bind
1598
1599         layout.prop(md, "factor", text="Factor")
1600         layout.prop(md, "iterations")
1601
1602         row = layout.row()
1603         row.prop(md, "smooth_type")
1604
1605         split = layout.split()
1606
1607         col = split.column()
1608         col.label(text="Vertex Group:")
1609         row = col.row(align=True)
1610         row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
1611         row.prop(md, "invert_vertex_group", text="", icon='ARROW_LEFTRIGHT')
1612
1613         col = split.column()
1614         col.prop(md, "use_only_smooth")
1615         col.prop(md, "use_pin_boundary")
1616
1617         layout.prop(md, "rest_source")
1618         if md.rest_source == 'BIND':
1619             layout.operator("object.correctivesmooth_bind", text="Unbind" if is_bind else "Bind")
1620
1621     def WEIGHTED_NORMAL(self, layout, ob, md):
1622         layout.label(text="Weighting Mode:")
1623         split = layout.split(align=True)
1624         col = split.column(align=True)
1625         col.prop(md, "mode", text="")
1626         col.prop(md, "weight", text="Weight")
1627         col.prop(md, "keep_sharp")
1628
1629         col = split.column(align=True)
1630         row = col.row(align=True)
1631         row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
1632         row.active = bool(md.vertex_group)
1633         row.prop(md, "invert_vertex_group", text="", icon='ARROW_LEFTRIGHT')
1634         col.prop(md, "thresh", text="Threshold")
1635         col.prop(md, "face_influence")
1636
1637
1638 class DATA_PT_gpencil_modifiers(ModifierButtonsPanel, Panel):
1639     bl_label = "Modifiers"
1640
1641     def check_conflicts(self, layout, ob):
1642         for md in ob.grease_pencil_modifiers:
1643             if md.type == 'GP_TIME':
1644                 row = layout.row()
1645                 row.label(text="Build and Time Offset modifier not compatible", icon='ERROR')
1646                 break
1647
1648     @classmethod
1649     def poll(cls, context):
1650         ob = context.object
1651         return ob and ob.type == 'GPENCIL'
1652
1653     def draw(self, context):
1654         layout = self.layout
1655
1656         ob = context.object
1657
1658         layout.operator_menu_enum("object.gpencil_modifier_add", "type")
1659
1660         for md in ob.grease_pencil_modifiers:
1661             box = layout.template_greasepencil_modifier(md)
1662             if box:
1663                 # match enum type to our functions, avoids a lookup table.
1664                 getattr(self, md.type)(box, ob, md)
1665
1666     # the mt.type enum is (ab)used for a lookup on function names
1667     # ...to avoid lengthy if statements
1668     # so each type must have a function here.
1669
1670     def GP_NOISE(self, layout, ob, md):
1671         gpd = ob.data
1672         split = layout.split()
1673
1674         col = split.column()
1675         row = col.row(align=True)
1676         row.prop(md, "factor")
1677         row.prop(md, "random", text="", icon='TIME', toggle=True)
1678         row = col.row()
1679         row.enabled = md.random
1680         row.prop(md, "step")
1681         col.prop(md, "full_stroke")
1682         col.prop(md, "move_extreme")
1683
1684         row = layout.row(align=True)
1685         row.label(text="Affect:")
1686         row = layout.row(align=True)
1687         row.prop(md, "use_edit_position", text="Position", icon='MESH_DATA', toggle=True)
1688         row.prop(md, "use_edit_strength", text="Strength", icon='COLOR', toggle=True)
1689         row.prop(md, "use_edit_thickness", text="Thickness", icon='LINE_DATA', toggle=True)
1690         row.prop(md, "use_edit_uv", text="UV", icon='MOD_UVPROJECT', toggle=True)
1691
1692         col = layout.column()
1693         col.separator()
1694         col.label(text="Vertex Group:")
1695         row = col.row(align=True)
1696         row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
1697         row.prop(md, "invert_vertex", text="", icon='ARROW_LEFTRIGHT')
1698
1699         col.label(text="Material:")
1700         row = col.row(align=True)
1701         row.prop(md, "pass_index", text="Pass")
1702         row.prop(md, "invert_material_pass", text="", icon='ARROW_LEFTRIGHT')
1703
1704         col.label(text="Layer:")
1705         row = col.row(align=True)
1706         row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
1707         row.prop(md, "invert_layers", text="", icon='ARROW_LEFTRIGHT')
1708         row = layout.row(align=True)
1709         row.prop(md, "layer_pass", text="Pass")
1710         row.prop(md, "invert_layer_pass", text="", icon='ARROW_LEFTRIGHT')
1711
1712     def GP_SMOOTH(self, layout, ob, md):
1713         gpd = ob.data
1714         col = layout.column()
1715         col.prop(md, "factor")
1716         col.prop(md, "step")
1717
1718         col.label(text="Affect:")
1719         row = col.row(align=True)
1720         row.prop(md, "use_edit_position", text="Position", icon='MESH_DATA', toggle=True)
1721         row.prop(md, "use_edit_strength", text="Strength", icon='COLOR', toggle=True)
1722         row.prop(md, "use_edit_thickness", text="Thickness", icon='LINE_DATA', toggle=True)
1723         row.prop(md, "use_edit_uv", text="UV", icon='MOD_UVPROJECT', toggle=True)
1724
1725         col.separator()
1726         col.label(text="Vertex Group:")
1727         row = col.row(align=True)
1728         row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
1729         row.prop(md, "invert_vertex", text="", icon='ARROW_LEFTRIGHT')
1730
1731         col.label(text="Material:")
1732         row = col.row(align=True)
1733         row.prop(md, "pass_index", text="Pass")
1734         row.prop(md, "invert_material_pass", text="", icon='ARROW_LEFTRIGHT')
1735
1736         col.label(text="Layer:")
1737         row = col.row(align=True)
1738         row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
1739         row.prop(md, "invert_layers", text="", icon='ARROW_LEFTRIGHT')
1740         row = layout.row(align=True)
1741         row.prop(md, "layer_pass", text="Pass")
1742         row.prop(md, "invert_layer_pass", text="", icon='ARROW_LEFTRIGHT')
1743
1744     def GP_SUBDIV(self, layout, ob, md):
1745         gpd = ob.data
1746         split = layout.split()
1747
1748         col = split.column()
1749         row = col.row(align=True)
1750         row.prop(md, "level")
1751         row.prop(md, "simple", text="", icon='PARTICLE_POINT')
1752
1753         col = layout.column()
1754         col.separator()
1755         col.label(text="Material:")
1756         row = col.row(align=True)
1757         row.prop(md, "pass_index", text="Pass")
1758         row.prop(md, "invert_material_pass", text="", icon='ARROW_LEFTRIGHT')
1759
1760         col.label(text="Layer:")
1761         row = col.row(align=True)
1762         row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
1763         row.prop(md, "invert_layers", text="", icon='ARROW_LEFTRIGHT')
1764         row = layout.row(align=True)
1765         row.prop(md, "layer_pass", text="Pass")
1766         row.prop(md, "invert_layer_pass", text="", icon='ARROW_LEFTRIGHT')
1767
1768     def GP_SIMPLIFY(self, layout, ob, md):
1769         gpd = ob.data
1770
1771         row = layout.row()
1772         row.prop(md, "mode")
1773
1774         split = layout.split()
1775
1776         col = split.column()
1777         col.label(text="Settings:")
1778         row = col.row(align=True)
1779         row.enabled = md.mode == 'FIXED'
1780         row.prop(md, "step")
1781
1782         row = col.row(align=True)
1783         row.enabled = not md.mode == 'FIXED'
1784         row.prop(md, "factor")
1785
1786         col = layout.column()
1787         col.separator()
1788         col.label(text="Material:")
1789         row = col.row(align=True)
1790         row.prop(md, "pass_index", text="Pass")
1791         row.prop(md, "invert_material_pass", text="", icon='ARROW_LEFTRIGHT')
1792
1793         col.label(text="Layer:")
1794         row = col.row(align=True)
1795         row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
1796         row.prop(md, "invert_layers", text="", icon='ARROW_LEFTRIGHT')
1797         row = layout.row(align=True)
1798         row.prop(md, "layer_pass", text="Pass")
1799         row.prop(md, "invert_layer_pass", text="", icon='ARROW_LEFTRIGHT')
1800
1801     def GP_THICK(self, layout, ob, md):
1802         gpd = ob.data
1803         split = layout.split()
1804
1805         col = split.column()
1806         row = col.row(align=True)
1807         row.prop(md, "thickness", text="Thickness Factor")
1808
1809         col.prop(md, "normalize_thickness")
1810
1811         if not md.normalize_thickness:
1812             split = layout.split()
1813             col = split.column()
1814             col.prop(md, "use_custom_curve")
1815
1816             if md.use_custom_curve:
1817                 col.template_curve_mapping(md, "curve")
1818
1819         col = layout.column()
1820         col.separator()
1821         col.label(text="Vertex Group:")
1822         row = col.row(align=True)
1823         row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
1824         row.prop(md, "invert_vertex", text="", icon='ARROW_LEFTRIGHT')
1825
1826         col.label(text="Material:")
1827         row = col.row(align=True)
1828         row.prop(md, "pass_index", text="Pass")
1829         row.prop(md, "invert_material_pass", text="", icon='ARROW_LEFTRIGHT')
1830
1831         col.label(text="Layer:")
1832         row = col.row(align=True)
1833         row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
1834         row.prop(md, "invert_layers", text="", icon='ARROW_LEFTRIGHT')
1835         row = layout.row(align=True)
1836         row.prop(md, "layer_pass", text="Pass")
1837         row.prop(md, "invert_layer_pass", text="", icon='ARROW_LEFTRIGHT')
1838
1839     def GP_TINT(self, layout, ob, md):
1840         gpd = ob.data
1841         split = layout.split()
1842
1843         col = split.column()
1844         col.prop(md, "color")
1845         col.prop(md, "factor")
1846
1847         row = layout.row()
1848         row.prop(md, "create_materials")
1849         row.prop(md, "modify_color")
1850
1851         col = layout.column()
1852         col.separator()
1853         col.label(text="Material:")
1854         row = col.row(align=True)
1855         row.prop(md, "pass_index", text="Pass")
1856         row.prop(md, "invert_material_pass", text="", icon='ARROW_LEFTRIGHT')
1857
1858         col.label(text="Layer:")
1859         row = col.row(align=True)
1860         row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
1861         row.prop(md, "invert_layers", text="", icon='ARROW_LEFTRIGHT')
1862         row = layout.row(align=True)
1863         row.prop(md, "layer_pass", text="Pass")
1864         row.prop(md, "invert_layer_pass", text="", icon='ARROW_LEFTRIGHT')
1865
1866     def GP_TIME(self, layout, ob, md):
1867         gpd = ob.data
1868
1869         row = layout.row()
1870         row.prop(md, "mode", text="Mode")
1871
1872         row = layout.row()
1873         if md.mode == 'FIX':
1874             txt = "Frame"
1875         else:
1876             txt = "Frame Offset"
1877         row.prop(md, "offset", text=txt)
1878
1879         row = layout.row()
1880         row.enabled = md.mode != 'FIX'
1881         row.prop(md, "frame_scale")
1882
1883         row = layout.row()
1884         row.separator()
1885
1886         row = layout.row()
1887         row.enabled = md.mode != 'FIX'
1888         row.prop(md, "use_custom_frame_range")
1889
1890         row = layout.row(align=True)
1891         row.enabled = md.mode != 'FIX' and md.use_custom_frame_range is True
1892         row.prop(md, "frame_start")
1893         row.prop(md, "frame_end")
1894
1895         row = layout.row()
1896         row.enabled = md.mode != 'FIX'
1897         row.prop(md, "use_keep_loop")
1898
1899         row = layout.row()
1900         row.label(text="Layer:")
1901         row = layout.row(align=True)
1902         row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
1903         row.prop(md, "invert_layers", text="", icon='ARROW_LEFTRIGHT')
1904
1905         row = layout.row(align=True)
1906         row.prop(md, "layer_pass", text="Pass")
1907         row.prop(md, "invert_layer_pass", text="", icon='ARROW_LEFTRIGHT')
1908
1909     def GP_COLOR(self, layout, ob, md):
1910         gpd = ob.data
1911         split = layout.split()
1912
1913         col = split.column()
1914         col.label(text="Color:")
1915         col.prop(md, "hue", text="H")
1916         col.prop(md, "saturation", text="S")
1917         col.prop(md, "value", text="V")
1918
1919         row = layout.row()
1920         row.prop(md, "create_materials")
1921         row.prop(md, "modify_color")
1922
1923         col = layout.column()
1924         col.separator()
1925         col.label(text="Material:")
1926         row = col.row(align=True)
1927         row.prop(md, "pass_index", text="Pass")
1928         row.prop(md, "invert_material_pass", text="", icon='ARROW_LEFTRIGHT')
1929
1930         col.label(text="Layer:")
1931         row = col.row(align=True)
1932         row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
1933         row.prop(md, "invert_layers", text="", icon='ARROW_LEFTRIGHT')
1934         row = layout.row(align=True)
1935         row.prop(md, "layer_pass", text="Pass")
1936         row.prop(md, "invert_layer_pass", text="", icon='ARROW_LEFTRIGHT')
1937
1938     def GP_OPACITY(self, layout, ob, md):
1939         gpd = ob.data
1940         split = layout.split()
1941
1942         col = split.column()
1943         col.label(text="Opacity:")
1944         col.prop(md, "factor")
1945
1946         row = layout.row()
1947         row.prop(md, "create_materials")
1948         row.prop(md, "modify_color")
1949
1950         col = layout.column()
1951         col.separator()
1952         col.label(text="Vertex Group:")
1953         row = col.row(align=True)
1954         row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
1955         row.prop(md, "invert_vertex", text="", icon='ARROW_LEFTRIGHT')
1956
1957         col.label(text="Material:")
1958         row = col.row(align=True)
1959         row.prop(md, "pass_index", text="Pass")
1960         row.prop(md, "invert_material_pass", text="", icon='ARROW_LEFTRIGHT')
1961
1962         col.label(text="Layer:")
1963         row = col.row(align=True)
1964         row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
1965         row.prop(md, "invert_layers", text="", icon='ARROW_LEFTRIGHT')
1966         row = layout.row(align=True)
1967         row.prop(md, "layer_pass", text="Pass")
1968         row.prop(md, "invert_layer_pass", text="", icon='ARROW_LEFTRIGHT')
1969
1970     def GP_ARRAY(self, layout, ob, md):
1971         gpd = ob.data
1972
1973         col = layout.column()
1974         col.prop(md, "count")
1975
1976         split = layout.split()
1977         col = split.column()
1978         col.label(text="Offset:")
1979         col.prop(md, "offset", text="")
1980         col.prop(md, "offset_object", text="Object")
1981
1982         col = split.column()
1983         col.label(text="Shift:")
1984         col.prop(md, "shift", text="")
1985
1986         split = layout.split()
1987         col = split.column()
1988         col.label(text="Rotation:")
1989         col.prop(md, "rotation", text="")
1990         col.separator()
1991         row = col.row(align=True)
1992         row.prop(md, "random_rot", text="", icon='TIME', toggle=True)
1993         row.prop(md, "rot_factor", text="")
1994
1995         col = split.column()
1996         col.label(text="Scale:")
1997         col.prop(md, "scale", text="")
1998         col.separator()
1999         row = col.row(align=True)
2000         row.prop(md, "random_scale", text="", icon='TIME', toggle=True)
2001         row.prop(md, "scale_factor", text="")
2002
2003         col = layout.column()
2004         col.prop(md, "replace_material", text="Material")
2005         col.prop(md, "keep_on_top", text="Keep original stroke on top")
2006
2007         col = layout.column()
2008         col.separator()
2009         col.label(text="Material:")
2010         row = col.row(align=True)
2011         row.prop(md, "pass_index", text="Pass")
2012         row.prop(md, "invert_material_pass", text="", icon='ARROW_LEFTRIGHT')
2013
2014         col.label(text="Layer:")
2015         row = col.row(align=True)
2016         row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
2017         row.prop(md, "invert_layers", text="", icon='ARROW_LEFTRIGHT')
2018         row = layout.row(align=True)
2019         row.prop(md, "layer_pass", text="Pass")
2020         row.prop(md, "invert_layer_pass", text="", icon='ARROW_LEFTRIGHT')
2021
2022     def GP_BUILD(self, layout, ob, md):
2023         gpd = ob.data
2024
2025         split = layout.split()
2026
2027         col = split.column()
2028         self.check_conflicts(col, ob)
2029
2030         col.prop(md, "mode")
2031         if md.mode == 'CONCURRENT':
2032             col.prop(md, "concurrent_time_alignment")
2033
2034         col.separator()
2035         col.prop(md, "transition")
2036         sub = col.column(align=True)
2037         sub.prop(md, "start_delay")
2038         sub.prop(md, "length")
2039
2040         col = layout.column(align=True)
2041         col.prop(md, "use_restrict_frame_range")
2042         sub = col.column(align=True)
2043         sub.active = md.use_restrict_frame_range
2044         sub.prop(md, "frame_start", text="Start")
2045         sub.prop(md, "frame_end", text="End")
2046
2047         col = layout.column()
2048         col.separator()
2049         col.label(text="Layer:")
2050         row = col.row(align=True)
2051         row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
2052         row.prop(md, "invert_layers", text="", icon='ARROW_LEFTRIGHT')
2053         row = layout.row(align=True)
2054         row.prop(md, "layer_pass", text="Pass")
2055         row.prop(md, "invert_layer_pass", text="", icon='ARROW_LEFTRIGHT')
2056
2057     def GP_LATTICE(self, layout, ob, md):
2058         gpd = ob.data
2059         split = layout.split()
2060
2061         col = split.column()
2062         col.label(text="Object:")
2063         col.prop(md, "object", text="")
2064
2065         layout.prop(md, "strength", slider=True)
2066
2067         col = layout.column()
2068         col.separator()
2069         col.label(text="Vertex Group:")
2070         row = col.row(align=True)
2071         row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
2072         row.prop(md, "invert_vertex", text="", icon='ARROW_LEFTRIGHT')
2073
2074         col.label(text="Material:")
2075         row = col.row(align=True)
2076         row.prop(md, "pass_index", text="Pass")
2077         row.prop(md, "invert_material_pass", text="", icon='ARROW_LEFTRIGHT')
2078
2079         col.label(text="Layer:")
2080         row = col.row(align=True)
2081         row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
2082         row.prop(md, "invert_layers", text="", icon='ARROW_LEFTRIGHT')
2083         row = layout.row(align=True)
2084         row.prop(md, "layer_pass", text="Pass")
2085         row.prop(md, "invert_layer_pass", text="", icon='ARROW_LEFTRIGHT')
2086
2087     def GP_MIRROR(self, layout, ob, md):
2088         gpd = ob.data
2089
2090         row = layout.row(align=True)
2091         row.prop(md, "x_axis")
2092         row.prop(md, "y_axis")
2093         row.prop(md, "z_axis")
2094
2095         layout.label(text="Object:")
2096         layout.prop(md, "object", text="")
2097
2098         col = layout.column()
2099         col.separator()
2100         col.label(text="Material:")
2101         row = col.row(align=True)
2102         row.prop(md, "pass_index", text="Pass")
2103         row.prop(md, "invert_material_pass", text="", icon='ARROW_LEFTRIGHT')
2104
2105         col.label(text="Layer:")
2106         row = col.row(align=True)
2107         row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
2108         row.prop(md, "invert_layers", text="", icon='ARROW_LEFTRIGHT')
2109         row = layout.row(align=True)
2110         row.prop(md, "layer_pass", text="Pass")
2111         row.prop(md, "invert_layer_pass", text="", icon='ARROW_LEFTRIGHT')
2112
2113     def GP_HOOK(self, layout, ob, md):
2114         gpd = ob.data
2115         split = layout.split()
2116
2117         col = split.column()
2118         col.label(text="Object:")
2119         col.prop(md, "object", text="")
2120         if md.object and md.object.type == 'ARMATURE':
2121             col.label(text="Bone:")
2122             col.prop_search(md, "subtarget", md.object.data, "bones", text="")
2123
2124         use_falloff = (md.falloff_type != 'NONE')
2125
2126         layout.separator()
2127
2128         row = layout.row(align=True)
2129         if use_falloff:
2130             row.prop(md, "falloff_radius")
2131         row.prop(md, "strength", slider=True)
2132         layout.prop(md, "falloff_type")
2133
2134         col = layout.column()
2135         if use_falloff:
2136             if md.falloff_type == 'CURVE':
2137                 col.template_curve_mapping(md, "falloff_curve")
2138
2139         split = layout.split()
2140
2141         col = split.column()
2142         col.prop(md, "use_falloff_uniform")
2143
2144         col = layout.column()
2145         col.separator()
2146         col.label(text="Vertex Group:")
2147         row = col.row(align=True)
2148         row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
2149         row.prop(md, "invert_vertex", text="", icon='ARROW_LEFTRIGHT')
2150
2151         col.label(text="Material:")
2152         row = col.row(align=True)
2153         row.prop(md, "pass_index", text="Pass")
2154         row.prop(md, "invert_material_pass", text="", icon='ARROW_LEFTRIGHT')
2155
2156         col.label(text="Layer:")
2157         row = col.row(align=True)
2158         row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
2159         row.prop(md, "invert_layers", text="", icon='ARROW_LEFTRIGHT')
2160         row = layout.row(align=True)
2161         row.prop(md, "layer_pass", text="Pass")
2162         row.prop(md, "invert_layer_pass", text="", icon='ARROW_LEFTRIGHT')
2163
2164     def GP_OFFSET(self, layout, ob, md):
2165         gpd = ob.data
2166         col = layout.column()
2167
2168         col.prop(md, "location")
2169         col.prop(md, "scale")
2170         col.prop(md, "rotation")
2171
2172         col = layout.column()
2173         col.separator()
2174         col.label(text="Vertex Group:")
2175         row = col.row(align=True)
2176         row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
2177         row.prop(md, "invert_vertex", text="", icon='ARROW_LEFTRIGHT')
2178
2179         col.label(text="Material:")
2180         row = col.row(align=True)
2181         row.prop(md, "pass_index", text="Pass")
2182         row.prop(md, "invert_material_pass", text="", icon='ARROW_LEFTRIGHT')
2183
2184         col.label(text="Layer:")
2185         row = col.row(align=True)
2186         row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
2187         row.prop(md, "invert_layers", text="", icon='ARROW_LEFTRIGHT')
2188         row = layout.row(align=True)
2189         row.prop(md, "layer_pass", text="Pass")
2190         row.prop(md, "invert_layer_pass", text="", icon='ARROW_LEFTRIGHT')
2191
2192     def GP_ARMATURE(self, layout, ob, md):
2193         split = layout.split()
2194
2195         col = split.column()
2196         col.label(text="Object:")
2197         col.prop(md, "object", text="")
2198         # col.prop(md, "use_deform_preserve_volume")
2199
2200         col = split.column()
2201         col.label(text="Bind To:")
2202         col.prop(md, "use_vertex_groups", text="Vertex Groups")
2203         col.prop(md, "use_bone_envelopes", text="Bone Envelopes")
2204
2205         layout.separator()
2206
2207         row = layout.row(align=True)
2208         row.label(text="Vertex Group:")
2209         row = layout.row(align=True)
2210         row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
2211         sub = row.row(align=True)
2212         sub.active = bool(md.vertex_group)
2213         sub.prop(md, "invert_vertex_group", text="", icon='ARROW_LEFTRIGHT')
2214
2215
2216 classes = (
2217     DATA_PT_modifiers,
2218     DATA_PT_gpencil_modifiers,
2219 )
2220
2221 if __name__ == "__main__":  # only for live edit.
2222     from bpy.utils import register_class
2223     for cls in classes:
2224         register_class(cls)