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