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