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