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.6)
121                             split.prop(brush, "wave_factor")
122                     elif (brush.brush_settings_context == "VELOCITY"):
123                         col = layout.row().column()
124                         col.label(text="Velocity Settings:")
125                         split = layout.split()
126                         col = split.column()
127                         col.prop(brush, "velocity_alpha")
128                         col.prop(brush, "velocity_color")
129                         col = split.column()
130                         col.prop(brush, "velocity_depth")
131                         sub = layout.row().column()
132                         sub.active = (brush.velocity_alpha or brush.velocity_color or brush.velocity_depth)
133                         sub.prop(brush, "max_velocity")
134                         sub.template_color_ramp(brush, "velocity_ramp", expand=True)
135                         layout.separator()
136                         layout.label(text="Smudge:")
137                         layout.prop(brush, "do_smudge")
138                         layout.prop(brush, "smudge_strength")
139                     else:
140                         layout.label(text="-WIP-")
141
142
143 class PHYSICS_PT_dp_advanced_canvas(PhysicButtonsPanel, bpy.types.Panel):
144     bl_label = "Dynamic Paint: Advanced"
145
146     @classmethod
147     def poll(cls, context):
148         md = context.dynamic_paint
149         return md and (md.ui_type == "CANVAS") and (md.canvas_settings) and (md.canvas_settings.canvas_surfaces.active)
150
151     def draw(self, context):
152         layout = self.layout
153
154         canvas = context.dynamic_paint.canvas_settings
155         surface = canvas.canvas_surfaces.active
156         ob = context.object
157
158         layout.prop(surface, "surface_type", expand=False)
159         layout.separator()
160
161         if (surface.surface_type == "PAINT"):
162             layout.label(text="Wetmap drying:")
163             split = layout.split(percentage=0.8)
164             split.prop(surface, "dry_speed", text="Dry Time")
165             split.prop(surface, "use_dry_log", text="Slow")
166             
167         if (surface.surface_type != "WAVE"):
168             if (surface.surface_type == "DISPLACE"):
169                 layout.prop(surface, "use_dissolve", text="Dissolve:")
170             elif (surface.surface_type == "WEIGHT"):
171                 layout.prop(surface, "use_dissolve", text="Fade:")
172             else:
173                 layout.prop(surface, "use_dissolve", text="Dissolve:")
174             sub = layout.column()
175             sub.active = surface.use_dissolve
176             split = sub.split(percentage=0.8)
177             split.prop(surface, "dissolve_speed", text="Time")
178             split.prop(surface, "use_dissolve_log", text="Slow")
179             
180         if (surface.surface_type == "WAVE"):
181             layout.prop(surface, "wave_open_borders")
182             
183             split = layout.split()
184             
185             col = split.column(align=True)
186             col.prop(surface, "wave_timescale")
187             col.prop(surface, "wave_speed")
188             
189             col = split.column(align=True)
190             col.prop(surface, "wave_damping")
191             col.prop(surface, "wave_spring")
192             
193         layout.label(text="Brush Group:")
194         layout.prop(surface, "brush_group", text="")
195
196
197 class PHYSICS_PT_dp_canvas_output(PhysicButtonsPanel, bpy.types.Panel):
198     bl_label = "Dynamic Paint: Output"
199     bl_options = {'DEFAULT_CLOSED'}
200
201     @classmethod
202     def poll(cls, context):
203         md = context.dynamic_paint
204         if (not (md and (md.ui_type == "CANVAS") and (md.canvas_settings))):
205             return 0
206         surface = context.dynamic_paint.canvas_settings.canvas_surfaces.active
207         return (surface and not (surface.surface_format=="VERTEX" and (surface.surface_type=="DISPLACE" or surface.surface_type=="WAVE")))
208
209     def draw(self, context):
210         layout = self.layout
211
212         canvas = context.dynamic_paint.canvas_settings
213         surface = canvas.canvas_surfaces.active
214         ob = context.object
215         
216         # vertex format outputs
217         if (surface.surface_format == "VERTEX"):
218             if (surface.surface_type == "PAINT"):
219                 # paintmap output
220                 row = layout.row()
221                 row.prop_search(surface, "output_name", ob.data, "vertex_colors", text="Paintmap layer: ")
222                 ic = 'ZOOMIN'
223                 if (surface.output_exists(object=ob, index=0)):
224                     ic = 'ZOOMOUT'
225                 col = row.column(align=True)
226                 col.operator("dpaint.output_toggle", icon=ic, text="").index = 0
227                 
228                 # wetmap output
229                 row = layout.row()
230                 row.prop_search(surface, "output_name2", ob.data, "vertex_colors", text="Wetmap layer: ")
231                 ic = 'ZOOMIN'
232                 if (surface.output_exists(object=ob, index=1)):
233                     ic = 'ZOOMOUT'
234                 col = row.column(align=True)
235                 col.operator("dpaint.output_toggle", icon=ic, text="").index = 1
236             if (surface.surface_type == "WEIGHT"):
237                 row = layout.row()
238                 row.prop_search(surface, "output_name", ob, "vertex_groups", text="Vertex Group: ")
239                 ic = 'ZOOMIN'
240                 if (surface.output_exists(object=ob, index=0)):
241                     ic = 'ZOOMOUT'
242                 col = row.column(align=True)
243                 col.operator("dpaint.output_toggle", icon=ic, text="").index = 0
244
245         # image format outputs
246         if (surface.surface_format == "IMAGE"):
247             col = layout.column()
248             col.label(text="UV layer:")
249             col.prop_search(surface, "uv_layer", ob.data, "uv_textures", text="")
250             
251             col.separator()
252             col = layout.column()
253             col.prop(surface, "image_output_path", text="Output directory")
254             col.prop(surface, "image_fileformat", text="Image Format")
255             col.separator()
256             if (surface.surface_type == "PAINT"):
257                 split = col.split()
258                 col = split.column()
259                 col.prop(surface, "do_output1", text="Output Paintmaps:")
260                 sub = split.column()
261                 sub.prop(surface, "premultiply", text="Premultiply alpha")
262                 sub.active = surface.do_output1
263                 sub = layout.column()
264                 sub.active = surface.do_output1
265                 sub.prop(surface, "output_name", text="Filename: ")
266                 
267                 col = layout.column()
268                 col.prop(surface, "do_output2", text="Output Wetmaps:")
269                 sub = col.column()
270                 sub.active = surface.do_output2
271                 sub.prop(surface, "output_name2", text="Filename: ")
272             else:
273                 col.prop(surface, "output_name", text="Filename: ")
274                 if (surface.surface_type == "DISPLACE"):
275                     col.prop(surface, "disp_type", text="Displace Type")
276             
277             layout.separator()
278             layout.operator("dpaint.bake", text="Bake Image Sequence", icon='MOD_DYNAMICPAINT')
279             if len(canvas.ui_info) != 0:
280                 layout.label(text=canvas.ui_info)
281                 
282
283 class PHYSICS_PT_dp_effects(PhysicButtonsPanel, bpy.types.Panel):
284     bl_label = "Dynamic Paint: Effects"
285     bl_options = {'DEFAULT_CLOSED'}
286
287     @classmethod
288     def poll(cls, context):
289         md = context.dynamic_paint
290         if (not (md and (md.ui_type == "CANVAS") and (md.canvas_settings))):
291             return False;
292         surface = context.dynamic_paint.canvas_settings.canvas_surfaces.active
293         return surface and (surface.surface_type == "PAINT")
294
295     def draw(self, context):
296         layout = self.layout
297
298         canvas = context.dynamic_paint.canvas_settings
299         surface = canvas.canvas_surfaces.active
300
301         layout.prop(surface, "effect_ui", expand=True)
302
303         if surface.effect_ui == "SPREAD":
304             layout.prop(surface, "use_spread")
305             col = layout.column()
306             col.active = surface.use_spread
307             col.prop(surface, "spread_speed")
308
309         elif surface.effect_ui == "DRIP":
310             layout.prop(surface, "use_drip")
311             col = layout.column()
312             col.active = surface.use_drip
313             effector_weights_ui(self, context, surface.effector_weights)
314             split = layout.split()
315
316             layout.label(text="Surface Movement:")
317             split = layout.split()
318             col = split.column()
319             col.prop(surface, "drip_velocity", slider=True)
320             col = split.column()
321             col.prop(surface, "drip_acceleration", slider=True)
322
323         elif surface.effect_ui == "SHRINK":
324             layout.prop(surface, "use_shrink")
325             col = layout.column()
326             col.active = surface.use_shrink
327             col.prop(surface, "shrink_speed")
328                         
329
330 class PHYSICS_PT_dp_cache(PhysicButtonsPanel, bpy.types.Panel):
331     bl_label = "Dynamic Paint: Cache"
332     bl_options = {'DEFAULT_CLOSED'}
333
334     @classmethod
335     def poll(cls, context):
336         md = context.dynamic_paint
337         return md and (md.ui_type == "CANVAS") and (md.canvas_settings) and \
338         (md.canvas_settings.canvas_surfaces.active) and (md.canvas_settings.canvas_surfaces.active.uses_cache)
339
340     def draw(self, context):
341         layout = self.layout
342
343         surface = context.dynamic_paint.canvas_settings.canvas_surfaces.active
344         cache = surface.point_cache
345         
346         point_cache_ui(self, context, cache, (cache.is_baked is False), 'DYNAMIC_PAINT')
347
348
349 class PHYSICS_PT_dp_advanced_brush(PhysicButtonsPanel, bpy.types.Panel):
350     bl_label = "Dynamic Paint: Advanced"
351     bl_options = {'DEFAULT_CLOSED'}
352
353     @classmethod
354     def poll(cls, context):
355         md = context.dynamic_paint
356         return md and (md.ui_type == "BRUSH") and (md.brush_settings)
357
358     def draw(self, context):
359         layout = self.layout
360
361         brush = context.dynamic_paint.brush_settings
362         ob = context.object
363                 
364         split = layout.split()
365         col = split.column()
366         col.prop(brush, "paint_source")
367
368         if brush.paint_source == "PSYS":
369             col.prop_search(brush, "psys", ob, "particle_systems", text="")
370             if brush.psys:
371                 col.label(text="Particle effect:")
372                 sub = col.column()
373                 sub.active = not brush.use_part_radius
374                 sub.prop(brush, "solid_radius", text="Solid Radius")
375                 col.prop(brush, "use_part_radius", text="Use Particle's Radius")
376                 col.prop(brush, "smooth_radius", text="Smooth radius")
377         elif brush.paint_source in {'VOLUME', 'VOLDIST'}:
378             split = layout.row().split(percentage=0.4)
379             sub = split.column()
380             sub.prop(brush, "accept_nonclosed")
381             if brush.accept_nonclosed:
382                 sub = split.column()
383                 sub.prop(brush, "ray_dir")
384                 
385                 
386         if brush.paint_source in {'DISTANCE', 'VOLDIST', 'POINT'}:
387             col.prop(brush, "paint_distance", text="Paint Distance")
388             split = layout.row().split(percentage=0.4)
389             sub = split.column()
390             if (brush.paint_source != 'POINT'):
391                 sub.prop(brush, "prox_facealigned")
392             sub = split.column()
393             sub.prop(brush, "prox_falloff", text="Falloff")
394             if brush.paint_source == "VOLDIST":
395                 col = layout.row().column()
396                 col.prop(brush, "prox_inverse")
397             if brush.prox_falloff == "RAMP":
398                 col = layout.row().column()
399                 col.separator()
400                 col.prop(brush, "prox_ramp_alpha", text="Only Use Alpha")
401                 col.template_color_ramp(brush, "paint_ramp", expand=True)
402
403 def register():
404     bpy.utils.register_module(__name__)
405
406
407 def unregister():
408     bpy.utils.register_module(__name__)
409
410 if __name__ == "__main__":
411     register()