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