Merging r45801 through r45809 from trunk into soc-2011-tomato
[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
24
25 from . import enums, engine
26
27
28 class CYCLES_MT_integrator_presets(Menu):
29     bl_label = "Integrator Presets"
30     preset_subdir = "cycles/integrator"
31     preset_operator = "script.execute_preset"
32     COMPAT_ENGINES = {'CYCLES'}
33     draw = Menu.draw_preset
34
35
36 class CyclesButtonsPanel():
37     bl_space_type = "PROPERTIES"
38     bl_region_type = "WINDOW"
39     bl_context = "render"
40
41     @classmethod
42     def poll(cls, context):
43         rd = context.scene.render
44         return rd.engine == 'CYCLES'
45
46
47 class CyclesRender_PT_integrator(CyclesButtonsPanel, Panel):
48     bl_label = "Integrator"
49     bl_options = {'DEFAULT_CLOSED'}
50
51     def draw(self, context):
52         layout = self.layout
53
54         scene = context.scene
55         cscene = scene.cycles
56
57         row = layout.row(align=True)
58         row.menu("CYCLES_MT_integrator_presets", text=bpy.types.CYCLES_MT_integrator_presets.bl_label)
59         row.operator("render.cycles_integrator_preset_add", text="", icon="ZOOMIN")
60         row.operator("render.cycles_integrator_preset_add", text="", icon="ZOOMOUT").remove_active = True
61
62         split = layout.split()
63
64         col = split.column()
65         sub = col.column(align=True)
66         sub.label(text="Samples:")
67         sub.prop(cscene, "samples", text="Render")
68         sub.prop(cscene, "preview_samples", text="Preview")
69         sub.prop(cscene, "seed")
70         sub.prop(cscene, "sample_clamp")
71
72         sub = col.column(align=True)
73         sub.label("Transparency:")
74         sub.prop(cscene, "transparent_max_bounces", text="Max")
75         sub.prop(cscene, "transparent_min_bounces", text="Min")
76         sub.prop(cscene, "use_transparent_shadows", text="Shadows")
77
78         col = split.column()
79
80         sub = col.column(align=True)
81         sub.label(text="Bounces:")
82         sub.prop(cscene, "max_bounces", text="Max")
83         sub.prop(cscene, "min_bounces", text="Min")
84
85         sub = col.column(align=True)
86         sub.label(text="Light Paths:")
87         sub.prop(cscene, "diffuse_bounces", text="Diffuse")
88         sub.prop(cscene, "glossy_bounces", text="Glossy")
89         sub.prop(cscene, "transmission_bounces", text="Transmission")
90
91         col.separator()
92
93         col.prop(cscene, "no_caustics")
94         col.prop(cscene, "blur_glossy")
95
96
97 class CyclesRender_PT_film(CyclesButtonsPanel, Panel):
98     bl_label = "Film"
99
100     def draw(self, context):
101         layout = self.layout
102
103         scene = context.scene
104         cscene = scene.cycles
105
106         split = layout.split()
107
108         col = split.column()
109         col.prop(cscene, "film_exposure")
110         col.prop(cscene, "film_transparent")
111
112         col = split.column()
113         sub = col.column(align=True)
114         sub.prop(cscene, "filter_type", text="")
115         if cscene.filter_type != 'BOX':
116             sub.prop(cscene, "filter_width", text="Width")
117
118
119 class CyclesRender_PT_performance(CyclesButtonsPanel, Panel):
120     bl_label = "Performance"
121     bl_options = {'DEFAULT_CLOSED'}
122
123     def draw(self, context):
124         layout = self.layout
125
126         scene = context.scene
127         rd = scene.render
128         cscene = scene.cycles
129
130         split = layout.split()
131
132         col = split.column(align=True)
133
134         col.label(text="Threads:")
135         col.row().prop(rd, "threads_mode", expand=True)
136         sub = col.column()
137         sub.enabled = rd.threads_mode == 'FIXED'
138         sub.prop(rd, "threads")
139
140         sub = col.column(align=True)
141         sub.label(text="Tiles:")
142         sub.prop(cscene, "debug_tile_size")
143         sub.prop(cscene, "debug_min_size")
144
145         col = split.column()
146
147         sub = col.column(align=True)
148         sub.label(text="Acceleration structure:")
149         sub.prop(cscene, "debug_bvh_type", text="")
150         sub.prop(cscene, "debug_use_spatial_splits")
151         sub.prop(cscene, "use_cache")
152
153
154 class CyclesRender_PT_layers(CyclesButtonsPanel, Panel):
155     bl_label = "Layers"
156     bl_options = {'DEFAULT_CLOSED'}
157     COMPAT_ENGINES = {'BLENDER_RENDER'}
158
159     def draw(self, context):
160         layout = self.layout
161
162         scene = context.scene
163         rd = scene.render
164
165         row = layout.row()
166         row.template_list(rd, "layers", rd.layers, "active_index", rows=2)
167
168         col = row.column(align=True)
169         col.operator("scene.render_layer_add", icon='ZOOMIN', text="")
170         col.operator("scene.render_layer_remove", icon='ZOOMOUT', text="")
171
172         row = layout.row()
173         rl = rd.layers.active
174         row.prop(rl, "name")
175         row.prop(rd, "use_single_layer", text="", icon_only=True)
176
177         split = layout.split()
178
179         col = split.column()
180         col.prop(scene, "layers", text="Scene")
181         col.prop(rl, "layers_exclude", text="Exclude")
182
183         col = split.column()
184         col.prop(rl, "layers", text="Layer")
185         col.label(text="Mask Layers:")
186         col.prop(rl, "layers_zmask", text="")
187
188         split = layout.split()
189
190         col = split.column()
191         col.label(text="Material:")
192         col.prop(rl, "material_override", text="")
193
194         col = split.column()
195         col.prop(rl, "samples")
196         col.prop(rl, "use_sky", "Use Environment")
197
198         split = layout.split()
199
200         col = split.column()
201         col.label(text="Passes:")
202         col.prop(rl, "use_pass_combined")
203         col.prop(rl, "use_pass_z")
204         col.prop(rl, "use_pass_normal")
205         col.prop(rl, "use_pass_object_index")
206         col.prop(rl, "use_pass_material_index")
207         col.prop(rl, "use_pass_emit")
208         col.prop(rl, "use_pass_environment")
209         col.prop(rl, "use_pass_ambient_occlusion")
210         col.prop(rl, "use_pass_shadow")
211
212         col = split.column()
213         col.label()
214         col.label(text="Diffuse:")
215         row = col.row(align=True)
216         row.prop(rl, "use_pass_diffuse_direct", text="Direct", toggle=True)
217         row.prop(rl, "use_pass_diffuse_indirect", text="Indirect", toggle=True)
218         row.prop(rl, "use_pass_diffuse_color", text="Color", toggle=True)
219         col.label(text="Glossy:")
220         row = col.row(align=True)
221         row.prop(rl, "use_pass_glossy_direct", text="Direct", toggle=True)
222         row.prop(rl, "use_pass_glossy_indirect", text="Indirect", toggle=True)
223         row.prop(rl, "use_pass_glossy_color", text="Color", toggle=True)
224         col.label(text="Transmission:")
225         row = col.row(align=True)
226         row.prop(rl, "use_pass_transmission_direct", text="Direct", toggle=True)
227         row.prop(rl, "use_pass_transmission_indirect", text="Indirect", toggle=True)
228         row.prop(rl, "use_pass_transmission_color", text="Color", toggle=True)
229
230
231 class Cycles_PT_post_processing(CyclesButtonsPanel, Panel):
232     bl_label = "Post Processing"
233     bl_options = {'DEFAULT_CLOSED'}
234
235     def draw(self, context):
236         layout = self.layout
237
238         rd = context.scene.render
239
240         split = layout.split()
241
242         col = split.column()
243         col.prop(rd, "use_compositing")
244         col.prop(rd, "use_sequencer")
245
246         col = split.column()
247         col.prop(rd, "dither_intensity", text="Dither", slider=True)
248
249
250 class CyclesCamera_PT_dof(CyclesButtonsPanel, Panel):
251     bl_label = "Depth of Field"
252     bl_context = "data"
253
254     @classmethod
255     def poll(cls, context):
256         return context.camera and CyclesButtonsPanel.poll(context)
257
258     def draw(self, context):
259         layout = self.layout
260
261         cam = context.camera
262         ccam = cam.cycles
263
264         split = layout.split()
265
266         col = split.column()
267         col.label("Focus:")
268         col.prop(cam, "dof_object", text="")
269
270         sub = col.row()
271         sub.active = cam.dof_object is None
272         sub.prop(cam, "dof_distance", text="Distance")
273
274         col = split.column()
275
276         col.label("Aperture:")
277         sub = col.column(align=True)
278         sub.prop(ccam, "aperture_type", text="")
279         if ccam.aperture_type == 'RADIUS':
280             sub.prop(ccam, "aperture_size", text="Size")
281         elif ccam.aperture_type == 'FSTOP':
282             sub.prop(ccam, "aperture_fstop", text="Number")
283
284         sub = col.column(align=True)
285         sub.prop(ccam, "aperture_blades", text="Blades")
286         sub.prop(ccam, "aperture_rotation", text="Rotation")
287
288
289 class Cycles_PT_context_material(CyclesButtonsPanel, Panel):
290     bl_label = ""
291     bl_context = "material"
292     bl_options = {'HIDE_HEADER'}
293
294     @classmethod
295     def poll(cls, context):
296         return (context.material or context.object) and CyclesButtonsPanel.poll(context)
297
298     def draw(self, context):
299         layout = self.layout
300
301         mat = context.material
302         ob = context.object
303         slot = context.material_slot
304         space = context.space_data
305
306         if ob:
307             row = layout.row()
308
309             row.template_list(ob, "material_slots", ob, "active_material_index", rows=2)
310
311             col = row.column(align=True)
312             col.operator("object.material_slot_add", icon='ZOOMIN', text="")
313             col.operator("object.material_slot_remove", icon='ZOOMOUT', text="")
314
315             col.menu("MATERIAL_MT_specials", icon='DOWNARROW_HLT', text="")
316
317             if ob.mode == 'EDIT':
318                 row = layout.row(align=True)
319                 row.operator("object.material_slot_assign", text="Assign")
320                 row.operator("object.material_slot_select", text="Select")
321                 row.operator("object.material_slot_deselect", text="Deselect")
322
323         split = layout.split(percentage=0.65)
324
325         if ob:
326             split.template_ID(ob, "active_material", new="material.new")
327             row = split.row()
328
329             if slot:
330                 row.prop(slot, "link", text="")
331             else:
332                 row.label()
333         elif mat:
334             split.template_ID(space, "pin_id")
335             split.separator()
336
337
338 class Cycles_PT_mesh_displacement(CyclesButtonsPanel, Panel):
339     bl_label = "Displacement"
340     bl_context = "data"
341
342     @classmethod
343     def poll(cls, context):
344         if CyclesButtonsPanel.poll(context):
345             if context.mesh or context.curve or context.meta_ball:
346                 if context.scene.cycles.feature_set == 'EXPERIMENTAL':
347                     return True
348
349         return False
350
351     def draw(self, context):
352         layout = self.layout
353
354         mesh = context.mesh
355         curve = context.curve
356         mball = context.meta_ball
357
358         if mesh:
359             cdata = mesh.cycles
360         elif curve:
361             cdata = curve.cycles
362         elif mball:
363             cdata = mball.cycles
364
365         layout.prop(cdata, "displacement_method", text="Method")
366         layout.prop(cdata, "use_subdivision")
367         layout.prop(cdata, "dicing_rate")
368
369
370 class CyclesObject_PT_ray_visibility(CyclesButtonsPanel, Panel):
371     bl_label = "Ray Visibility"
372     bl_context = "object"
373     bl_options = {'DEFAULT_CLOSED'}
374
375     @classmethod
376     def poll(cls, context):
377         ob = context.object
378         return CyclesButtonsPanel.poll(context) and ob and ob.type in {'MESH', 'CURVE', 'CURVE', 'SURFACE', 'FONT', 'META'}  # todo: 'LAMP'
379
380     def draw(self, context):
381         layout = self.layout
382
383         ob = context.object
384         visibility = ob.cycles_visibility
385
386         flow = layout.column_flow()
387
388         flow.prop(visibility, "camera")
389         flow.prop(visibility, "diffuse")
390         flow.prop(visibility, "glossy")
391         flow.prop(visibility, "transmission")
392         flow.prop(visibility, "shadow")
393
394
395 def find_node(material, nodetype):
396     if material and material.node_tree:
397         ntree = material.node_tree
398
399         for node in ntree.nodes:
400             if getattr(node, "type", None) == nodetype:
401                 return node
402
403     return None
404
405
406 def find_node_input(node, name):
407     for input in node.inputs:
408         if input.name == name:
409             return input
410
411     return None
412
413
414 def panel_node_draw(layout, id_data, output_type, input_name):
415     if not id_data.use_nodes:
416         layout.prop(id_data, "use_nodes", icon='NODETREE')
417         return False
418
419     ntree = id_data.node_tree
420
421     node = find_node(id_data, output_type)
422     if not node:
423         layout.label(text="No output node.")
424     else:
425         input = find_node_input(node, input_name)
426         layout.template_node_view(ntree, node, input)
427
428     return True
429
430
431 class CyclesLamp_PT_lamp(CyclesButtonsPanel, Panel):
432     bl_label = "Lamp"
433     bl_context = "data"
434
435     @classmethod
436     def poll(cls, context):
437         return context.lamp and CyclesButtonsPanel.poll(context)
438
439     def draw(self, context):
440         layout = self.layout
441
442         lamp = context.lamp
443         clamp = lamp.cycles
444
445         layout.prop(lamp, "type", expand=True)
446
447         split = layout.split()
448         col = split.column(align=True)
449
450         if lamp.type in {'POINT', 'SUN', 'SPOT'}:
451             col.prop(lamp, "shadow_soft_size", text="Size")
452         elif lamp.type == 'AREA':
453             col.prop(lamp, "shape", text="")
454             sub = col.column(align=True)
455
456             if lamp.shape == 'SQUARE':
457                 sub.prop(lamp, "size")
458             elif lamp.shape == 'RECTANGLE':
459                 sub.prop(lamp, "size", text="Size X")
460                 sub.prop(lamp, "size_y", text="Size Y")
461
462         col = split.column()
463         col.prop(clamp, "cast_shadow")
464
465         if lamp.type == 'SPOT':
466             layout.label(text="Not supported, interpreted as point lamp.")
467         elif lamp.type == 'HEMI':
468             layout.label(text="Not supported, interpreted as sun lamp.")
469
470
471 class CyclesLamp_PT_nodes(CyclesButtonsPanel, Panel):
472     bl_label = "Nodes"
473     bl_context = "data"
474
475     @classmethod
476     def poll(cls, context):
477         return context.lamp and CyclesButtonsPanel.poll(context)
478
479     def draw(self, context):
480         layout = self.layout
481
482         lamp = context.lamp
483         if not panel_node_draw(layout, lamp, 'OUTPUT_LAMP', 'Surface'):
484             layout.prop(lamp, "color")
485
486
487 class CyclesWorld_PT_surface(CyclesButtonsPanel, Panel):
488     bl_label = "Surface"
489     bl_context = "world"
490
491     @classmethod
492     def poll(cls, context):
493         return context.world and CyclesButtonsPanel.poll(context)
494
495     def draw(self, context):
496         layout = self.layout
497
498         world = context.world
499
500         if not panel_node_draw(layout, world, 'OUTPUT_WORLD', 'Surface'):
501             layout.prop(world, "horizon_color", text="Color")
502
503
504 class CyclesWorld_PT_volume(CyclesButtonsPanel, Panel):
505     bl_label = "Volume"
506     bl_context = "world"
507     bl_options = {'DEFAULT_CLOSED'}
508
509     @classmethod
510     def poll(cls, context):
511         # world = context.world
512         # world and world.node_tree and CyclesButtonsPanel.poll(context)
513         return False
514
515     def draw(self, context):
516         layout = self.layout
517         layout.active = False
518
519         world = context.world
520         panel_node_draw(layout, world, 'OUTPUT_WORLD', 'Volume')
521
522
523 class CyclesWorld_PT_ambient_occlusion(CyclesButtonsPanel, Panel):
524     bl_label = "Ambient Occlusion"
525     bl_context = "world"
526
527     @classmethod
528     def poll(cls, context):
529         return context.world and CyclesButtonsPanel.poll(context)
530
531     def draw_header(self, context):
532         light = context.world.light_settings
533         self.layout.prop(light, "use_ambient_occlusion", text="")
534
535     def draw(self, context):
536         layout = self.layout
537         light = context.world.light_settings
538
539         layout.active = light.use_ambient_occlusion
540
541         row = layout.row()
542         row.prop(light, "ao_factor", text="Factor")
543         row.prop(light, "distance", text="Distance")
544
545
546 class CyclesWorld_PT_settings(CyclesButtonsPanel, Panel):
547     bl_label = "Settings"
548     bl_context = "world"
549     bl_options = {'DEFAULT_CLOSED'}
550
551     @classmethod
552     def poll(cls, context):
553         return context.world and CyclesButtonsPanel.poll(context)
554
555     def draw(self, context):
556         layout = self.layout
557
558         world = context.world
559         cworld = world.cycles
560
561         col = layout.column()
562
563         col.prop(cworld, "sample_as_light")
564         row = col.row()
565         row.active = cworld.sample_as_light
566         row.prop(cworld, "sample_map_resolution")
567
568
569 class CyclesMaterial_PT_surface(CyclesButtonsPanel, Panel):
570     bl_label = "Surface"
571     bl_context = "material"
572
573     @classmethod
574     def poll(cls, context):
575         return context.material and CyclesButtonsPanel.poll(context)
576
577     def draw(self, context):
578         layout = self.layout
579
580         mat = context.material
581         if not panel_node_draw(layout, mat, 'OUTPUT_MATERIAL', 'Surface'):
582             layout.prop(mat, "diffuse_color")
583
584
585 class CyclesMaterial_PT_volume(CyclesButtonsPanel, Panel):
586     bl_label = "Volume"
587     bl_context = "material"
588     bl_options = {'DEFAULT_CLOSED'}
589
590     @classmethod
591     def poll(cls, context):
592         # mat = context.material
593         # mat and mat.node_tree and CyclesButtonsPanel.poll(context)
594         return False
595
596     def draw(self, context):
597         layout = self.layout
598         layout.active = False
599
600         mat = context.material
601         cmat = mat.cycles
602
603         panel_node_draw(layout, mat, 'OUTPUT_MATERIAL', 'Volume')
604
605         layout.prop(cmat, "homogeneous_volume")
606
607
608 class CyclesMaterial_PT_displacement(CyclesButtonsPanel, Panel):
609     bl_label = "Displacement"
610     bl_context = "material"
611
612     @classmethod
613     def poll(cls, context):
614         mat = context.material
615         return mat and mat.node_tree and CyclesButtonsPanel.poll(context)
616
617     def draw(self, context):
618         layout = self.layout
619
620         mat = context.material
621         panel_node_draw(layout, mat, 'OUTPUT_MATERIAL', 'Displacement')
622
623
624 class CyclesMaterial_PT_settings(CyclesButtonsPanel, Panel):
625     bl_label = "Settings"
626     bl_context = "material"
627     bl_options = {'DEFAULT_CLOSED'}
628
629     @classmethod
630     def poll(cls, context):
631         return context.material and CyclesButtonsPanel.poll(context)
632
633     def draw(self, context):
634         layout = self.layout
635
636         mat = context.material
637         cmat = mat.cycles
638
639         split = layout.split()
640
641         col = split.column()
642         col.prop(mat, "diffuse_color", text="Viewport Color")
643
644         col = split.column()
645         col.prop(cmat, "sample_as_light")
646         col.prop(mat, "pass_index")
647
648
649 class CyclesTexture_PT_context(CyclesButtonsPanel, Panel):
650     bl_label = ""
651     bl_context = "texture"
652     bl_options = {'HIDE_HEADER'}
653     COMPAT_ENGINES = {'CYCLES'}
654
655     def draw(self, context):
656         layout = self.layout
657
658         tex = context.texture
659         space = context.space_data
660         pin_id = space.pin_id
661         use_pin_id = space.use_pin_id
662         user = context.texture_user
663
664         if not use_pin_id or not isinstance(pin_id, bpy.types.Texture):
665             pin_id = None
666
667         if not pin_id:
668             layout.template_texture_user()
669
670         if user:
671             layout.separator()
672
673             split = layout.split(percentage=0.65)
674             col = split.column()
675
676             if pin_id:
677                 col.template_ID(space, "pin_id")
678             elif user:
679                 col.template_ID(user, "texture", new="texture.new")
680
681             if tex:
682                 split = layout.split(percentage=0.2)
683                 split.label(text="Type:")
684                 split.prop(tex, "type", text="")
685
686
687 class CyclesTexture_PT_nodes(CyclesButtonsPanel, Panel):
688     bl_label = "Nodes"
689     bl_context = "texture"
690
691     @classmethod
692     def poll(cls, context):
693         tex = context.texture
694         return (tex and tex.use_nodes) and CyclesButtonsPanel.poll(context)
695
696     def draw(self, context):
697         layout = self.layout
698
699         tex = context.texture
700         panel_node_draw(layout, tex, 'OUTPUT_TEXTURE', 'Color')
701
702
703 class CyclesTexture_PT_node(CyclesButtonsPanel, Panel):
704     bl_label = "Node"
705     bl_context = "texture"
706
707     @classmethod
708     def poll(cls, context):
709         node = context.texture_node
710         return node and CyclesButtonsPanel.poll(context)
711
712     def draw(self, context):
713         layout = self.layout
714
715         node = context.texture_node
716         ntree = node.id_data
717         layout.template_node_view(ntree, node, None)
718
719
720 class CyclesTexture_PT_mapping(CyclesButtonsPanel, Panel):
721     bl_label = "Mapping"
722     bl_context = "texture"
723
724     @classmethod
725     def poll(cls, context):
726         tex = context.texture
727         node = context.texture_node
728         return (node or (tex and tex.use_nodes)) and CyclesButtonsPanel.poll(context)
729
730     def draw(self, context):
731         layout = self.layout
732
733         # tex = context.texture
734         node = context.texture_node
735
736         mapping = node.texture_mapping
737
738         row = layout.row()
739
740         row.column().prop(mapping, "translation")
741         row.column().prop(mapping, "rotation")
742         row.column().prop(mapping, "scale")
743
744         layout.label(text="Projection:")
745
746         row = layout.row()
747         row.prop(mapping, "mapping_x", text="")
748         row.prop(mapping, "mapping_y", text="")
749         row.prop(mapping, "mapping_z", text="")
750
751
752 class CyclesTexture_PT_colors(CyclesButtonsPanel, Panel):
753     bl_label = "Color"
754     bl_context = "texture"
755     bl_options = {'DEFAULT_CLOSED'}
756
757     @classmethod
758     def poll(cls, context):
759         # tex = context.texture
760         # node = context.texture_node
761         return False
762         #return (node or (tex and tex.use_nodes)) and CyclesButtonsPanel.poll(context)
763
764     def draw(self, context):
765         layout = self.layout
766
767         # tex = context.texture
768         node = context.texture_node
769
770         mapping = node.color_mapping
771
772         split = layout.split()
773
774         col = split.column()
775         col.label(text="Blend:")
776         col.prop(mapping, "blend_type", text="")
777         col.prop(mapping, "blend_factor", text="Factor")
778         col.prop(mapping, "blend_color", text="")
779
780         col = split.column()
781         col.label(text="Adjust:")
782         col.prop(mapping, "brightness")
783         col.prop(mapping, "contrast")
784         col.prop(mapping, "saturation")
785
786         layout.separator()
787
788         layout.prop(mapping, "use_color_ramp", text="Ramp")
789         if mapping.use_color_ramp:
790             layout.template_color_ramp(mapping, "color_ramp", expand=True)
791
792
793 def draw_device(self, context):
794     scene = context.scene
795     layout = self.layout
796
797     if scene.render.engine == 'CYCLES':
798         cscene = scene.cycles
799
800         layout.prop(cscene, "feature_set")
801
802         device_type = context.user_preferences.system.compute_device_type
803         if device_type == 'CUDA':
804             layout.prop(cscene, "device")
805         elif device_type == 'OPENCL' and cscene.feature_set == 'EXPERIMENTAL':
806             layout.prop(cscene, "device")
807
808
809 def draw_pause(self, context):
810     layout = self.layout
811     scene = context.scene
812
813     if scene.render.engine == "CYCLES":
814         view = context.space_data
815
816         if view.viewport_shade == 'RENDERED':
817             cscene = scene.cycles
818             layername = scene.render.layers.active.name
819             layout.prop(cscene, "preview_pause", icon="PAUSE", text="")
820             layout.prop(cscene, "preview_active_layer", icon="RENDERLAYERS", text=layername)
821
822
823 def get_panels():
824     return (
825         bpy.types.RENDER_PT_render,
826         bpy.types.RENDER_PT_output,
827         bpy.types.RENDER_PT_encoding,
828         bpy.types.RENDER_PT_dimensions,
829         bpy.types.RENDER_PT_stamp,
830         bpy.types.SCENE_PT_scene,
831         bpy.types.SCENE_PT_audio,
832         bpy.types.SCENE_PT_unit,
833         bpy.types.SCENE_PT_keying_sets,
834         bpy.types.SCENE_PT_keying_set_paths,
835         bpy.types.SCENE_PT_physics,
836         bpy.types.WORLD_PT_context_world,
837         bpy.types.DATA_PT_context_mesh,
838         bpy.types.DATA_PT_context_camera,
839         bpy.types.DATA_PT_context_lamp,
840         bpy.types.DATA_PT_texture_space,
841         bpy.types.DATA_PT_curve_texture_space,
842         bpy.types.DATA_PT_mball_texture_space,
843         bpy.types.DATA_PT_vertex_groups,
844         bpy.types.DATA_PT_shape_keys,
845         bpy.types.DATA_PT_uv_texture,
846         bpy.types.DATA_PT_vertex_colors,
847         bpy.types.DATA_PT_camera,
848         bpy.types.DATA_PT_camera_display,
849         bpy.types.DATA_PT_lens,
850         bpy.types.DATA_PT_custom_props_mesh,
851         bpy.types.DATA_PT_custom_props_camera,
852         bpy.types.DATA_PT_custom_props_lamp,
853         bpy.types.TEXTURE_PT_clouds,
854         bpy.types.TEXTURE_PT_wood,
855         bpy.types.TEXTURE_PT_marble,
856         bpy.types.TEXTURE_PT_magic,
857         bpy.types.TEXTURE_PT_blend,
858         bpy.types.TEXTURE_PT_stucci,
859         bpy.types.TEXTURE_PT_image,
860         bpy.types.TEXTURE_PT_image_sampling,
861         bpy.types.TEXTURE_PT_image_mapping,
862         bpy.types.TEXTURE_PT_musgrave,
863         bpy.types.TEXTURE_PT_voronoi,
864         bpy.types.TEXTURE_PT_distortednoise,
865         bpy.types.TEXTURE_PT_voxeldata,
866         bpy.types.TEXTURE_PT_pointdensity,
867         bpy.types.TEXTURE_PT_pointdensity_turbulence,
868         bpy.types.PARTICLE_PT_context_particles,
869         bpy.types.PARTICLE_PT_emission,
870         bpy.types.PARTICLE_PT_hair_dynamics,
871         bpy.types.PARTICLE_PT_cache,
872         bpy.types.PARTICLE_PT_velocity,
873         bpy.types.PARTICLE_PT_rotation,
874         bpy.types.PARTICLE_PT_physics,
875         bpy.types.PARTICLE_PT_boidbrain,
876         bpy.types.PARTICLE_PT_render,
877         bpy.types.PARTICLE_PT_draw,
878         bpy.types.PARTICLE_PT_children,
879         bpy.types.PARTICLE_PT_field_weights,
880         bpy.types.PARTICLE_PT_force_fields,
881         bpy.types.PARTICLE_PT_vertexgroups,
882         bpy.types.PARTICLE_PT_custom_props,
883         )
884
885
886 def register():
887     bpy.types.RENDER_PT_render.append(draw_device)
888     bpy.types.VIEW3D_HT_header.append(draw_pause)
889
890     for panel in get_panels():
891         panel.COMPAT_ENGINES.add('CYCLES')
892
893
894 def unregister():
895     bpy.types.RENDER_PT_render.remove(draw_device)
896     bpy.types.VIEW3D_HT_header.remove(draw_pause)
897
898     for panel in get_panels():
899         panel.COMPAT_ENGINES.remove('CYCLES')