Merged revision(s) 57671-57767 from trunk/blender into soc-2013-dingto
[blender.git] / intern / cycles / blender / addon / ui.py
1 #
2 # Copyright 2011, Blender Foundation.
3 #
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 # GNU General Public License for more details.
13 #
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software Foundation,
16 # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 #
18
19 # <pep8 compliant>
20
21 import bpy
22
23 from bpy.types import Panel, Menu, Operator
24
25
26 class CYCLES_MT_integrator_presets(Menu):
27     bl_label = "Integrator Presets"
28     preset_subdir = "cycles/integrator"
29     preset_operator = "script.execute_preset"
30     COMPAT_ENGINES = {'CYCLES'}
31     draw = Menu.draw_preset
32
33
34 class CyclesButtonsPanel():
35     bl_space_type = "PROPERTIES"
36     bl_region_type = "WINDOW"
37     bl_context = "render"
38
39     @classmethod
40     def poll(cls, context):
41         rd = context.scene.render
42         return rd.engine == 'CYCLES'
43
44
45 class CyclesRender_PT_sampling(CyclesButtonsPanel, Panel):
46     bl_label = "Sampling"
47     bl_options = {'DEFAULT_CLOSED'}
48
49     def draw(self, context):
50         layout = self.layout
51
52         scene = context.scene
53         cscene = scene.cycles
54
55         split = layout.split()
56
57         col = split.column()
58         col.prop(cscene, "progressive")
59
60         sub = col.column(align=True)
61         sub.prop(cscene, "seed")
62         sub.prop(cscene, "sample_clamp")
63
64         if cscene.progressive:
65             col = split.column()
66             col.label(text="Samples:")
67             sub = col.column(align=True)
68             sub.prop(cscene, "samples", text="Render")
69             sub.prop(cscene, "preview_samples", text="Preview")
70         else:
71             sub.label(text="AA Samples:")
72             sub.prop(cscene, "aa_samples", text="Render")
73             sub.prop(cscene, "preview_aa_samples", text="Preview")
74
75             col = split.column()
76             col.label(text="Samples:")
77             sub = col.column(align=True)
78             sub.prop(cscene, "diffuse_samples", text="Diffuse")
79             sub.prop(cscene, "glossy_samples", text="Glossy")
80             sub.prop(cscene, "transmission_samples", text="Transmission")
81             sub.prop(cscene, "ao_samples", text="AO")
82             sub.prop(cscene, "mesh_light_samples", text="Mesh Light")
83             sub.prop(cscene, "subsurface_samples", text="Subsurface")
84
85         if cscene.feature_set == 'EXPERIMENTAL' and (device_type == 'NONE' or cscene.device == 'CPU'):
86             layout.row().prop(cscene, "sampling_pattern", text="Pattern")
87
88         for rl in scene.render.layers:
89             if rl.samples > 0:
90                 layout.separator()
91                 layout.row().prop(cscene, "use_layer_samples")
92                 break
93
94
95 class CyclesRender_PT_light_paths(CyclesButtonsPanel, Panel):
96     bl_label = "Light Paths"
97     bl_options = {'DEFAULT_CLOSED'}
98
99     def draw(self, context):
100         layout = self.layout
101
102         scene = context.scene
103         cscene = scene.cycles
104
105         row = layout.row(align=True)
106         row.menu("CYCLES_MT_integrator_presets", text=bpy.types.CYCLES_MT_integrator_presets.bl_label)
107         row.operator("render.cycles_integrator_preset_add", text="", icon="ZOOMIN")
108         row.operator("render.cycles_integrator_preset_add", text="", icon="ZOOMOUT").remove_active = True
109
110         split = layout.split()
111
112         col = split.column()
113
114         sub = col.column(align=True)
115         sub.label("Transparency:")
116         sub.prop(cscene, "transparent_max_bounces", text="Max")
117         sub.prop(cscene, "transparent_min_bounces", text="Min")
118         sub.prop(cscene, "use_transparent_shadows", text="Shadows")
119
120         col.separator()
121
122         col.prop(cscene, "no_caustics")
123         col.prop(cscene, "blur_glossy")
124
125         col = split.column()
126
127         sub = col.column(align=True)
128         sub.label(text="Bounces:")
129         sub.prop(cscene, "max_bounces", text="Max")
130         sub.prop(cscene, "min_bounces", text="Min")
131
132         sub = col.column(align=True)
133         sub.prop(cscene, "diffuse_bounces", text="Diffuse")
134         sub.prop(cscene, "glossy_bounces", text="Glossy")
135         sub.prop(cscene, "transmission_bounces", text="Transmission")
136
137
138 class CyclesRender_PT_motion_blur(CyclesButtonsPanel, Panel):
139     bl_label = "Motion Blur"
140     bl_options = {'DEFAULT_CLOSED'}
141
142     def draw_header(self, context):
143         rd = context.scene.render
144
145         self.layout.prop(rd, "use_motion_blur", text="")
146
147     def draw(self, context):
148         layout = self.layout
149
150         rd = context.scene.render
151         layout.active = rd.use_motion_blur
152
153         row = layout.row()
154         row.prop(rd, "motion_blur_shutter")
155
156
157 class CyclesRender_PT_film(CyclesButtonsPanel, Panel):
158     bl_label = "Film"
159
160     def draw(self, context):
161         layout = self.layout
162
163         scene = context.scene
164         cscene = scene.cycles
165
166         split = layout.split()
167
168         col = split.column()
169         col.prop(cscene, "film_exposure")
170         col.prop(cscene, "film_transparent")
171
172         col = split.column()
173         sub = col.column(align=True)
174         sub.prop(cscene, "filter_type", text="")
175         if cscene.filter_type != 'BOX':
176             sub.prop(cscene, "filter_width", text="Width")
177
178
179 class CyclesRender_PT_performance(CyclesButtonsPanel, Panel):
180     bl_label = "Performance"
181     bl_options = {'DEFAULT_CLOSED'}
182
183     def draw(self, context):
184         layout = self.layout
185
186         scene = context.scene
187         rd = scene.render
188         cscene = scene.cycles
189
190         split = layout.split()
191
192         col = split.column(align=True)
193
194         col.label(text="Threads:")
195         col.row().prop(rd, "threads_mode", expand=True)
196         sub = col.column()
197         sub.enabled = rd.threads_mode == 'FIXED'
198         sub.prop(rd, "threads")
199
200         sub = col.column(align=True)
201         sub.label(text="Tiles:")
202         sub.prop(cscene, "tile_order", text="")
203
204         sub.prop(rd, "tile_x", text="X")
205         sub.prop(rd, "tile_y", text="Y")
206
207         sub.prop(cscene, "use_progressive_refine")
208
209         subsub = sub.column()
210         subsub.enabled = not rd.use_border
211         subsub.prop(rd, "use_save_buffers")
212
213         col = split.column()
214
215         sub = col.column(align=True)
216         sub.label(text="Acceleration structure:")
217         sub.prop(cscene, "debug_bvh_type", text="")
218         sub.prop(cscene, "debug_use_spatial_splits")
219         sub.prop(cscene, "use_cache")
220
221         sub = col.column(align=True)
222         sub.label(text="Viewport:")
223         sub.prop(cscene, "preview_start_resolution")
224
225         sub = col.column(align=True)
226         sub.label(text="Final Render:")
227         sub.prop(rd, "use_persistent_data", text="Persistent Images")
228
229
230 class CyclesRender_PT_opengl(CyclesButtonsPanel, Panel):
231     bl_label = "OpenGL Render"
232     bl_options = {'DEFAULT_CLOSED'}
233
234     def draw(self, context):
235         layout = self.layout
236
237         rd = context.scene.render
238
239         split = layout.split()
240
241         col = split.column()
242         col.prop(rd, "use_antialiasing")
243         sub = col.row()
244         sub.active = rd.use_antialiasing
245         sub.prop(rd, "antialiasing_samples", expand=True)
246
247         col = split.column()
248         col.label(text="Alpha:")
249         col.prop(rd, "alpha_mode", text="")
250
251
252 class CyclesRender_PT_layers(CyclesButtonsPanel, Panel):
253     bl_label = "Layer List"
254     bl_context = "render_layer"
255     bl_options = {'HIDE_HEADER'}
256
257     def draw(self, context):
258         layout = self.layout
259
260         scene = context.scene
261         rd = scene.render
262         rl = rd.layers.active
263
264         row = layout.row()
265         row.template_list("RENDERLAYER_UL_renderlayers", "", rd, "layers", rd.layers, "active_index", rows=2)
266
267         col = row.column(align=True)
268         col.operator("scene.render_layer_add", icon='ZOOMIN', text="")
269         col.operator("scene.render_layer_remove", icon='ZOOMOUT', text="")
270
271         row = layout.row()
272         if rl:
273             row.prop(rl, "name")
274         row.prop(rd, "use_single_layer", text="", icon_only=True)
275
276
277 class CyclesRender_PT_layer_options(CyclesButtonsPanel, Panel):
278     bl_label = "Layer"
279     bl_context = "render_layer"
280
281     def draw(self, context):
282         layout = self.layout
283
284         scene = context.scene
285         rd = scene.render
286         rl = rd.layers.active
287
288         split = layout.split()
289
290         col = split.column()
291         col.prop(scene, "layers", text="Scene")
292         col.prop(rl, "layers_exclude", text="Exclude")
293
294         col = split.column()
295         col.prop(rl, "layers", text="Layer")
296         col.prop(rl, "layers_zmask", text="Mask Layer")
297
298         split = layout.split()
299
300         col = split.column()
301         col.label(text="Material:")
302         col.prop(rl, "material_override", text="")
303         col.separator()
304         col.prop(rl, "samples")
305
306         col = split.column()
307         col.prop(rl, "use_sky", "Use Environment")
308         col.prop(rl, "use_solid", "Use Surfaces")
309         col.prop(rl, "use_strand", "Use Hair")
310
311
312 class CyclesRender_PT_layer_passes(CyclesButtonsPanel, Panel):
313     bl_label = "Passes"
314     bl_context = "render_layer"
315     bl_options = {'DEFAULT_CLOSED'}
316
317     def draw(self, context):
318         layout = self.layout
319
320         scene = context.scene
321         rd = scene.render
322         rl = rd.layers.active
323
324         split = layout.split()
325
326         col = split.column()
327         col.prop(rl, "use_pass_combined")
328         col.prop(rl, "use_pass_z")
329         col.prop(rl, "use_pass_mist")
330         col.prop(rl, "use_pass_normal")
331         col.prop(rl, "use_pass_vector")
332         col.prop(rl, "use_pass_uv")
333         col.prop(rl, "use_pass_object_index")
334         col.prop(rl, "use_pass_material_index")
335         col.prop(rl, "use_pass_shadow")
336
337         col = split.column()
338         col.label(text="Diffuse:")
339         row = col.row(align=True)
340         row.prop(rl, "use_pass_diffuse_direct", text="Direct", toggle=True)
341         row.prop(rl, "use_pass_diffuse_indirect", text="Indirect", toggle=True)
342         row.prop(rl, "use_pass_diffuse_color", text="Color", toggle=True)
343         col.label(text="Glossy:")
344         row = col.row(align=True)
345         row.prop(rl, "use_pass_glossy_direct", text="Direct", toggle=True)
346         row.prop(rl, "use_pass_glossy_indirect", text="Indirect", toggle=True)
347         row.prop(rl, "use_pass_glossy_color", text="Color", toggle=True)
348         col.label(text="Transmission:")
349         row = col.row(align=True)
350         row.prop(rl, "use_pass_transmission_direct", text="Direct", toggle=True)
351         row.prop(rl, "use_pass_transmission_indirect", text="Indirect", toggle=True)
352         row.prop(rl, "use_pass_transmission_color", text="Color", toggle=True)
353
354         col.prop(rl, "use_pass_emit", text="Emission")
355         col.prop(rl, "use_pass_environment")
356         col.prop(rl, "use_pass_ambient_occlusion")
357
358
359 class Cycles_PT_post_processing(CyclesButtonsPanel, Panel):
360     bl_label = "Post Processing"
361     bl_options = {'DEFAULT_CLOSED'}
362
363     def draw(self, context):
364         layout = self.layout
365
366         rd = context.scene.render
367
368         split = layout.split()
369
370         col = split.column()
371         col.prop(rd, "use_compositing")
372         col.prop(rd, "use_sequencer")
373
374         col = split.column()
375         col.prop(rd, "dither_intensity", text="Dither", slider=True)
376
377
378 class CyclesCamera_PT_dof(CyclesButtonsPanel, Panel):
379     bl_label = "Depth of Field"
380     bl_context = "data"
381
382     @classmethod
383     def poll(cls, context):
384         return context.camera and CyclesButtonsPanel.poll(context)
385
386     def draw(self, context):
387         layout = self.layout
388
389         cam = context.camera
390         ccam = cam.cycles
391
392         split = layout.split()
393
394         col = split.column()
395         col.label("Focus:")
396         col.prop(cam, "dof_object", text="")
397
398         sub = col.row()
399         sub.active = cam.dof_object is None
400         sub.prop(cam, "dof_distance", text="Distance")
401
402         col = split.column()
403
404         col.label("Aperture:")
405         sub = col.column(align=True)
406         sub.prop(ccam, "aperture_type", text="")
407         if ccam.aperture_type == 'RADIUS':
408             sub.prop(ccam, "aperture_size", text="Size")
409         elif ccam.aperture_type == 'FSTOP':
410             sub.prop(ccam, "aperture_fstop", text="Number")
411
412         sub = col.column(align=True)
413         sub.prop(ccam, "aperture_blades", text="Blades")
414         sub.prop(ccam, "aperture_rotation", text="Rotation")
415
416
417 class Cycles_PT_context_material(CyclesButtonsPanel, Panel):
418     bl_label = ""
419     bl_context = "material"
420     bl_options = {'HIDE_HEADER'}
421
422     @classmethod
423     def poll(cls, context):
424         return (context.material or context.object) and CyclesButtonsPanel.poll(context)
425
426     def draw(self, context):
427         layout = self.layout
428
429         mat = context.material
430         ob = context.object
431         slot = context.material_slot
432         space = context.space_data
433
434         if ob:
435             row = layout.row()
436
437             row.template_list("MATERIAL_UL_matslots", "", ob, "material_slots", ob, "active_material_index", rows=2)
438
439             col = row.column(align=True)
440             col.operator("object.material_slot_add", icon='ZOOMIN', text="")
441             col.operator("object.material_slot_remove", icon='ZOOMOUT', text="")
442
443             col.menu("MATERIAL_MT_specials", icon='DOWNARROW_HLT', text="")
444
445             if ob.mode == 'EDIT':
446                 row = layout.row(align=True)
447                 row.operator("object.material_slot_assign", text="Assign")
448                 row.operator("object.material_slot_select", text="Select")
449                 row.operator("object.material_slot_deselect", text="Deselect")
450
451         split = layout.split(percentage=0.65)
452
453         if ob:
454             split.template_ID(ob, "active_material", new="material.new")
455             row = split.row()
456
457             if slot:
458                 row.prop(slot, "link", text="")
459             else:
460                 row.label()
461         elif mat:
462             split.template_ID(space, "pin_id")
463             split.separator()
464
465
466 class Cycles_PT_mesh_displacement(CyclesButtonsPanel, Panel):
467     bl_label = "Displacement"
468     bl_context = "data"
469
470     @classmethod
471     def poll(cls, context):
472         if CyclesButtonsPanel.poll(context):
473             if context.mesh or context.curve or context.meta_ball:
474                 if context.scene.cycles.feature_set == 'EXPERIMENTAL':
475                     return True
476
477         return False
478
479     def draw(self, context):
480         layout = self.layout
481
482         mesh = context.mesh
483         curve = context.curve
484         mball = context.meta_ball
485
486         if mesh:
487             cdata = mesh.cycles
488         elif curve:
489             cdata = curve.cycles
490         elif mball:
491             cdata = mball.cycles
492
493         layout.prop(cdata, "displacement_method", text="Method")
494         layout.prop(cdata, "use_subdivision")
495         layout.prop(cdata, "dicing_rate")
496
497
498 class Cycles_PT_mesh_normals(CyclesButtonsPanel, Panel):
499     bl_label = "Normals"
500     bl_context = "data"
501
502     @classmethod
503     def poll(cls, context):
504         return CyclesButtonsPanel.poll(context) and context.mesh
505
506     def draw(self, context):
507         layout = self.layout
508
509         mesh = context.mesh
510
511         split = layout.split()
512
513         col = split.column()
514         col.prop(mesh, "show_double_sided")
515
516         col = split.column()
517         col.label()
518
519
520 class CyclesObject_PT_ray_visibility(CyclesButtonsPanel, Panel):
521     bl_label = "Ray Visibility"
522     bl_context = "object"
523     bl_options = {'DEFAULT_CLOSED'}
524
525     @classmethod
526     def poll(cls, context):
527         ob = context.object
528         return CyclesButtonsPanel.poll(context) and ob and ob.type in {'MESH', 'CURVE', 'CURVE', 'SURFACE', 'FONT', 'META', 'LAMP'}
529
530     def draw(self, context):
531         layout = self.layout
532
533         ob = context.object
534         visibility = ob.cycles_visibility
535
536         flow = layout.column_flow()
537
538         flow.prop(visibility, "camera")
539         flow.prop(visibility, "diffuse")
540         flow.prop(visibility, "glossy")
541         flow.prop(visibility, "transmission")
542
543         if ob.type != 'LAMP':
544             flow.prop(visibility, "shadow")
545
546
547 class CYCLES_OT_use_shading_nodes(Operator):
548     """Enable nodes on a material, world or lamp"""
549     bl_idname = "cycles.use_shading_nodes"
550     bl_label = "Use Nodes"
551
552     @classmethod
553     def poll(cls, context):
554         return context.material or context.world or context.lamp
555
556     def execute(self, context):
557         if context.material:
558             context.material.use_nodes = True
559         elif context.world:
560             context.world.use_nodes = True
561         elif context.lamp:
562             context.lamp.use_nodes = True
563
564         return {'FINISHED'}
565
566
567 def find_node(material, nodetype):
568     if material and material.node_tree:
569         ntree = material.node_tree
570
571         for node in ntree.nodes:
572             if getattr(node, "type", None) == nodetype:
573                 return node
574
575     return None
576
577
578 def find_node_input(node, name):
579     for input in node.inputs:
580         if input.name == name:
581             return input
582
583     return None
584
585
586 def panel_node_draw(layout, id_data, output_type, input_name):
587     if not id_data.use_nodes:
588         layout.operator("cycles.use_shading_nodes", icon='NODETREE')
589         return False
590
591     ntree = id_data.node_tree
592
593     node = find_node(id_data, output_type)
594     if not node:
595         layout.label(text="No output node")
596     else:
597         input = find_node_input(node, input_name)
598         layout.template_node_view(ntree, node, input)
599
600     return True
601
602
603 class CyclesLamp_PT_preview(CyclesButtonsPanel, Panel):
604     bl_label = "Preview"
605     bl_context = "data"
606     bl_options = {'DEFAULT_CLOSED'}
607
608     @classmethod
609     def poll(cls, context):
610         return context.lamp and CyclesButtonsPanel.poll(context)
611
612     def draw(self, context):
613         self.layout.template_preview(context.lamp)
614
615
616 class CyclesLamp_PT_lamp(CyclesButtonsPanel, Panel):
617     bl_label = "Lamp"
618     bl_context = "data"
619
620     @classmethod
621     def poll(cls, context):
622         return context.lamp and CyclesButtonsPanel.poll(context)
623
624     def draw(self, context):
625         layout = self.layout
626
627         lamp = context.lamp
628         clamp = lamp.cycles
629         cscene = context.scene.cycles
630
631         layout.prop(lamp, "type", expand=True)
632
633         split = layout.split()
634         col = split.column(align=True)
635
636         if lamp.type in {'POINT', 'SUN', 'SPOT'}:
637             col.prop(lamp, "shadow_soft_size", text="Size")
638         elif lamp.type == 'AREA':
639             col.prop(lamp, "shape", text="")
640             sub = col.column(align=True)
641
642             if lamp.shape == 'SQUARE':
643                 sub.prop(lamp, "size")
644             elif lamp.shape == 'RECTANGLE':
645                 sub.prop(lamp, "size", text="Size X")
646                 sub.prop(lamp, "size_y", text="Size Y")
647
648         if not cscene.progressive:
649             col.prop(clamp, "samples")
650
651         col = split.column()
652         col.prop(clamp, "cast_shadow")
653
654         layout.prop(clamp, "use_multiple_importance_sampling")
655
656         if lamp.type == 'HEMI':
657             layout.label(text="Not supported, interpreted as sun lamp")
658
659
660 class CyclesLamp_PT_nodes(CyclesButtonsPanel, Panel):
661     bl_label = "Nodes"
662     bl_context = "data"
663
664     @classmethod
665     def poll(cls, context):
666         return context.lamp and CyclesButtonsPanel.poll(context)
667
668     def draw(self, context):
669         layout = self.layout
670
671         lamp = context.lamp
672         if not panel_node_draw(layout, lamp, 'OUTPUT_LAMP', 'Surface'):
673             layout.prop(lamp, "color")
674
675
676 class CyclesLamp_PT_spot(CyclesButtonsPanel, Panel):
677     bl_label = "Spot Shape"
678     bl_context = "data"
679
680     @classmethod
681     def poll(cls, context):
682         lamp = context.lamp
683         return (lamp and lamp.type == 'SPOT') and CyclesButtonsPanel.poll(context)
684
685     def draw(self, context):
686         layout = self.layout
687
688         lamp = context.lamp
689
690         split = layout.split()
691
692         col = split.column()
693         sub = col.column()
694         sub.prop(lamp, "spot_size", text="Size")
695         sub.prop(lamp, "spot_blend", text="Blend", slider=True)
696
697         col = split.column()
698         col.prop(lamp, "show_cone")
699
700
701 class CyclesWorld_PT_preview(CyclesButtonsPanel, Panel):
702     bl_label = "Preview"
703     bl_context = "world"
704     bl_options = {'DEFAULT_CLOSED'}
705
706     @classmethod
707     def poll(cls, context):
708         return context.world and CyclesButtonsPanel.poll(context)
709
710     def draw(self, context):
711         self.layout.template_preview(context.world)
712
713
714 class CyclesWorld_PT_surface(CyclesButtonsPanel, Panel):
715     bl_label = "Surface"
716     bl_context = "world"
717
718     @classmethod
719     def poll(cls, context):
720         return context.world and CyclesButtonsPanel.poll(context)
721
722     def draw(self, context):
723         layout = self.layout
724
725         world = context.world
726
727         if not panel_node_draw(layout, world, 'OUTPUT_WORLD', 'Surface'):
728             layout.prop(world, "horizon_color", text="Color")
729
730
731 class CyclesWorld_PT_volume(CyclesButtonsPanel, Panel):
732     bl_label = "Volume"
733     bl_context = "world"
734     bl_options = {'DEFAULT_CLOSED'}
735
736     @classmethod
737     def poll(cls, context):
738         # world = context.world
739         # world and world.node_tree and CyclesButtonsPanel.poll(context)
740         return False
741
742     def draw(self, context):
743         layout = self.layout
744         layout.active = False
745
746         world = context.world
747         panel_node_draw(layout, world, 'OUTPUT_WORLD', 'Volume')
748
749
750 class CyclesWorld_PT_ambient_occlusion(CyclesButtonsPanel, Panel):
751     bl_label = "Ambient Occlusion"
752     bl_context = "world"
753
754     @classmethod
755     def poll(cls, context):
756         return context.world and CyclesButtonsPanel.poll(context)
757
758     def draw_header(self, context):
759         light = context.world.light_settings
760         self.layout.prop(light, "use_ambient_occlusion", text="")
761
762     def draw(self, context):
763         layout = self.layout
764         light = context.world.light_settings
765
766         layout.active = light.use_ambient_occlusion
767
768         row = layout.row()
769         row.prop(light, "ao_factor", text="Factor")
770         row.prop(light, "distance", text="Distance")
771
772 class CyclesWorld_PT_mist(CyclesButtonsPanel, Panel):
773     bl_label = "Mist Pass"
774     bl_context = "world"
775     bl_options = {'DEFAULT_CLOSED'}
776
777     @classmethod
778     def poll(cls, context):
779         if CyclesButtonsPanel.poll(context):
780             for rl in context.scene.render.layers:
781                 if rl.use_pass_mist:
782                     return True
783
784         return False
785
786     def draw(self, context):
787         layout = self.layout
788
789         world = context.world
790
791         split = layout.split(align=True)
792         split.prop(world.mist_settings, "start")
793         split.prop(world.mist_settings, "depth")
794
795         layout.prop(world.mist_settings, "falloff")
796
797
798 class CyclesWorld_PT_ray_visibility(CyclesButtonsPanel, Panel):
799     bl_label = "Ray Visibility"
800     bl_context = "world"
801     bl_options = {'DEFAULT_CLOSED'}
802
803     @classmethod
804     def poll(cls, context):
805         return CyclesButtonsPanel.poll(context) and context.world
806
807     def draw(self, context):
808         layout = self.layout
809
810         world = context.world
811         visibility = world.cycles_visibility
812
813         flow = layout.column_flow()
814
815         flow.prop(visibility, "camera")
816         flow.prop(visibility, "diffuse")
817         flow.prop(visibility, "glossy")
818         flow.prop(visibility, "transmission")
819
820
821 class CyclesWorld_PT_settings(CyclesButtonsPanel, Panel):
822     bl_label = "Settings"
823     bl_context = "world"
824     bl_options = {'DEFAULT_CLOSED'}
825
826     @classmethod
827     def poll(cls, context):
828         return context.world and CyclesButtonsPanel.poll(context)
829
830     def draw(self, context):
831         layout = self.layout
832
833         world = context.world
834         cworld = world.cycles
835         cscene = context.scene.cycles
836
837         col = layout.column()
838
839         col.prop(cworld, "sample_as_light")
840         sub = col.row(align=True)
841         sub.active = cworld.sample_as_light
842         sub.prop(cworld, "sample_map_resolution")
843         if not cscene.progressive:
844             sub.prop(cworld, "samples")
845
846
847 class CyclesMaterial_PT_preview(CyclesButtonsPanel, Panel):
848     bl_label = "Preview"
849     bl_context = "material"
850     bl_options = {'DEFAULT_CLOSED'}
851
852     @classmethod
853     def poll(cls, context):
854         return context.material and CyclesButtonsPanel.poll(context)
855
856     def draw(self, context):
857         self.layout.template_preview(context.material)
858
859
860 class CyclesMaterial_PT_surface(CyclesButtonsPanel, Panel):
861     bl_label = "Surface"
862     bl_context = "material"
863
864     @classmethod
865     def poll(cls, context):
866         return context.material and CyclesButtonsPanel.poll(context)
867
868     def draw(self, context):
869         layout = self.layout
870
871         mat = context.material
872         if not panel_node_draw(layout, mat, 'OUTPUT_MATERIAL', 'Surface'):
873             layout.prop(mat, "diffuse_color")
874
875
876 class CyclesMaterial_PT_volume(CyclesButtonsPanel, Panel):
877     bl_label = "Volume"
878     bl_context = "material"
879     bl_options = {'DEFAULT_CLOSED'}
880
881     @classmethod
882     def poll(cls, context):
883         # mat = context.material
884         # mat and mat.node_tree and CyclesButtonsPanel.poll(context)
885         return False
886
887     def draw(self, context):
888         layout = self.layout
889         layout.active = False
890
891         mat = context.material
892         cmat = mat.cycles
893
894         panel_node_draw(layout, mat, 'OUTPUT_MATERIAL', 'Volume')
895
896         layout.prop(cmat, "homogeneous_volume")
897
898
899 class CyclesMaterial_PT_displacement(CyclesButtonsPanel, Panel):
900     bl_label = "Displacement"
901     bl_context = "material"
902
903     @classmethod
904     def poll(cls, context):
905         mat = context.material
906         return mat and mat.node_tree and CyclesButtonsPanel.poll(context)
907
908     def draw(self, context):
909         layout = self.layout
910
911         mat = context.material
912         panel_node_draw(layout, mat, 'OUTPUT_MATERIAL', 'Displacement')
913
914
915 class CyclesMaterial_PT_settings(CyclesButtonsPanel, Panel):
916     bl_label = "Settings"
917     bl_context = "material"
918     bl_options = {'DEFAULT_CLOSED'}
919
920     @classmethod
921     def poll(cls, context):
922         return context.material and CyclesButtonsPanel.poll(context)
923
924     def draw(self, context):
925         layout = self.layout
926
927         mat = context.material
928         cmat = mat.cycles
929
930         split = layout.split()
931
932         col = split.column()
933         col.prop(mat, "diffuse_color", text="Viewport Color")
934
935         col = split.column(align=True)
936         col.label()
937         col.prop(mat, "pass_index")
938         
939         col = layout.column()
940         col.prop(cmat, "sample_as_light")
941         col.prop(cmat, "use_transparent_shadow")
942
943
944 class CyclesTexture_PT_context(CyclesButtonsPanel, Panel):
945     bl_label = ""
946     bl_context = "texture"
947     bl_options = {'HIDE_HEADER'}
948     COMPAT_ENGINES = {'CYCLES'}
949
950     def draw(self, context):
951         layout = self.layout
952
953         tex = context.texture
954         space = context.space_data
955         pin_id = space.pin_id
956         use_pin_id = space.use_pin_id
957         user = context.texture_user
958
959         space.use_limited_texture_context = False
960
961         if not (use_pin_id and isinstance(pin_id, bpy.types.Texture)):
962             pin_id = None
963
964         if not pin_id:
965             layout.template_texture_user()
966
967         if user or pin_id:
968             layout.separator()
969
970             split = layout.split(percentage=0.65)
971             col = split.column()
972
973             if pin_id:
974                 col.template_ID(space, "pin_id")
975             else:
976                 propname = context.texture_user_property.identifier
977                 col.template_ID(user, propname, new="texture.new")
978
979             if tex:
980                 split = layout.split(percentage=0.2)
981                 split.label(text="Type:")
982                 split.prop(tex, "type", text="")
983
984
985 class CyclesTexture_PT_node(CyclesButtonsPanel, Panel):
986     bl_label = "Node"
987     bl_context = "texture"
988
989     @classmethod
990     def poll(cls, context):
991         node = context.texture_node
992         return node and CyclesButtonsPanel.poll(context)
993
994     def draw(self, context):
995         layout = self.layout
996
997         node = context.texture_node
998         ntree = node.id_data
999         layout.template_node_view(ntree, node, None)
1000
1001
1002 class CyclesTexture_PT_mapping(CyclesButtonsPanel, Panel):
1003     bl_label = "Mapping"
1004     bl_context = "texture"
1005
1006     @classmethod
1007     def poll(cls, context):
1008         node = context.texture_node
1009         return node and CyclesButtonsPanel.poll(context)
1010
1011     def draw(self, context):
1012         layout = self.layout
1013
1014         node = context.texture_node
1015
1016         mapping = node.texture_mapping
1017
1018         row = layout.row()
1019
1020         row.column().prop(mapping, "translation")
1021         row.column().prop(mapping, "rotation")
1022         row.column().prop(mapping, "scale")
1023
1024         layout.label(text="Projection:")
1025
1026         row = layout.row()
1027         row.prop(mapping, "mapping_x", text="")
1028         row.prop(mapping, "mapping_y", text="")
1029         row.prop(mapping, "mapping_z", text="")
1030
1031
1032 class CyclesTexture_PT_colors(CyclesButtonsPanel, Panel):
1033     bl_label = "Color"
1034     bl_context = "texture"
1035     bl_options = {'DEFAULT_CLOSED'}
1036
1037     @classmethod
1038     def poll(cls, context):
1039         # node = context.texture_node
1040         return False
1041         #return node and CyclesButtonsPanel.poll(context)
1042
1043     def draw(self, context):
1044         layout = self.layout
1045
1046         node = context.texture_node
1047
1048         mapping = node.color_mapping
1049
1050         split = layout.split()
1051
1052         col = split.column()
1053         col.label(text="Blend:")
1054         col.prop(mapping, "blend_type", text="")
1055         col.prop(mapping, "blend_factor", text="Factor")
1056         col.prop(mapping, "blend_color", text="")
1057
1058         col = split.column()
1059         col.label(text="Adjust:")
1060         col.prop(mapping, "brightness")
1061         col.prop(mapping, "contrast")
1062         col.prop(mapping, "saturation")
1063
1064         layout.separator()
1065
1066         layout.prop(mapping, "use_color_ramp", text="Ramp")
1067         if mapping.use_color_ramp:
1068             layout.template_color_ramp(mapping, "color_ramp", expand=True)
1069
1070
1071 class CyclesParticle_PT_textures(CyclesButtonsPanel, Panel):
1072     bl_label = "Textures"
1073     bl_context = "particle"
1074     bl_options = {'DEFAULT_CLOSED'}
1075
1076     @classmethod
1077     def poll(cls, context):
1078         psys = context.particle_system
1079         return psys and CyclesButtonsPanel.poll(context)
1080
1081     def draw(self, context):
1082         layout = self.layout
1083
1084         psys = context.particle_system
1085         part = psys.settings
1086
1087         row = layout.row()
1088         row.template_list("TEXTURE_UL_texslots", "", part, "texture_slots", part, "active_texture_index", rows=2)
1089
1090         col = row.column(align=True)
1091         col.operator("texture.slot_move", text="", icon='TRIA_UP').type = 'UP'
1092         col.operator("texture.slot_move", text="", icon='TRIA_DOWN').type = 'DOWN'
1093         col.menu("TEXTURE_MT_specials", icon='DOWNARROW_HLT', text="")
1094
1095         if not part.active_texture:
1096             layout.template_ID(part, "active_texture", new="texture.new")
1097         else:
1098             slot = part.texture_slots[part.active_texture_index]
1099             layout.template_ID(slot, "texture", new="texture.new")
1100
1101
1102 class CyclesRender_PT_CurveRendering(CyclesButtonsPanel, Panel):
1103     bl_label = "Cycles Hair Rendering"
1104     bl_context = "particle"
1105
1106     @classmethod
1107     def poll(cls, context):
1108         scene = context.scene
1109         cscene = scene.cycles
1110         psys = context.particle_system
1111         experimental = (cscene.feature_set == 'EXPERIMENTAL')
1112         return CyclesButtonsPanel.poll(context) and experimental and psys
1113
1114     def draw_header(self, context):
1115         ccscene = context.scene.cycles_curves
1116         self.layout.prop(ccscene, "use_curves", text="")
1117
1118     def draw(self, context):
1119         layout = self.layout
1120
1121         scene = context.scene
1122         ccscene = scene.cycles_curves
1123
1124         layout.active = ccscene.use_curves
1125
1126         layout.prop(ccscene, "preset", text="Mode")
1127
1128         if ccscene.preset == 'CUSTOM':
1129             layout.prop(ccscene, "primitive", text="Primitive")
1130
1131             if ccscene.primitive == 'TRIANGLES':
1132                 layout.prop(ccscene, "triangle_method", text="Method")
1133                 if ccscene.triangle_method == 'TESSELLATED_TRIANGLES':
1134                     layout.prop(ccscene, "resolution", text="Resolution")
1135                 layout.prop(ccscene, "use_smooth", text="Smooth")
1136             elif ccscene.primitive == 'LINE_SEGMENTS':
1137                 layout.prop(ccscene, "use_backfacing", text="Check back-faces")
1138
1139                 row = layout.row()
1140                 row.prop(ccscene, "use_encasing", text="Exclude encasing")
1141                 sub = row.row()
1142                 sub.active = ccscene.use_encasing
1143                 sub.prop(ccscene, "encasing_ratio", text="Ratio for encasing")
1144
1145                 layout.prop(ccscene, "line_method", text="Method")
1146                 layout.prop(ccscene, "use_tangent_normal", text="Use tangent normal as default")
1147                 layout.prop(ccscene, "use_tangent_normal_geometry", text="Use tangent normal geometry")
1148                 layout.prop(ccscene, "use_tangent_normal_correction", text="Correct tangent normal for slope")
1149                 layout.prop(ccscene, "interpolation", text="Interpolation")
1150
1151                 row = layout.row()
1152                 row.prop(ccscene, "segments", text="Segments")
1153                 row.prop(ccscene, "normalmix", text="Ray Mix")
1154             elif ccscene.primitive in {'CURVE_SEGMENTS', 'CURVE_RIBBONS'}:
1155                 layout.prop(ccscene, "subdivisions", text="Curve subdivisions")
1156                 layout.prop(ccscene, "use_backfacing", text="Check back-faces")
1157
1158                 layout.prop(ccscene, "interpolation", text="Interpolation")
1159                 row = layout.row()
1160                 row.prop(ccscene, "segments", text="Segments")
1161
1162             row = layout.row()
1163             row.prop(ccscene, "use_parents", text="Include parents")
1164         
1165         row = layout.row()
1166         row.prop(ccscene, "minimum_width", text="Min Pixels")
1167         row.prop(ccscene, "maximum_width", text="Max Ext.")
1168
1169
1170 class CyclesParticle_PT_CurveSettings(CyclesButtonsPanel, Panel):
1171     bl_label = "Cycles Hair Settings"
1172     bl_context = "particle"
1173
1174     @classmethod
1175     def poll(cls, context):
1176         scene = context.scene
1177         cscene = scene.cycles
1178         ccscene = scene.cycles_curves
1179         use_curves = ccscene.use_curves and context.particle_system
1180         experimental = cscene.feature_set == 'EXPERIMENTAL'
1181         return CyclesButtonsPanel.poll(context) and experimental and use_curves
1182
1183     def draw(self, context):
1184         layout = self.layout
1185
1186         psys = context.particle_settings
1187         cpsys = psys.cycles
1188
1189         row = layout.row()
1190         row.prop(cpsys, "shape", text="Shape")
1191
1192         layout.label(text="Thickness:")
1193         row = layout.row()
1194         row.prop(cpsys, "root_width", text="Root")
1195         row.prop(cpsys, "tip_width", text="Tip")
1196         
1197         row = layout.row()
1198         row.prop(cpsys, "radius_scale", text="Scaling")
1199         row.prop(cpsys, "use_closetip", text="Close tip")
1200
1201
1202 class CyclesScene_PT_simplify(CyclesButtonsPanel, Panel):
1203     bl_label = "Simplify"
1204     bl_context = "scene"
1205     COMPAT_ENGINES = {'CYCLES'}
1206
1207     def draw_header(self, context):
1208         rd = context.scene.render
1209         self.layout.prop(rd, "use_simplify", text="")
1210
1211     def draw(self, context):
1212         layout = self.layout
1213
1214         rd = context.scene.render
1215
1216         layout.active = rd.use_simplify
1217
1218         row = layout.row()
1219         row.prop(rd, "simplify_subdivision", text="Subdivision")
1220         row.prop(rd, "simplify_child_particles", text="Child Particles")
1221
1222
1223 def draw_device(self, context):
1224     scene = context.scene
1225     layout = self.layout
1226
1227     if scene.render.engine == 'CYCLES':
1228         from . import engine
1229         cscene = scene.cycles
1230
1231         layout.prop(cscene, "feature_set")
1232
1233         device_type = context.user_preferences.system.compute_device_type
1234         if device_type == 'CUDA':
1235             layout.prop(cscene, "device")
1236         elif device_type == 'OPENCL':
1237             layout.prop(cscene, "device")
1238
1239         if engine.with_osl() and (cscene.device == 'CPU' or device_type == 'NONE'):
1240             layout.prop(cscene, "shading_system")
1241
1242
1243 def draw_pause(self, context):
1244     layout = self.layout
1245     scene = context.scene
1246
1247     if scene.render.engine == "CYCLES":
1248         view = context.space_data
1249
1250         if view.viewport_shade == 'RENDERED':
1251             cscene = scene.cycles
1252             layername = scene.render.layers.active.name
1253             layout.prop(cscene, "preview_pause", icon="PAUSE", text="")
1254             layout.prop(cscene, "preview_active_layer", icon="RENDERLAYERS", text=layername)
1255
1256
1257 def get_panels():
1258     types = bpy.types
1259     return (
1260         types.RENDER_PT_render,
1261         types.RENDER_PT_output,
1262         types.RENDER_PT_encoding,
1263         types.RENDER_PT_dimensions,
1264         types.RENDER_PT_stamp,
1265         types.SCENE_PT_scene,
1266         types.SCENE_PT_color_management,
1267         types.SCENE_PT_custom_props,
1268         types.SCENE_PT_audio,
1269         types.SCENE_PT_unit,
1270         types.SCENE_PT_keying_sets,
1271         types.SCENE_PT_keying_set_paths,
1272         types.SCENE_PT_physics,
1273         types.WORLD_PT_context_world,
1274         types.WORLD_PT_custom_props,
1275         types.DATA_PT_context_mesh,
1276         types.DATA_PT_context_camera,
1277         types.DATA_PT_context_lamp,
1278         types.DATA_PT_context_speaker,
1279         types.DATA_PT_texture_space,
1280         types.DATA_PT_curve_texture_space,
1281         types.DATA_PT_mball_texture_space,
1282         types.DATA_PT_vertex_groups,
1283         types.DATA_PT_shape_keys,
1284         types.DATA_PT_uv_texture,
1285         types.DATA_PT_vertex_colors,
1286         types.DATA_PT_camera,
1287         types.DATA_PT_camera_display,
1288         types.DATA_PT_lens,
1289         types.DATA_PT_speaker,
1290         types.DATA_PT_distance,
1291         types.DATA_PT_cone,
1292         types.DATA_PT_customdata,
1293         types.DATA_PT_custom_props_mesh,
1294         types.DATA_PT_custom_props_camera,
1295         types.DATA_PT_custom_props_lamp,
1296         types.DATA_PT_custom_props_speaker,
1297         types.DATA_PT_custom_props_arm,
1298         types.DATA_PT_custom_props_curve,
1299         types.DATA_PT_custom_props_lattice,
1300         types.DATA_PT_custom_props_metaball,
1301         types.TEXTURE_PT_custom_props,
1302         types.TEXTURE_PT_clouds,
1303         types.TEXTURE_PT_wood,
1304         types.TEXTURE_PT_marble,
1305         types.TEXTURE_PT_magic,
1306         types.TEXTURE_PT_blend,
1307         types.TEXTURE_PT_stucci,
1308         types.TEXTURE_PT_image,
1309         types.TEXTURE_PT_image_sampling,
1310         types.TEXTURE_PT_image_mapping,
1311         types.TEXTURE_PT_musgrave,
1312         types.TEXTURE_PT_voronoi,
1313         types.TEXTURE_PT_distortednoise,
1314         types.TEXTURE_PT_voxeldata,
1315         types.TEXTURE_PT_pointdensity,
1316         types.TEXTURE_PT_pointdensity_turbulence,
1317         types.TEXTURE_PT_mapping,
1318         types.TEXTURE_PT_influence,
1319         types.TEXTURE_PT_colors,
1320         types.PARTICLE_PT_context_particles,
1321         types.PARTICLE_PT_custom_props,
1322         types.PARTICLE_PT_emission,
1323         types.PARTICLE_PT_hair_dynamics,
1324         types.PARTICLE_PT_cache,
1325         types.PARTICLE_PT_velocity,
1326         types.PARTICLE_PT_rotation,
1327         types.PARTICLE_PT_physics,
1328         types.SCENE_PT_rigid_body_world,
1329         types.SCENE_PT_rigid_body_cache,
1330         types.SCENE_PT_rigid_body_field_weights,
1331         types.PARTICLE_PT_boidbrain,
1332         types.PARTICLE_PT_render,
1333         types.PARTICLE_PT_draw,
1334         types.PARTICLE_PT_children,
1335         types.PARTICLE_PT_field_weights,
1336         types.PARTICLE_PT_force_fields,
1337         types.PARTICLE_PT_vertexgroups,
1338         types.MATERIAL_PT_custom_props,
1339         types.BONE_PT_custom_props,
1340         types.OBJECT_PT_custom_props,
1341         )
1342
1343
1344 def register():
1345     bpy.types.RENDER_PT_render.append(draw_device)
1346     bpy.types.VIEW3D_HT_header.append(draw_pause)
1347
1348     for panel in get_panels():
1349         panel.COMPAT_ENGINES.add('CYCLES')
1350
1351
1352 def unregister():
1353     bpy.types.RENDER_PT_render.remove(draw_device)
1354     bpy.types.VIEW3D_HT_header.remove(draw_pause)
1355
1356     for panel in get_panels():
1357         panel.COMPAT_ENGINES.remove('CYCLES')