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