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