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