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