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