Cleanup: use staticmethod where appropriate
[blender.git] / release / scripts / startup / bl_ui / properties_physics_dynamicpaint.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
21 from bpy.types import (
22     Panel,
23     UIList,
24 )
25 from .properties_physics_common import (
26     point_cache_ui,
27     effector_weights_ui,
28 )
29
30
31 class PHYSICS_UL_dynapaint_surfaces(UIList):
32     def draw_item(self, _context, layout, _data, item, icon, _active_data, _active_propname, _index):
33         # assert(isinstance(item, bpy.types.DynamicPaintSurface)
34         surf = item
35         sticon = layout.enum_item_icon(surf, "surface_type", surf.surface_type)
36
37         if self.layout_type in {'DEFAULT', 'COMPACT'}:
38             row = layout.row(align=True)
39             row.label(text="", icon_value=icon)
40             row.prop(surf, "name", text="", emboss=False, icon_value=sticon)
41             row = layout.row(align=True)
42
43             if surf.use_color_preview:
44                 row.prop(
45                     surf,
46                     "show_preview",
47                     text="",
48                     emboss=False,
49                     icon='RESTRICT_VIEW_OFF' if surf.show_preview else 'RESTRICT_VIEW_ON'
50                 )
51             row.prop(surf, "is_active", text="")
52
53         elif self.layout_type == 'GRID':
54             layout.alignment = 'CENTER'
55             row = layout.row(align=True)
56             row.label(text="", icon_value=icon)
57             row.label(text="", icon_value=sticon)
58
59
60 class PhysicButtonsPanel:
61     bl_space_type = 'PROPERTIES'
62     bl_region_type = 'WINDOW'
63     bl_context = "physics"
64
65     @staticmethod
66     def poll_dyn_paint(context):
67         ob = context.object
68         return (ob and ob.type == 'MESH') and context.dynamic_paint
69
70     @staticmethod
71     def poll_dyn_canvas(context):
72         if not PhysicButtonsPanel.poll_dyn_paint(context):
73             return False
74
75         md = context.dynamic_paint
76         return (md and md.ui_type == 'CANVAS' and md.canvas_settings and md.canvas_settings.canvas_surfaces.active)
77
78     @staticmethod
79     def poll_dyn_canvas_paint(context):
80         if not PhysicButtonsPanel.poll_dyn_canvas(context):
81             return False
82
83         surface = context.dynamic_paint.canvas_settings.canvas_surfaces.active
84         return (surface.surface_type == 'PAINT')
85
86     @staticmethod
87     def poll_dyn_canvas_brush(context):
88         if not PhysicButtonsPanel.poll_dyn_paint(context):
89             return False
90
91         md = context.dynamic_paint
92         return (md and md.ui_type == 'BRUSH' and md.brush_settings)
93
94     @staticmethod
95     def poll_dyn_output(context):
96         if not PhysicButtonsPanel.poll_dyn_canvas(context):
97             return False
98
99         surface = context.dynamic_paint.canvas_settings.canvas_surfaces.active
100         return (not (surface.surface_format == 'VERTEX' and (surface.surface_type in {'DISPLACE', 'WAVE'})))
101
102     @staticmethod
103     def poll_dyn_output_maps(context):
104         if not PhysicButtonsPanel.poll_dyn_output(context):
105             return False
106
107         surface = context.dynamic_paint.canvas_settings.canvas_surfaces.active
108         return (surface.surface_format == 'IMAGE' and surface.surface_type == 'PAINT')
109
110
111 class PHYSICS_PT_dynamic_paint(PhysicButtonsPanel, Panel):
112     bl_label = "Dynamic Paint"
113     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
114
115     @classmethod
116     def poll(cls, context):
117         if not PhysicButtonsPanel.poll_dyn_paint(context):
118             return False
119
120         return (context.engine in cls.COMPAT_ENGINES)
121
122     def draw(self, context):
123         layout = self.layout
124         layout.use_property_split = True
125
126         md = context.dynamic_paint
127
128         layout.prop(md, "ui_type")
129
130
131 class PHYSICS_PT_dynamic_paint_settings(PhysicButtonsPanel, Panel):
132     bl_label = "Settings"
133     bl_parent_id = 'PHYSICS_PT_dynamic_paint'
134     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
135
136     @classmethod
137     def poll(cls, context):
138         if not PhysicButtonsPanel.poll_dyn_paint(context):
139             return False
140
141         return (context.engine in cls.COMPAT_ENGINES)
142
143     def draw(self, context):
144         layout = self.layout
145
146         md = context.dynamic_paint
147
148         if md.ui_type == 'CANVAS':
149             canvas = md.canvas_settings
150
151             if canvas is None:
152                 layout.operator("dpaint.type_toggle", text="Add Canvas").type = 'CANVAS'
153                 return  # do nothing.
154
155             layout.operator("dpaint.type_toggle", text="Remove Canvas", icon='X').type = 'CANVAS'
156
157             surface = canvas.canvas_surfaces.active
158
159             row = layout.row()
160             row.template_list(
161                 "PHYSICS_UL_dynapaint_surfaces", "", canvas, "canvas_surfaces",
162                 canvas.canvas_surfaces, "active_index", rows=1
163             )
164
165             col = row.column(align=True)
166             col.operator("dpaint.surface_slot_add", icon='ADD', text="")
167             col.operator("dpaint.surface_slot_remove", icon='REMOVE', text="")
168
169             layout.separator()
170
171             layout.use_property_split = True
172
173             if surface:
174                 flow = layout.grid_flow(
175                     row_major=True, columns=0, even_columns=True, even_rows=False, align=False
176                 )
177                 col = flow.column()
178
179                 col.prop(surface, "surface_format")
180
181                 if surface.surface_format != 'VERTEX':
182                     col.prop(surface, "image_resolution")
183                 col.prop(surface, "use_antialiasing")
184
185                 col = flow.column(align=True)
186                 col.prop(surface, "frame_start", text="Frame Start")
187                 col.prop(surface, "frame_end", text="End")
188
189                 col.prop(surface, "frame_substeps")
190
191         elif md.ui_type == 'BRUSH':
192             brush = md.brush_settings
193
194             if brush is None:
195                 layout.operator("dpaint.type_toggle", text="Add Brush").type = 'BRUSH'
196                 return  # do nothing.
197
198             layout.operator("dpaint.type_toggle", text="Remove Brush", icon='X').type = 'BRUSH'
199
200             layout.use_property_split = True
201
202             flow = layout.grid_flow(
203                 row_major=True, columns=0, even_columns=True, even_rows=False, align=False
204             )
205             col = flow.column()
206             col.prop(brush, "paint_color")
207             col.prop(brush, "paint_alpha", text="Alpha", slider=True)
208
209             col = flow.column()
210             col.prop(brush, "paint_wetness", text="Wetness", slider=True)
211             col.prop(brush, "use_absolute_alpha")
212             col.prop(brush, "use_paint_erase")
213
214
215 class PHYSICS_PT_dp_advanced_canvas(PhysicButtonsPanel, Panel):
216     bl_label = "Advanced"
217     bl_parent_id = "PHYSICS_PT_dynamic_paint"
218     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
219
220     @classmethod
221     def poll(cls, context):
222         if not PhysicButtonsPanel.poll_dyn_canvas(context):
223             return False
224
225         return (context.engine in cls.COMPAT_ENGINES)
226
227     def draw(self, context):
228         layout = self.layout
229         layout.use_property_split = True
230
231         canvas = context.dynamic_paint.canvas_settings
232         surface = canvas.canvas_surfaces.active
233         surface_type = surface.surface_type
234
235         layout.prop(surface, "surface_type")
236
237         layout.separator()
238
239         flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=True)
240
241         # per type settings
242         if surface_type == 'DISPLACE':
243             col = flow.column()
244
245             if surface.surface_format == 'VERTEX':
246                 col.prop(surface, "depth_clamp")
247                 col.prop(surface, "displace_factor")
248
249             col.prop(surface, "use_incremental_displace")
250             col.separator()
251
252         elif surface_type == 'WAVE':
253             col = flow.column()
254             col.prop(surface, "use_wave_open_border")
255             col.prop(surface, "wave_timescale")
256             col.prop(surface, "wave_speed")
257
258             col.separator()
259
260             col = flow.column()
261             col.prop(surface, "wave_damping")
262             col.prop(surface, "wave_spring")
263             col.prop(surface, "wave_smoothness")
264
265             col.separator()
266
267         col = flow.column()
268         col.prop(surface, "brush_collection")
269
270         if surface_type not in {'DISPLACE', 'WAVE'}:
271             col = flow.column()  # flow the layout otherwise.
272
273         col.prop(surface, "brush_influence_scale", text="Scale Influence")
274         col.prop(surface, "brush_radius_scale", text="Radius")
275
276
277 class PHYSICS_PT_dp_advanced_canvas_paint_dry(PhysicButtonsPanel, Panel):
278     bl_label = "Dry"
279     bl_parent_id = "PHYSICS_PT_dp_advanced_canvas"
280     bl_options = {'DEFAULT_CLOSED'}
281     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
282
283     @classmethod
284     def poll(cls, context):
285         if not PhysicButtonsPanel.poll_dyn_canvas_paint(context):
286             return False
287
288         return (context.engine in cls.COMPAT_ENGINES)
289
290     def draw_header(self, context):
291         canvas = context.dynamic_paint.canvas_settings
292         surface = canvas.canvas_surfaces.active
293         self.layout.prop(surface, "use_drying", text="")
294
295     def draw(self, context):
296         layout = self.layout
297         layout.use_property_split = True
298         flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
299
300         canvas = context.dynamic_paint.canvas_settings
301         surface = canvas.canvas_surfaces.active
302
303         flow.active = surface.use_drying
304
305         col = flow.column()
306         col.prop(surface, "dry_speed", text="Time")
307
308         col = flow.column()
309         col.prop(surface, "color_dry_threshold", text="Color")
310         col.prop(surface, "use_dry_log", text="Slow")
311
312
313 class PHYSICS_PT_dp_advanced_canvas_paint_dissolve(PhysicButtonsPanel, Panel):
314     bl_label = "Dissolve"
315     bl_parent_id = "PHYSICS_PT_dp_advanced_canvas"
316     bl_options = {'DEFAULT_CLOSED'}
317     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
318
319     @classmethod
320     def poll(cls, context):
321         if not PhysicButtonsPanel.poll_dyn_canvas(context):
322             return False
323
324         surface = context.dynamic_paint.canvas_settings.canvas_surfaces.active
325
326         return (surface.surface_type != 'WAVE' and context.engine in cls.COMPAT_ENGINES)
327
328     def draw_header(self, context):
329         canvas = context.dynamic_paint.canvas_settings
330         surface = canvas.canvas_surfaces.active
331         self.layout.prop(surface, "use_dissolve", text="")
332
333     def draw(self, context):
334         layout = self.layout
335         layout.use_property_split = True
336         flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
337
338         canvas = context.dynamic_paint.canvas_settings
339         surface = canvas.canvas_surfaces.active
340
341         flow.active = surface.use_dissolve
342
343         col = flow.column()
344         col.prop(surface, "dissolve_speed", text="Time")
345
346         col = flow.column()
347         col.prop(surface, "use_dissolve_log", text="Slow")
348
349
350 class PHYSICS_PT_dp_canvas_output(PhysicButtonsPanel, Panel):
351     bl_label = "Output"
352     bl_parent_id = "PHYSICS_PT_dynamic_paint"
353     bl_options = {'DEFAULT_CLOSED'}
354     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
355
356     @classmethod
357     def poll(cls, context):
358         if not PhysicButtonsPanel.poll_dyn_output(context):
359             return False
360
361         return (context.engine in cls.COMPAT_ENGINES)
362
363     def draw(self, context):
364         layout = self.layout
365         layout.use_property_split = True
366
367         canvas = context.dynamic_paint.canvas_settings
368         surface = canvas.canvas_surfaces.active
369         ob = context.object
370
371         surface_type = surface.surface_type
372
373         # vertex format outputs.
374         if surface.surface_format == 'VERTEX':
375             if surface_type == 'PAINT':
376                 # toggle active preview.
377                 layout.prop(surface, "preview_id")
378
379                 # paint-map output.
380                 row = layout.row()
381                 row.prop_search(surface, "output_name_a", ob.data, "vertex_colors", text="Paintmap Layer")
382
383                 icons = 'REMOVE' if surface.output_exists(object=ob, index=0) else 'ADD'
384                 row.operator("dpaint.output_toggle", icon=icons, text="").output = 'A'
385
386                 # wet-map output.
387                 row = layout.row()
388                 row.prop_search(surface, "output_name_b", ob.data, "vertex_colors", text="Wetmap Layer")
389
390                 icons = 'REMOVE' if surface.output_exists(object=ob, index=1) else 'ADD'
391                 row.operator("dpaint.output_toggle", icon=icons, text="").output = 'B'
392
393             elif surface_type == 'WEIGHT':
394                 row = layout.row()
395                 row.prop_search(surface, "output_name_a", ob, "vertex_groups", text="Vertex Group")
396
397                 icons = 'REMOVE' if surface.output_exists(object=ob, index=0) else 'ADD'
398                 row.operator("dpaint.output_toggle", icon=icons, text="").output = 'A'
399
400         # image format outputs.
401         if surface.surface_format == 'IMAGE':
402             # layout.operator("dpaint.bake", text="Bake Image Sequence", icon='MOD_DYNAMICPAINT')
403
404             flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
405
406             col = flow.column()
407
408             col.prop_search(surface, "uv_layer", ob.data, "uv_layers", text="UV Map")
409
410             col = flow.column()
411             col.prop(surface, "image_fileformat")
412             col.prop(surface, "use_premultiply", text="Premultiply Alpha")
413
414             if surface_type != 'PAINT':
415                 col = col.column()
416                 col.prop(surface, "output_name_a", text="Filename")
417
418                 if surface_type == 'DISPLACE':
419                     col.prop(surface, "displace_type", text="Displace Type")
420                     col.prop(surface, "depth_clamp")
421
422                 elif surface_type == 'WAVE':
423                     col.prop(surface, "depth_clamp", text="Wave Clamp")
424
425
426 class PHYSICS_PT_dp_canvas_output_paintmaps(PhysicButtonsPanel, Panel):
427     bl_label = "Paintmaps"
428     bl_parent_id = "PHYSICS_PT_dp_canvas_output"
429     bl_options = {'DEFAULT_CLOSED'}
430     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
431
432     @classmethod
433     def poll(cls, context):
434         if not PhysicButtonsPanel.poll_dyn_output_maps(context):
435             return False
436
437         return (context.engine in cls.COMPAT_ENGINES)
438
439     def draw_header(self, context):
440         canvas = context.dynamic_paint.canvas_settings
441         surface = canvas.canvas_surfaces.active
442         self.layout.prop(surface, "use_output_a", text="")
443
444     def draw(self, context):
445         layout = self.layout
446         layout.use_property_split = True
447
448         canvas = context.dynamic_paint.canvas_settings
449         surface = canvas.canvas_surfaces.active
450
451         sub = layout.column()
452         sub.active = surface.use_output_a
453         sub.prop(surface, "output_name_a", text="Name")
454
455
456 class PHYSICS_PT_dp_canvas_output_bake(PhysicButtonsPanel, Panel):
457     bl_label = "Bake"
458     bl_parent_id = "PHYSICS_PT_dp_canvas_output"
459     bl_options = {'DEFAULT_CLOSED'}
460     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
461
462     @classmethod
463     def poll(cls, context):
464         if not PhysicButtonsPanel.poll_dyn_output_maps(context):
465             return False
466
467         return (context.engine in cls.COMPAT_ENGINES)
468
469     def draw(self, context):
470         layout = self.layout
471
472         canvas = context.dynamic_paint.canvas_settings
473         surface = canvas.canvas_surfaces.active
474
475         row = layout.row(align=True)
476         row.alignment = 'RIGHT'
477         row.label(text="Cache Path")
478
479         layout.prop(surface, "image_output_path", text="")
480         layout.operator("dpaint.bake", text="Bake Image Sequence", icon='MOD_DYNAMICPAINT')
481
482
483 class PHYSICS_PT_dp_canvas_output_wetmaps(PhysicButtonsPanel, Panel):
484     bl_label = "Wetmaps"
485     bl_parent_id = "PHYSICS_PT_dp_canvas_output"
486     bl_options = {'DEFAULT_CLOSED'}
487     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
488
489     @classmethod
490     def poll(cls, context):
491         if not PhysicButtonsPanel.poll_dyn_output_maps(context):
492             return False
493
494         return (context.engine in cls.COMPAT_ENGINES)
495
496     def draw_header(self, context):
497         canvas = context.dynamic_paint.canvas_settings
498         surface = canvas.canvas_surfaces.active
499         self.layout.prop(surface, "use_output_b", text="")
500
501     def draw(self, context):
502         layout = self.layout
503         layout.use_property_split = True
504
505         canvas = context.dynamic_paint.canvas_settings
506         surface = canvas.canvas_surfaces.active
507
508         sub = layout.column()
509         sub.active = surface.use_output_b
510         sub.prop(surface, "output_name_b", text="Name")
511
512
513 class PHYSICS_PT_dp_canvas_initial_color(PhysicButtonsPanel, Panel):
514     bl_label = "Initial Color"
515     bl_parent_id = "PHYSICS_PT_dynamic_paint"
516     bl_options = {'DEFAULT_CLOSED'}
517     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
518
519     @classmethod
520     def poll(cls, context):
521         if not PhysicButtonsPanel.poll_dyn_canvas_paint(context):
522             return False
523
524         return (context.engine in cls.COMPAT_ENGINES)
525
526     def draw(self, context):
527         layout = self.layout
528
529         canvas = context.dynamic_paint.canvas_settings
530         surface = canvas.canvas_surfaces.active
531         ob = context.object
532
533         layout.use_property_split = True
534
535         col = layout.column()
536         col.prop(surface, "init_color_type", text="Type", expand=False)
537
538         if surface.init_color_type != 'NONE':
539             col.separator()
540
541         # dissolve
542         if surface.init_color_type == 'COLOR':
543             layout.prop(surface, "init_color")
544
545         elif surface.init_color_type == 'TEXTURE':
546             col.prop(surface, "init_texture")
547             col.prop_search(surface, "init_layername", ob.data, "uv_layers", text="UV Map")
548
549         elif surface.init_color_type == 'VERTEX_COLOR':
550             col.prop_search(surface, "init_layername", ob.data, "vertex_colors", text="Color Layer")
551
552
553 class PHYSICS_PT_dp_effects(PhysicButtonsPanel, Panel):
554     bl_label = "Effects"
555     bl_parent_id = 'PHYSICS_PT_dynamic_paint'
556     bl_options = {'DEFAULT_CLOSED'}
557     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
558
559     @classmethod
560     def poll(cls, context):
561         if not PhysicButtonsPanel.poll_dyn_canvas_paint(context):
562             return False
563
564         return (context.engine in cls.COMPAT_ENGINES)
565
566     def draw(self, _context):
567         return  # do nothing.
568
569
570 class PHYSICS_PT_dp_effects_spread(PhysicButtonsPanel, Panel):
571     bl_label = "Spread"
572     bl_parent_id = "PHYSICS_PT_dp_effects"
573     bl_options = {'DEFAULT_CLOSED'}
574     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
575
576     @classmethod
577     def poll(cls, context):
578         if not PhysicButtonsPanel.poll_dyn_paint(context):
579             return False
580
581         return (context.engine in cls.COMPAT_ENGINES)
582
583     def draw_header(self, context):
584         canvas = context.dynamic_paint.canvas_settings
585         surface = canvas.canvas_surfaces.active
586
587         self.layout.prop(surface, "use_spread", text="")
588
589     def draw(self, context):
590         layout = self.layout
591         layout.use_property_split = True
592         flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
593
594         canvas = context.dynamic_paint.canvas_settings
595         surface = canvas.canvas_surfaces.active
596         layout.active = surface.use_spread
597
598         col = flow.column()
599         col.prop(surface, "spread_speed", text="Speed")
600
601         col = flow.column()
602         col.prop(surface, "color_spread_speed", text="Color")
603
604
605 class PHYSICS_PT_dp_effects_drip(PhysicButtonsPanel, Panel):
606     bl_label = "Drip"
607     bl_parent_id = "PHYSICS_PT_dp_effects"
608     bl_options = {'DEFAULT_CLOSED'}
609     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
610
611     @classmethod
612     def poll(cls, context):
613         if not PhysicButtonsPanel.poll_dyn_paint(context):
614             return False
615
616         return (context.engine in cls.COMPAT_ENGINES)
617
618     def draw_header(self, context):
619         canvas = context.dynamic_paint.canvas_settings
620         surface = canvas.canvas_surfaces.active
621
622         self.layout.prop(surface, "use_drip", text="")
623
624     def draw(self, context):
625         layout = self.layout
626         layout.use_property_split = True
627         flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
628
629         canvas = context.dynamic_paint.canvas_settings
630         surface = canvas.canvas_surfaces.active
631
632         flow.active = surface.use_drip
633
634         col = flow.column()
635         col.prop(surface, "drip_velocity", slider=True)
636
637         col = flow.column()
638         col.prop(surface, "drip_acceleration", slider=True)
639
640
641 class PHYSICS_PT_dp_effects_drip_weights(PhysicButtonsPanel, Panel):
642     bl_label = "Weights"
643     bl_parent_id = "PHYSICS_PT_dp_effects_drip"
644     bl_options = {'DEFAULT_CLOSED'}
645     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
646
647     @classmethod
648     def poll(cls, context):
649         if not PhysicButtonsPanel.poll_dyn_paint(context):
650             return False
651
652         return (context.engine in cls.COMPAT_ENGINES)
653
654     def draw(self, context):
655         layout = self.layout
656
657         canvas = context.dynamic_paint.canvas_settings
658         surface = canvas.canvas_surfaces.active
659
660         layout.active = surface.use_drip
661
662         effector_weights_ui(self, surface.effector_weights, 'DYNAMIC_PAINT')
663
664
665 class PHYSICS_PT_dp_effects_shrink(PhysicButtonsPanel, Panel):
666     bl_label = "Shrink"
667     bl_parent_id = "PHYSICS_PT_dp_effects"
668     bl_options = {'DEFAULT_CLOSED'}
669     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
670
671     @classmethod
672     def poll(cls, context):
673         if not PhysicButtonsPanel.poll_dyn_paint(context):
674             return False
675
676         return (context.engine in cls.COMPAT_ENGINES)
677
678     def draw_header(self, context):
679         canvas = context.dynamic_paint.canvas_settings
680         surface = canvas.canvas_surfaces.active
681
682         self.layout.prop(surface, "use_shrink", text="")
683
684     def draw(self, context):
685         layout = self.layout
686         layout.use_property_split = True
687
688         canvas = context.dynamic_paint.canvas_settings
689         surface = canvas.canvas_surfaces.active
690         layout.active = surface.use_shrink
691
692         layout.prop(surface, "shrink_speed", text="Speed")
693
694
695 class PHYSICS_PT_dp_cache(PhysicButtonsPanel, Panel):
696     bl_label = "Cache"
697     bl_parent_id = "PHYSICS_PT_dynamic_paint"
698     bl_options = {'DEFAULT_CLOSED'}
699     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
700
701     @classmethod
702     def poll(cls, context):
703         if not PhysicButtonsPanel.poll_dyn_canvas(context):
704             return False
705
706         surface = context.dynamic_paint.canvas_settings.canvas_surfaces.active
707         return (surface.is_cache_user and (context.engine in cls.COMPAT_ENGINES))
708
709     def draw(self, context):
710         surface = context.dynamic_paint.canvas_settings.canvas_surfaces.active
711         cache = surface.point_cache
712
713         point_cache_ui(self, cache, (cache.is_baked is False), 'DYNAMIC_PAINT')
714
715
716 class PHYSICS_PT_dp_brush_source(PhysicButtonsPanel, Panel):
717     bl_label = "Source"
718     bl_parent_id = "PHYSICS_PT_dynamic_paint"
719     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
720
721     @classmethod
722     def poll(cls, context):
723         if not PhysicButtonsPanel.poll_dyn_canvas_brush(context):
724             return False
725
726         return (context.engine in cls.COMPAT_ENGINES)
727
728     def draw(self, context):
729         layout = self.layout
730         layout.use_property_split = True
731
732         brush = context.dynamic_paint.brush_settings
733         ob = context.object
734
735         layout.prop(brush, "paint_source", text="Paint")
736
737         flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
738
739         if brush.paint_source == 'PARTICLE_SYSTEM':
740             col = flow.column()
741
742             col.separator()
743
744             col.prop_search(brush, "particle_system", ob, "particle_systems")
745
746             if brush.particle_system:
747                 col = flow.column()
748
749                 sub = col.column()
750                 sub.active = not brush.use_particle_radius
751                 sub.prop(brush, "solid_radius", text="Effect Solid Radius")
752
753                 col.prop(brush, "use_particle_radius", text="Use Particle's Radius")
754                 col.prop(brush, "smooth_radius", text="Smooth Radius")
755
756         if brush.paint_source in {'DISTANCE', 'VOLUME_DISTANCE', 'POINT'}:
757             col = flow.column()
758
759             col.separator()
760
761             col.prop(brush, "paint_distance", text="Distance")
762             col.prop(brush, "proximity_falloff")
763
764             if brush.paint_source == 'VOLUME_DISTANCE':
765                 col.prop(brush, "invert_proximity")
766
767                 col = flow.column()
768                 col.prop(brush, "use_negative_volume")
769
770             if brush.paint_source in {'DISTANCE', 'VOLUME_DISTANCE'}:
771                 col = flow.column() if brush.paint_source != 'VOLUME_DISTANCE' else col.column()
772                 col.prop(brush, "use_proximity_project")
773
774                 sub = col.column()
775                 sub.active = brush.use_proximity_project
776                 sub.prop(brush, "ray_direction")
777
778
779 class PHYSICS_PT_dp_brush_source_color_ramp(PhysicButtonsPanel, Panel):
780     bl_label = "Falloff Ramp"
781     bl_parent_id = "PHYSICS_PT_dp_brush_source"
782     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
783
784     @classmethod
785     def poll(cls, context):
786         if not PhysicButtonsPanel.poll_dyn_canvas_brush(context):
787             return False
788
789         brush = context.dynamic_paint.brush_settings
790         return ((brush.paint_source in {'DISTANCE', 'VOLUME_DISTANCE', 'POINT'})
791                 and (brush.proximity_falloff == 'RAMP')
792                 and (context.engine in cls.COMPAT_ENGINES))
793
794     def draw(self, context):
795         layout = self.layout
796         layout.use_property_split = True
797
798         brush = context.dynamic_paint.brush_settings
799         layout.prop(brush, "use_proximity_ramp_alpha", text="Only Use Alpha")
800
801         layout.use_property_split = False
802         layout.template_color_ramp(brush, "paint_ramp", expand=True)
803
804
805 class PHYSICS_PT_dp_brush_velocity(PhysicButtonsPanel, Panel):
806     bl_label = "Velocity"
807     bl_parent_id = "PHYSICS_PT_dynamic_paint"
808     bl_options = {'DEFAULT_CLOSED'}
809     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
810
811     @classmethod
812     def poll(cls, context):
813         if not PhysicButtonsPanel.poll_dyn_canvas_brush(context):
814             return False
815
816         return (context.engine in cls.COMPAT_ENGINES)
817
818     def draw(self, context):
819         layout = self.layout
820         layout.use_property_split = True
821         flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
822
823         brush = context.dynamic_paint.brush_settings
824
825         col = flow.column()
826         col.prop(brush, "use_velocity_alpha")
827         col.prop(brush, "use_velocity_color")
828
829         col = flow.column()
830         col.prop(brush, "use_velocity_depth")
831         sub = col.column()
832         sub.active = (brush.use_velocity_alpha or brush.use_velocity_color or brush.use_velocity_depth)
833         sub.prop(brush, "velocity_max")
834
835
836 class PHYSICS_PT_dp_brush_velocity_color_ramp(PhysicButtonsPanel, Panel):
837     bl_label = "Ramp"
838     bl_parent_id = "PHYSICS_PT_dp_brush_velocity"
839     bl_options = {'DEFAULT_CLOSED'}
840     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
841
842     @classmethod
843     def poll(cls, context):
844         if not PhysicButtonsPanel.poll_dyn_canvas_brush(context):
845             return False
846
847         return (context.engine in cls.COMPAT_ENGINES)
848
849     def draw(self, context):
850         layout = self.layout
851
852         brush = context.dynamic_paint.brush_settings
853
854         layout.template_color_ramp(brush, "velocity_ramp", expand=True)
855
856
857 class PHYSICS_PT_dp_brush_velocity_smudge(PhysicButtonsPanel, Panel):
858     bl_label = "Smudge"
859     bl_parent_id = "PHYSICS_PT_dp_brush_velocity"
860     bl_options = {'DEFAULT_CLOSED'}
861     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
862
863     @classmethod
864     def poll(cls, context):
865         if not PhysicButtonsPanel.poll_dyn_canvas_brush(context):
866             return False
867
868         return (context.engine in cls.COMPAT_ENGINES)
869
870     def draw_header(self, context):
871         brush = context.dynamic_paint.brush_settings
872
873         self.layout.prop(brush, "use_smudge", text="")
874
875     def draw(self, context):
876         layout = self.layout
877         layout.use_property_split = True
878
879         brush = context.dynamic_paint.brush_settings
880
881         layout.active = brush.use_smudge
882         layout.prop(brush, "smudge_strength", text="Strength", slider=True)
883
884
885 class PHYSICS_PT_dp_brush_wave(PhysicButtonsPanel, Panel):
886     bl_label = "Waves"
887     bl_parent_id = "PHYSICS_PT_dynamic_paint"
888     bl_options = {'DEFAULT_CLOSED'}
889     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
890
891     @classmethod
892     def poll(cls, context):
893         if not PhysicButtonsPanel.poll_dyn_canvas_brush(context):
894             return False
895
896         return (context.engine in cls.COMPAT_ENGINES)
897
898     def draw(self, context):
899         layout = self.layout
900         layout.use_property_split = True
901
902         brush = context.dynamic_paint.brush_settings
903
904         layout.prop(brush, "wave_type", text="Type")
905
906         flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=True)
907
908         if brush.wave_type != 'REFLECT':
909             col = flow.column()
910             col.prop(brush, "wave_factor")
911
912             col = flow.column()
913             col.prop(brush, "wave_clamp")
914
915
916 classes = (
917     PHYSICS_UL_dynapaint_surfaces,
918     PHYSICS_PT_dynamic_paint,
919     PHYSICS_PT_dynamic_paint_settings,
920     PHYSICS_PT_dp_advanced_canvas,
921     PHYSICS_PT_dp_advanced_canvas_paint_dissolve,
922     PHYSICS_PT_dp_advanced_canvas_paint_dry,
923     PHYSICS_PT_dp_cache,
924     PHYSICS_PT_dp_effects,
925     PHYSICS_PT_dp_effects_spread,
926     PHYSICS_PT_dp_effects_drip,
927     PHYSICS_PT_dp_effects_drip_weights,
928     PHYSICS_PT_dp_effects_shrink,
929     PHYSICS_PT_dp_canvas_initial_color,
930     PHYSICS_PT_dp_brush_source,
931     PHYSICS_PT_dp_brush_source_color_ramp,
932     PHYSICS_PT_dp_brush_velocity,
933     PHYSICS_PT_dp_brush_velocity_color_ramp,
934     PHYSICS_PT_dp_brush_velocity_smudge,
935     PHYSICS_PT_dp_brush_wave,
936     PHYSICS_PT_dp_canvas_output,
937     PHYSICS_PT_dp_canvas_output_bake,
938     PHYSICS_PT_dp_canvas_output_paintmaps,
939     PHYSICS_PT_dp_canvas_output_wetmaps,
940 )
941
942
943 if __name__ == "__main__":  # only for live edit.
944     from bpy.utils import register_class
945     for cls in classes:
946         register_class(cls)