Dynamic Paint:
[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 import bpy
21
22 from bl_ui.properties_physics_common import (
23     point_cache_ui,
24     effector_weights_ui,
25     )
26
27 class PhysicButtonsPanel():
28     bl_space_type = 'PROPERTIES'
29     bl_region_type = 'WINDOW'
30     bl_context = "physics"
31
32     @classmethod
33     def poll(cls, context):
34         ob = context.object
35         rd = context.scene.render
36         return (ob and ob.type == 'MESH') and (not rd.use_game_engine) and (context.dynamic_paint)
37
38
39 class PHYSICS_PT_dynamic_paint(PhysicButtonsPanel, bpy.types.Panel):
40     bl_label = "Dynamic Paint"
41
42     def draw(self, context):
43         layout = self.layout
44
45         md = context.dynamic_paint
46         ob = context.object
47
48         if md:
49             layout.prop(md, "ui_type", expand=True)
50
51             if (md.ui_type == "CANVAS"):
52                 canvas = md.canvas_settings
53                 
54                 if (not canvas):
55                     layout.operator("dpaint.type_toggle", text="Add Canvas").type = 'CANVAS'
56                 else:
57                     layout.operator("dpaint.type_toggle", text="Remove Canvas", icon='X').type = 'CANVAS'
58
59                     surface = canvas.canvas_surfaces.active
60                     row = layout.row()
61                     row.template_list(canvas, "canvas_surfaces", canvas.canvas_surfaces, "active_index", rows=2)
62
63                     col = row.column(align=True)
64                     col.operator("dpaint.surface_slot_add", icon='ZOOMIN', text="")
65                     col.operator("dpaint.surface_slot_remove", icon='ZOOMOUT', text="")
66                     
67                     if surface:
68                         layout.prop(surface, "name")
69                         layout.prop(surface, "surface_format", expand=False)
70                         col = layout.column()
71                         
72                         if surface.surface_format != "VERTEX":
73                             col.label(text="Quality:")
74                             col.prop(surface, "image_resolution")
75                         col.prop(surface, "use_anti_aliasing")
76                     
77                         col = layout.column()
78                         col.label(text="Frames:")
79                         split = col.split()
80                     
81                         col = split.column(align=True)
82                         col.prop(surface, "start_frame", text="Start")
83                         col.prop(surface, "end_frame", text="End")
84                     
85                         col = split.column()
86                         col.prop(surface, "substeps")
87
88             elif (md.ui_type == "BRUSH"):
89                 brush = md.brush_settings
90                 
91                 if (not brush):
92                     layout.operator("dpaint.type_toggle", text="Add Brush").type = 'BRUSH'
93                 else:
94                     layout.operator("dpaint.type_toggle", text="Remove Brush", icon='X').type = 'BRUSH'
95                     
96                     layout.prop(brush, "brush_settings_context", expand=True, icon_only=True)
97                     
98                     if (brush.brush_settings_context == "GENERAL"):
99                         split = layout.split()
100
101                         col = split.column()
102                         col.prop(brush, "absolute_alpha")
103                         col.prop(brush, "paint_erase")
104                         col.prop(brush, "paint_wetness", text="Wetness")
105                     
106                         col = split.column()
107                         sub = col.column()
108                         sub.active = (brush.paint_source != "PSYS");
109                         sub.prop(brush, "use_material")
110                         if brush.use_material and brush.paint_source != "PSYS":
111                             col.prop(brush, "material", text="")
112                             col.prop(brush, "paint_alpha", text="Alpha Factor")
113                         else:
114                             col.prop(brush, "paint_color", text="")
115                             col.prop(brush, "paint_alpha", text="Alpha")
116                     
117                     elif (brush.brush_settings_context == "WAVE"):
118                         layout.prop(brush, "wave_type")
119                         if (brush.wave_type != "REFLECT"):
120                             split = layout.split(percentage=0.5)
121                             col = split.column()
122                             col.prop(brush, "wave_factor")
123                             col = split.column()
124                             col.prop(brush, "wave_clamp")
125                     elif (brush.brush_settings_context == "VELOCITY"):
126                         col = layout.row().column()
127                         col.label(text="Velocity Settings:")
128                         split = layout.split()
129                         col = split.column()
130                         col.prop(brush, "velocity_alpha")
131                         col.prop(brush, "velocity_color")
132                         col = split.column()
133                         col.prop(brush, "velocity_depth")
134                         sub = layout.row().column()
135                         sub.active = (brush.velocity_alpha or brush.velocity_color or brush.velocity_depth)
136                         sub.prop(brush, "max_velocity")
137                         sub.template_color_ramp(brush, "velocity_ramp", expand=True)
138                         layout.separator()
139                         layout.label(text="Smudge:")
140                         layout.prop(brush, "do_smudge")
141                         layout.prop(brush, "smudge_strength")
142                     else:
143                         layout.label(text="-WIP-")
144
145
146 class PHYSICS_PT_dp_advanced_canvas(PhysicButtonsPanel, bpy.types.Panel):
147     bl_label = "Dynamic Paint: Advanced"
148
149     @classmethod
150     def poll(cls, context):
151         md = context.dynamic_paint
152         return md and (md.ui_type == "CANVAS") and (md.canvas_settings) and (md.canvas_settings.canvas_surfaces.active)
153
154     def draw(self, context):
155         layout = self.layout
156
157         canvas = context.dynamic_paint.canvas_settings
158         surface = canvas.canvas_surfaces.active
159         ob = context.object
160
161         layout.prop(surface, "surface_type", expand=False)
162         layout.separator()
163
164         # dissolve
165         if (surface.surface_type == "PAINT"):
166             layout.label(text="Wetmap drying:")
167             split = layout.split(percentage=0.8)
168             split.prop(surface, "dry_speed", text="Dry Time")
169             split.prop(surface, "use_dry_log", text="Slow")
170             
171         if (surface.surface_type != "WAVE"):
172             if (surface.surface_type == "DISPLACE"):
173                 layout.prop(surface, "use_dissolve", text="Dissolve:")
174             elif (surface.surface_type == "WEIGHT"):
175                 layout.prop(surface, "use_dissolve", text="Fade:")
176             else:
177                 layout.prop(surface, "use_dissolve", text="Dissolve:")
178             sub = layout.column()
179             sub.active = surface.use_dissolve
180             split = sub.split(percentage=0.8)
181             split.prop(surface, "dissolve_speed", text="Time")
182             split.prop(surface, "use_dissolve_log", text="Slow")
183         
184         # per type settings
185         if (surface.surface_type == "DISPLACE"):
186             layout.prop(surface, "disp_clamp")
187             layout.prop(surface, "incremental_disp")
188             
189         if (surface.surface_type == "WAVE"):
190             layout.prop(surface, "wave_open_borders")
191             
192             split = layout.split()
193             
194             col = split.column(align=True)
195             col.prop(surface, "wave_timescale")
196             col.prop(surface, "wave_speed")
197             
198             col = split.column(align=True)
199             col.prop(surface, "wave_damping")
200             col.prop(surface, "wave_spring")
201             
202         layout.label(text="Brush Group:")
203         layout.prop(surface, "brush_group", text="")
204
205 class PHYSICS_PT_dp_canvas_output(PhysicButtonsPanel, bpy.types.Panel):
206     bl_label = "Dynamic Paint: Output"
207     bl_options = {'DEFAULT_CLOSED'}
208
209     @classmethod
210     def poll(cls, context):
211         md = context.dynamic_paint
212         if (not (md and (md.ui_type == "CANVAS") and (md.canvas_settings))):
213             return 0
214         surface = context.dynamic_paint.canvas_settings.canvas_surfaces.active
215         return (surface and not (surface.surface_format=="VERTEX" and (surface.surface_type=="DISPLACE" or surface.surface_type=="WAVE")))
216
217     def draw(self, context):
218         layout = self.layout
219
220         canvas = context.dynamic_paint.canvas_settings
221         surface = canvas.canvas_surfaces.active
222         ob = context.object
223         
224         # vertex format outputs
225         if (surface.surface_format == "VERTEX"):
226             if (surface.surface_type == "PAINT"):
227                  # toggle active preview
228                 layout.prop(surface, "preview_id")
229                 
230                 # paintmap output
231                 row = layout.row()
232                 row.prop_search(surface, "output_name", ob.data, "vertex_colors", text="Paintmap layer: ")
233                 ic = 'ZOOMIN'
234                 if (surface.output_exists(object=ob, index=0)):
235                     ic = 'ZOOMOUT'
236                 col = row.column(align=True)
237                 col.operator("dpaint.output_toggle", icon=ic, text="").index = 0
238                 
239                 # wetmap output
240                 row = layout.row()
241                 row.prop_search(surface, "output_name2", ob.data, "vertex_colors", text="Wetmap layer: ")
242                 ic = 'ZOOMIN'
243                 if (surface.output_exists(object=ob, index=1)):
244                     ic = 'ZOOMOUT'
245                 col = row.column(align=True)
246                 col.operator("dpaint.output_toggle", icon=ic, text="").index = 1
247             if (surface.surface_type == "WEIGHT"):
248                 row = layout.row()
249                 row.prop_search(surface, "output_name", ob, "vertex_groups", text="Vertex Group: ")
250                 ic = 'ZOOMIN'
251                 if (surface.output_exists(object=ob, index=0)):
252                     ic = 'ZOOMOUT'
253                 col = row.column(align=True)
254                 col.operator("dpaint.output_toggle", icon=ic, text="").index = 0
255
256         # image format outputs
257         if (surface.surface_format == "IMAGE"):
258             col = layout.column()
259             col.label(text="UV layer:")
260             col.prop_search(surface, "uv_layer", ob.data, "uv_textures", text="")
261             
262             col.separator()
263             col = layout.column()
264             col.prop(surface, "image_output_path", text="Output directory")
265             col.prop(surface, "image_fileformat", text="Image Format")
266             col.separator()
267             if (surface.surface_type == "PAINT"):
268                 split = col.split()
269                 col = split.column()
270                 col.prop(surface, "do_output1", text="Output Paintmaps:")
271                 sub = split.column()
272                 sub.prop(surface, "premultiply", text="Premultiply alpha")
273                 sub.active = surface.do_output1
274                 sub = layout.column()
275                 sub.active = surface.do_output1
276                 sub.prop(surface, "output_name", text="Filename: ")
277                 
278                 col = layout.column()
279                 col.prop(surface, "do_output2", text="Output Wetmaps:")
280                 sub = col.column()
281                 sub.active = surface.do_output2
282                 sub.prop(surface, "output_name2", text="Filename: ")
283             else:
284                 col.prop(surface, "output_name", text="Filename: ")
285                 if (surface.surface_type == "DISPLACE"):
286                     col.prop(surface, "disp_type", text="Displace Type")
287             
288             layout.separator()
289             layout.operator("dpaint.bake", text="Bake Image Sequence", icon='MOD_DYNAMICPAINT')
290             if len(canvas.ui_info) != 0:
291                 layout.label(text=canvas.ui_info)
292
293 class PHYSICS_PT_dp_canvas_initial_color(PhysicButtonsPanel, bpy.types.Panel):
294     bl_label = "Dynamic Paint: Initial Color"
295     bl_options = {'DEFAULT_CLOSED'}
296
297     @classmethod
298     def poll(cls, context):
299         md = context.dynamic_paint
300         if (not (md and (md.ui_type == "CANVAS") and (md.canvas_settings))):
301             return 0
302         surface = context.dynamic_paint.canvas_settings.canvas_surfaces.active
303         return (surface and surface.surface_type=="PAINT")
304
305     def draw(self, context):
306         layout = self.layout
307
308         canvas = context.dynamic_paint.canvas_settings
309         surface = canvas.canvas_surfaces.active
310         ob = context.object
311
312         layout.prop(surface, "init_color_type", expand=False)
313         layout.separator()
314
315         # dissolve
316         if (surface.init_color_type == "COLOR"):
317             layout.prop(surface, "init_color")
318             
319         if (surface.init_color_type == "TEXTURE"):
320             layout.prop(surface, "init_texture")
321             layout.prop_search(surface, "init_layername", ob.data, "uv_textures", text="UV Layer:")
322         
323         if (surface.init_color_type == "VERTEXCOLOR"):
324             layout.prop_search(surface, "init_layername", ob.data, "vertex_colors", text="Color Layer: ")
325
326 class PHYSICS_PT_dp_effects(PhysicButtonsPanel, bpy.types.Panel):
327     bl_label = "Dynamic Paint: Effects"
328     bl_options = {'DEFAULT_CLOSED'}
329
330     @classmethod
331     def poll(cls, context):
332         md = context.dynamic_paint
333         if (not (md and (md.ui_type == "CANVAS") and (md.canvas_settings))):
334             return False;
335         surface = context.dynamic_paint.canvas_settings.canvas_surfaces.active
336         return surface and (surface.surface_type == "PAINT")
337
338     def draw(self, context):
339         layout = self.layout
340
341         canvas = context.dynamic_paint.canvas_settings
342         surface = canvas.canvas_surfaces.active
343
344         layout.prop(surface, "effect_ui", expand=True)
345
346         if surface.effect_ui == "SPREAD":
347             layout.prop(surface, "use_spread")
348             col = layout.column()
349             col.active = surface.use_spread
350             split = col.split()
351             sub = split.column()
352             sub.prop(surface, "spread_speed")
353             sub = split.column()
354             sub.prop(surface, "color_spread_speed")
355
356         elif surface.effect_ui == "DRIP":
357             layout.prop(surface, "use_drip")
358             col = layout.column()
359             col.active = surface.use_drip
360             effector_weights_ui(self, context, surface.effector_weights)
361             split = layout.split()
362
363             layout.label(text="Surface Movement:")
364             split = layout.split()
365             col = split.column()
366             col.prop(surface, "drip_velocity", slider=True)
367             col = split.column()
368             col.prop(surface, "drip_acceleration", slider=True)
369
370         elif surface.effect_ui == "SHRINK":
371             layout.prop(surface, "use_shrink")
372             col = layout.column()
373             col.active = surface.use_shrink
374             col.prop(surface, "shrink_speed")
375                         
376
377 class PHYSICS_PT_dp_cache(PhysicButtonsPanel, bpy.types.Panel):
378     bl_label = "Dynamic Paint: Cache"
379     bl_options = {'DEFAULT_CLOSED'}
380
381     @classmethod
382     def poll(cls, context):
383         md = context.dynamic_paint
384         return md and (md.ui_type == "CANVAS") and (md.canvas_settings) and \
385         (md.canvas_settings.canvas_surfaces.active) and (md.canvas_settings.canvas_surfaces.active.uses_cache)
386
387     def draw(self, context):
388         layout = self.layout
389
390         surface = context.dynamic_paint.canvas_settings.canvas_surfaces.active
391         cache = surface.point_cache
392         
393         point_cache_ui(self, context, cache, (cache.is_baked is False), 'DYNAMIC_PAINT')
394
395
396 class PHYSICS_PT_dp_advanced_brush(PhysicButtonsPanel, bpy.types.Panel):
397     bl_label = "Dynamic Paint: Advanced"
398     bl_options = {'DEFAULT_CLOSED'}
399
400     @classmethod
401     def poll(cls, context):
402         md = context.dynamic_paint
403         return md and (md.ui_type == "BRUSH") and (md.brush_settings)
404
405     def draw(self, context):
406         layout = self.layout
407
408         brush = context.dynamic_paint.brush_settings
409         ob = context.object
410                 
411         split = layout.split()
412         col = split.column()
413         col.prop(brush, "paint_source")
414
415         if brush.paint_source == "PSYS":
416             col.prop_search(brush, "psys", ob, "particle_systems", text="")
417             if brush.psys:
418                 col.label(text="Particle effect:")
419                 sub = col.column()
420                 sub.active = not brush.use_part_radius
421                 sub.prop(brush, "solid_radius", text="Solid Radius")
422                 col.prop(brush, "use_part_radius", text="Use Particle's Radius")
423                 col.prop(brush, "smooth_radius", text="Smooth radius")
424                 
425         if brush.paint_source in {'DISTANCE', 'VOLDIST', 'POINT'}:
426             col.prop(brush, "paint_distance", text="Paint Distance")
427             split = layout.row().split(percentage=0.4)
428             sub = split.column()
429             if brush.paint_source == 'DISTANCE':
430                 sub.prop(brush, "prox_project")
431             if brush.paint_source == "VOLDIST":
432                 sub.prop(brush, "prox_inverse")
433                 
434             sub = split.column()
435             if brush.paint_source == 'DISTANCE':
436                 column = sub.column()
437                 column.active = brush.prox_project
438                 column.prop(brush, "ray_dir")
439             sub.prop(brush, "prox_falloff")
440             if brush.prox_falloff == "RAMP":
441                 col = layout.row().column()
442                 col.separator()
443                 col.prop(brush, "prox_ramp_alpha", text="Only Use Alpha")
444                 col.template_color_ramp(brush, "paint_ramp", expand=True)
445
446 def register():
447     bpy.utils.register_module(__name__)
448
449
450 def unregister():
451     bpy.utils.register_module(__name__)
452
453 if __name__ == "__main__":
454     register()