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