Merged revision(s) 57768-57827 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
773 class CyclesWorld_PT_mist(CyclesButtonsPanel, Panel):
774     bl_label = "Mist Pass"
775     bl_context = "world"
776     bl_options = {'DEFAULT_CLOSED'}
777
778     @classmethod
779     def poll(cls, context):
780         if CyclesButtonsPanel.poll(context):
781             for rl in context.scene.render.layers:
782                 if rl.use_pass_mist:
783                     return True
784
785         return False
786
787     def draw(self, context):
788         layout = self.layout
789
790         world = context.world
791
792         split = layout.split(align=True)
793         split.prop(world.mist_settings, "start")
794         split.prop(world.mist_settings, "depth")
795
796         layout.prop(world.mist_settings, "falloff")
797
798
799 class CyclesWorld_PT_ray_visibility(CyclesButtonsPanel, Panel):
800     bl_label = "Ray Visibility"
801     bl_context = "world"
802     bl_options = {'DEFAULT_CLOSED'}
803
804     @classmethod
805     def poll(cls, context):
806         return CyclesButtonsPanel.poll(context) and context.world
807
808     def draw(self, context):
809         layout = self.layout
810
811         world = context.world
812         visibility = world.cycles_visibility
813
814         flow = layout.column_flow()
815
816         flow.prop(visibility, "camera")
817         flow.prop(visibility, "diffuse")
818         flow.prop(visibility, "glossy")
819         flow.prop(visibility, "transmission")
820
821
822 class CyclesWorld_PT_settings(CyclesButtonsPanel, Panel):
823     bl_label = "Settings"
824     bl_context = "world"
825     bl_options = {'DEFAULT_CLOSED'}
826
827     @classmethod
828     def poll(cls, context):
829         return context.world and CyclesButtonsPanel.poll(context)
830
831     def draw(self, context):
832         layout = self.layout
833
834         world = context.world
835         cworld = world.cycles
836         cscene = context.scene.cycles
837
838         col = layout.column()
839
840         col.prop(cworld, "sample_as_light")
841         sub = col.row(align=True)
842         sub.active = cworld.sample_as_light
843         sub.prop(cworld, "sample_map_resolution")
844         if not cscene.progressive:
845             sub.prop(cworld, "samples")
846
847
848 class CyclesMaterial_PT_preview(CyclesButtonsPanel, Panel):
849     bl_label = "Preview"
850     bl_context = "material"
851     bl_options = {'DEFAULT_CLOSED'}
852
853     @classmethod
854     def poll(cls, context):
855         return context.material and CyclesButtonsPanel.poll(context)
856
857     def draw(self, context):
858         self.layout.template_preview(context.material)
859
860
861 class CyclesMaterial_PT_surface(CyclesButtonsPanel, Panel):
862     bl_label = "Surface"
863     bl_context = "material"
864
865     @classmethod
866     def poll(cls, context):
867         return context.material and CyclesButtonsPanel.poll(context)
868
869     def draw(self, context):
870         layout = self.layout
871
872         mat = context.material
873         if not panel_node_draw(layout, mat, 'OUTPUT_MATERIAL', 'Surface'):
874             layout.prop(mat, "diffuse_color")
875
876
877 class CyclesMaterial_PT_volume(CyclesButtonsPanel, Panel):
878     bl_label = "Volume"
879     bl_context = "material"
880     bl_options = {'DEFAULT_CLOSED'}
881
882     @classmethod
883     def poll(cls, context):
884         # mat = context.material
885         # mat and mat.node_tree and CyclesButtonsPanel.poll(context)
886         return False
887
888     def draw(self, context):
889         layout = self.layout
890         layout.active = False
891
892         mat = context.material
893         cmat = mat.cycles
894
895         panel_node_draw(layout, mat, 'OUTPUT_MATERIAL', 'Volume')
896
897         layout.prop(cmat, "homogeneous_volume")
898
899
900 class CyclesMaterial_PT_displacement(CyclesButtonsPanel, Panel):
901     bl_label = "Displacement"
902     bl_context = "material"
903
904     @classmethod
905     def poll(cls, context):
906         mat = context.material
907         return mat and mat.node_tree and CyclesButtonsPanel.poll(context)
908
909     def draw(self, context):
910         layout = self.layout
911
912         mat = context.material
913         panel_node_draw(layout, mat, 'OUTPUT_MATERIAL', 'Displacement')
914
915
916 class CyclesMaterial_PT_settings(CyclesButtonsPanel, Panel):
917     bl_label = "Settings"
918     bl_context = "material"
919     bl_options = {'DEFAULT_CLOSED'}
920
921     @classmethod
922     def poll(cls, context):
923         return context.material and CyclesButtonsPanel.poll(context)
924
925     def draw(self, context):
926         layout = self.layout
927
928         mat = context.material
929         cmat = mat.cycles
930
931         split = layout.split()
932
933         col = split.column()
934         col.prop(mat, "diffuse_color", text="Viewport Color")
935
936         col = split.column(align=True)
937         col.label()
938         col.prop(mat, "pass_index")
939
940         col = layout.column()
941         col.prop(cmat, "sample_as_light")
942         col.prop(cmat, "use_transparent_shadow")
943
944
945 class CyclesTexture_PT_context(CyclesButtonsPanel, Panel):
946     bl_label = ""
947     bl_context = "texture"
948     bl_options = {'HIDE_HEADER'}
949     COMPAT_ENGINES = {'CYCLES'}
950
951     def draw(self, context):
952         layout = self.layout
953
954         tex = context.texture
955         space = context.space_data
956         pin_id = space.pin_id
957         use_pin_id = space.use_pin_id
958         user = context.texture_user
959
960         space.use_limited_texture_context = False
961
962         if not (use_pin_id and isinstance(pin_id, bpy.types.Texture)):
963             pin_id = None
964
965         if not pin_id:
966             layout.template_texture_user()
967
968         if user or pin_id:
969             layout.separator()
970
971             split = layout.split(percentage=0.65)
972             col = split.column()
973
974             if pin_id:
975                 col.template_ID(space, "pin_id")
976             else:
977                 propname = context.texture_user_property.identifier
978                 col.template_ID(user, propname, new="texture.new")
979
980             if tex:
981                 split = layout.split(percentage=0.2)
982                 split.label(text="Type:")
983                 split.prop(tex, "type", text="")
984
985
986 class CyclesTexture_PT_node(CyclesButtonsPanel, Panel):
987     bl_label = "Node"
988     bl_context = "texture"
989
990     @classmethod
991     def poll(cls, context):
992         node = context.texture_node
993         return node and CyclesButtonsPanel.poll(context)
994
995     def draw(self, context):
996         layout = self.layout
997
998         node = context.texture_node
999         ntree = node.id_data
1000         layout.template_node_view(ntree, node, None)
1001
1002
1003 class CyclesTexture_PT_mapping(CyclesButtonsPanel, Panel):
1004     bl_label = "Mapping"
1005     bl_context = "texture"
1006
1007     @classmethod
1008     def poll(cls, context):
1009         node = context.texture_node
1010         return node and CyclesButtonsPanel.poll(context)
1011
1012     def draw(self, context):
1013         layout = self.layout
1014
1015         node = context.texture_node
1016
1017         mapping = node.texture_mapping
1018
1019         row = layout.row()
1020
1021         row.column().prop(mapping, "translation")
1022         row.column().prop(mapping, "rotation")
1023         row.column().prop(mapping, "scale")
1024
1025         layout.label(text="Projection:")
1026
1027         row = layout.row()
1028         row.prop(mapping, "mapping_x", text="")
1029         row.prop(mapping, "mapping_y", text="")
1030         row.prop(mapping, "mapping_z", text="")
1031
1032
1033 class CyclesTexture_PT_colors(CyclesButtonsPanel, Panel):
1034     bl_label = "Color"
1035     bl_context = "texture"
1036     bl_options = {'DEFAULT_CLOSED'}
1037
1038     @classmethod
1039     def poll(cls, context):
1040         # node = context.texture_node
1041         return False
1042         #return node and CyclesButtonsPanel.poll(context)
1043
1044     def draw(self, context):
1045         layout = self.layout
1046
1047         node = context.texture_node
1048
1049         mapping = node.color_mapping
1050
1051         split = layout.split()
1052
1053         col = split.column()
1054         col.label(text="Blend:")
1055         col.prop(mapping, "blend_type", text="")
1056         col.prop(mapping, "blend_factor", text="Factor")
1057         col.prop(mapping, "blend_color", text="")
1058
1059         col = split.column()
1060         col.label(text="Adjust:")
1061         col.prop(mapping, "brightness")
1062         col.prop(mapping, "contrast")
1063         col.prop(mapping, "saturation")
1064
1065         layout.separator()
1066
1067         layout.prop(mapping, "use_color_ramp", text="Ramp")
1068         if mapping.use_color_ramp:
1069             layout.template_color_ramp(mapping, "color_ramp", expand=True)
1070
1071
1072 class CyclesParticle_PT_textures(CyclesButtonsPanel, Panel):
1073     bl_label = "Textures"
1074     bl_context = "particle"
1075     bl_options = {'DEFAULT_CLOSED'}
1076
1077     @classmethod
1078     def poll(cls, context):
1079         psys = context.particle_system
1080         return psys and CyclesButtonsPanel.poll(context)
1081
1082     def draw(self, context):
1083         layout = self.layout
1084
1085         psys = context.particle_system
1086         part = psys.settings
1087
1088         row = layout.row()
1089         row.template_list("TEXTURE_UL_texslots", "", part, "texture_slots", part, "active_texture_index", rows=2)
1090
1091         col = row.column(align=True)
1092         col.operator("texture.slot_move", text="", icon='TRIA_UP').type = 'UP'
1093         col.operator("texture.slot_move", text="", icon='TRIA_DOWN').type = 'DOWN'
1094         col.menu("TEXTURE_MT_specials", icon='DOWNARROW_HLT', text="")
1095
1096         if not part.active_texture:
1097             layout.template_ID(part, "active_texture", new="texture.new")
1098         else:
1099             slot = part.texture_slots[part.active_texture_index]
1100             layout.template_ID(slot, "texture", new="texture.new")
1101
1102
1103 class CyclesRender_PT_CurveRendering(CyclesButtonsPanel, Panel):
1104     bl_label = "Cycles Hair Rendering"
1105     bl_context = "particle"
1106
1107     @classmethod
1108     def poll(cls, context):
1109         scene = context.scene
1110         cscene = scene.cycles
1111         psys = context.particle_system
1112         experimental = (cscene.feature_set == 'EXPERIMENTAL')
1113         return CyclesButtonsPanel.poll(context) and experimental and psys
1114
1115     def draw_header(self, context):
1116         ccscene = context.scene.cycles_curves
1117         self.layout.prop(ccscene, "use_curves", text="")
1118
1119     def draw(self, context):
1120         layout = self.layout
1121
1122         scene = context.scene
1123         ccscene = scene.cycles_curves
1124
1125         layout.active = ccscene.use_curves
1126
1127         layout.prop(ccscene, "preset", text="Mode")
1128
1129         if ccscene.preset == 'CUSTOM':
1130             layout.prop(ccscene, "primitive", text="Primitive")
1131
1132             if ccscene.primitive == 'TRIANGLES':
1133                 layout.prop(ccscene, "triangle_method", text="Method")
1134                 if ccscene.triangle_method == 'TESSELLATED_TRIANGLES':
1135                     layout.prop(ccscene, "resolution", text="Resolution")
1136                 layout.prop(ccscene, "use_smooth", text="Smooth")
1137             elif ccscene.primitive == 'LINE_SEGMENTS':
1138                 layout.prop(ccscene, "use_backfacing", text="Check back-faces")
1139
1140                 row = layout.row()
1141                 row.prop(ccscene, "use_encasing", text="Exclude encasing")
1142                 sub = row.row()
1143                 sub.active = ccscene.use_encasing
1144                 sub.prop(ccscene, "encasing_ratio", text="Ratio for encasing")
1145
1146                 layout.prop(ccscene, "line_method", text="Method")
1147                 layout.prop(ccscene, "use_tangent_normal", text="Use tangent normal as default")
1148                 layout.prop(ccscene, "use_tangent_normal_geometry", text="Use tangent normal geometry")
1149                 layout.prop(ccscene, "use_tangent_normal_correction", text="Correct tangent normal for slope")
1150                 layout.prop(ccscene, "interpolation", text="Interpolation")
1151
1152                 row = layout.row()
1153                 row.prop(ccscene, "segments", text="Segments")
1154                 row.prop(ccscene, "normalmix", text="Ray Mix")
1155             elif ccscene.primitive in {'CURVE_SEGMENTS', 'CURVE_RIBBONS'}:
1156                 layout.prop(ccscene, "subdivisions", text="Curve subdivisions")
1157                 layout.prop(ccscene, "use_backfacing", text="Check back-faces")
1158
1159                 layout.prop(ccscene, "interpolation", text="Interpolation")
1160                 row = layout.row()
1161                 row.prop(ccscene, "segments", text="Segments")
1162
1163             row = layout.row()
1164             row.prop(ccscene, "use_parents", text="Include parents")
1165
1166         row = layout.row()
1167         row.prop(ccscene, "minimum_width", text="Min Pixels")
1168         row.prop(ccscene, "maximum_width", text="Max Ext.")
1169
1170
1171 class CyclesParticle_PT_CurveSettings(CyclesButtonsPanel, Panel):
1172     bl_label = "Cycles Hair Settings"
1173     bl_context = "particle"
1174
1175     @classmethod
1176     def poll(cls, context):
1177         scene = context.scene
1178         cscene = scene.cycles
1179         ccscene = scene.cycles_curves
1180         use_curves = ccscene.use_curves and context.particle_system
1181         experimental = cscene.feature_set == 'EXPERIMENTAL'
1182         return CyclesButtonsPanel.poll(context) and experimental and use_curves
1183
1184     def draw(self, context):
1185         layout = self.layout
1186
1187         psys = context.particle_settings
1188         cpsys = psys.cycles
1189
1190         row = layout.row()
1191         row.prop(cpsys, "shape", text="Shape")
1192
1193         layout.label(text="Thickness:")
1194         row = layout.row()
1195         row.prop(cpsys, "root_width", text="Root")
1196         row.prop(cpsys, "tip_width", text="Tip")
1197
1198         row = layout.row()
1199         row.prop(cpsys, "radius_scale", text="Scaling")
1200         row.prop(cpsys, "use_closetip", text="Close tip")
1201
1202
1203 class CyclesScene_PT_simplify(CyclesButtonsPanel, Panel):
1204     bl_label = "Simplify"
1205     bl_context = "scene"
1206     COMPAT_ENGINES = {'CYCLES'}
1207
1208     def draw_header(self, context):
1209         rd = context.scene.render
1210         self.layout.prop(rd, "use_simplify", text="")
1211
1212     def draw(self, context):
1213         layout = self.layout
1214
1215         rd = context.scene.render
1216
1217         layout.active = rd.use_simplify
1218
1219         row = layout.row()
1220         row.prop(rd, "simplify_subdivision", text="Subdivision")
1221         row.prop(rd, "simplify_child_particles", text="Child Particles")
1222
1223
1224 def draw_device(self, context):
1225     scene = context.scene
1226     layout = self.layout
1227
1228     if scene.render.engine == 'CYCLES':
1229         from . import engine
1230         cscene = scene.cycles
1231
1232         layout.prop(cscene, "feature_set")
1233
1234         device_type = context.user_preferences.system.compute_device_type
1235         if device_type == 'CUDA':
1236             layout.prop(cscene, "device")
1237         elif device_type == 'OPENCL':
1238             layout.prop(cscene, "device")
1239
1240         if engine.with_osl() and (cscene.device == 'CPU' or device_type == 'NONE'):
1241             layout.prop(cscene, "shading_system")
1242
1243
1244 def draw_pause(self, context):
1245     layout = self.layout
1246     scene = context.scene
1247
1248     if scene.render.engine == "CYCLES":
1249         view = context.space_data
1250
1251         if view.viewport_shade == 'RENDERED':
1252             cscene = scene.cycles
1253             layername = scene.render.layers.active.name
1254             layout.prop(cscene, "preview_pause", icon="PAUSE", text="")
1255             layout.prop(cscene, "preview_active_layer", icon="RENDERLAYERS", text=layername)
1256
1257
1258 def get_panels():
1259     types = bpy.types
1260     return (
1261         types.RENDER_PT_render,
1262         types.RENDER_PT_output,
1263         types.RENDER_PT_encoding,
1264         types.RENDER_PT_dimensions,
1265         types.RENDER_PT_stamp,
1266         types.SCENE_PT_scene,
1267         types.SCENE_PT_color_management,
1268         types.SCENE_PT_custom_props,
1269         types.SCENE_PT_audio,
1270         types.SCENE_PT_unit,
1271         types.SCENE_PT_keying_sets,
1272         types.SCENE_PT_keying_set_paths,
1273         types.SCENE_PT_physics,
1274         types.WORLD_PT_context_world,
1275         types.WORLD_PT_custom_props,
1276         types.DATA_PT_context_mesh,
1277         types.DATA_PT_context_camera,
1278         types.DATA_PT_context_lamp,
1279         types.DATA_PT_context_speaker,
1280         types.DATA_PT_texture_space,
1281         types.DATA_PT_curve_texture_space,
1282         types.DATA_PT_mball_texture_space,
1283         types.DATA_PT_vertex_groups,
1284         types.DATA_PT_shape_keys,
1285         types.DATA_PT_uv_texture,
1286         types.DATA_PT_vertex_colors,
1287         types.DATA_PT_camera,
1288         types.DATA_PT_camera_display,
1289         types.DATA_PT_lens,
1290         types.DATA_PT_speaker,
1291         types.DATA_PT_distance,
1292         types.DATA_PT_cone,
1293         types.DATA_PT_customdata,
1294         types.DATA_PT_custom_props_mesh,
1295         types.DATA_PT_custom_props_camera,
1296         types.DATA_PT_custom_props_lamp,
1297         types.DATA_PT_custom_props_speaker,
1298         types.DATA_PT_custom_props_arm,
1299         types.DATA_PT_custom_props_curve,
1300         types.DATA_PT_custom_props_lattice,
1301         types.DATA_PT_custom_props_metaball,
1302         types.TEXTURE_PT_custom_props,
1303         types.TEXTURE_PT_clouds,
1304         types.TEXTURE_PT_wood,
1305         types.TEXTURE_PT_marble,
1306         types.TEXTURE_PT_magic,
1307         types.TEXTURE_PT_blend,
1308         types.TEXTURE_PT_stucci,
1309         types.TEXTURE_PT_image,
1310         types.TEXTURE_PT_image_sampling,
1311         types.TEXTURE_PT_image_mapping,
1312         types.TEXTURE_PT_musgrave,
1313         types.TEXTURE_PT_voronoi,
1314         types.TEXTURE_PT_distortednoise,
1315         types.TEXTURE_PT_voxeldata,
1316         types.TEXTURE_PT_pointdensity,
1317         types.TEXTURE_PT_pointdensity_turbulence,
1318         types.TEXTURE_PT_mapping,
1319         types.TEXTURE_PT_influence,
1320         types.TEXTURE_PT_colors,
1321         types.PARTICLE_PT_context_particles,
1322         types.PARTICLE_PT_custom_props,
1323         types.PARTICLE_PT_emission,
1324         types.PARTICLE_PT_hair_dynamics,
1325         types.PARTICLE_PT_cache,
1326         types.PARTICLE_PT_velocity,
1327         types.PARTICLE_PT_rotation,
1328         types.PARTICLE_PT_physics,
1329         types.SCENE_PT_rigid_body_world,
1330         types.SCENE_PT_rigid_body_cache,
1331         types.SCENE_PT_rigid_body_field_weights,
1332         types.PARTICLE_PT_boidbrain,
1333         types.PARTICLE_PT_render,
1334         types.PARTICLE_PT_draw,
1335         types.PARTICLE_PT_children,
1336         types.PARTICLE_PT_field_weights,
1337         types.PARTICLE_PT_force_fields,
1338         types.PARTICLE_PT_vertexgroups,
1339         types.MATERIAL_PT_custom_props,
1340         types.BONE_PT_custom_props,
1341         types.OBJECT_PT_custom_props,
1342         )
1343
1344
1345 def register():
1346     bpy.types.RENDER_PT_render.append(draw_device)
1347     bpy.types.VIEW3D_HT_header.append(draw_pause)
1348
1349     for panel in get_panels():
1350         panel.COMPAT_ENGINES.add('CYCLES')
1351
1352
1353 def unregister():
1354     bpy.types.RENDER_PT_render.remove(draw_device)
1355     bpy.types.VIEW3D_HT_header.remove(draw_pause)
1356
1357     for panel in get_panels():
1358         panel.COMPAT_ENGINES.remove('CYCLES')