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