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