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