Cycles: shuffle addon import statements a bit to try to fix a strange import
[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
26 class CYCLES_MT_integrator_presets(Menu):
27     bl_label = "Integrator Presets"
28     preset_subdir = "cycles/integrator"
29     preset_operator = "script.execute_preset"
30     COMPAT_ENGINES = {'CYCLES'}
31     draw = Menu.draw_preset
32
33
34 class CyclesButtonsPanel():
35     bl_space_type = "PROPERTIES"
36     bl_region_type = "WINDOW"
37     bl_context = "render"
38
39     @classmethod
40     def poll(cls, context):
41         rd = context.scene.render
42         return rd.engine == 'CYCLES'
43
44
45 class CyclesRender_PT_sampling(CyclesButtonsPanel, Panel):
46     bl_label = "Sampling"
47     bl_options = {'DEFAULT_CLOSED'}
48
49     def draw(self, context):
50         layout = self.layout
51
52         scene = context.scene
53         cscene = scene.cycles
54         device_type = context.user_preferences.system.compute_device_type
55
56         split = layout.split()
57
58         col = split.column()
59         sub = col.column()
60         sub.active = (device_type == 'NONE' or cscene.device == 'CPU')
61         sub.prop(cscene, "progressive")
62
63         sub = col.column(align=True)
64         sub.prop(cscene, "seed")
65         sub.prop(cscene, "sample_clamp")
66
67         if cscene.progressive or (device_type != 'NONE' and cscene.device == 'GPU'):
68             col = split.column()
69             col.label(text="Samples:")
70             sub = col.column(align=True)
71             sub.prop(cscene, "samples", text="Render")
72             sub.prop(cscene, "preview_samples", text="Preview")
73         else:
74             sub.label(text="AA Samples:")
75             sub.prop(cscene, "aa_samples", text="Render")
76             sub.prop(cscene, "preview_aa_samples", text="Preview")
77
78             col = split.column()
79             col.label(text="Samples:")
80             sub = col.column(align=True)
81             sub.prop(cscene, "diffuse_samples", text="Diffuse")
82             sub.prop(cscene, "glossy_samples", text="Glossy")
83             sub.prop(cscene, "transmission_samples", text="Transmission")
84             sub.prop(cscene, "ao_samples", text="AO")
85             sub.prop(cscene, "mesh_light_samples", text="Mesh Light")
86
87
88 class CyclesRender_PT_light_paths(CyclesButtonsPanel, Panel):
89     bl_label = "Light Paths"
90     bl_options = {'DEFAULT_CLOSED'}
91
92     def draw(self, context):
93         layout = self.layout
94
95         scene = context.scene
96         cscene = scene.cycles
97
98         row = layout.row(align=True)
99         row.menu("CYCLES_MT_integrator_presets", text=bpy.types.CYCLES_MT_integrator_presets.bl_label)
100         row.operator("render.cycles_integrator_preset_add", text="", icon="ZOOMIN")
101         row.operator("render.cycles_integrator_preset_add", text="", icon="ZOOMOUT").remove_active = True
102
103         split = layout.split()
104
105         col = split.column()
106
107         sub = col.column(align=True)
108         sub.label("Transparency:")
109         sub.prop(cscene, "transparent_max_bounces", text="Max")
110         sub.prop(cscene, "transparent_min_bounces", text="Min")
111         sub.prop(cscene, "use_transparent_shadows", text="Shadows")
112
113         col.separator()
114
115         col.prop(cscene, "no_caustics")
116         col.prop(cscene, "blur_glossy")
117
118         col = split.column()
119
120         sub = col.column(align=True)
121         sub.label(text="Bounces:")
122         sub.prop(cscene, "max_bounces", text="Max")
123         sub.prop(cscene, "min_bounces", text="Min")
124
125         sub = col.column(align=True)
126         sub.prop(cscene, "diffuse_bounces", text="Diffuse")
127         sub.prop(cscene, "glossy_bounces", text="Glossy")
128         sub.prop(cscene, "transmission_bounces", text="Transmission")
129
130
131 class CyclesRender_PT_motion_blur(CyclesButtonsPanel, Panel):
132     bl_label = "Motion Blur"
133     bl_options = {'DEFAULT_CLOSED'}
134
135     def draw_header(self, context):
136         rd = context.scene.render
137
138         self.layout.prop(rd, "use_motion_blur", text="")
139
140     def draw(self, context):
141         layout = self.layout
142
143         rd = context.scene.render
144         layout.active = rd.use_motion_blur
145
146         row = layout.row()
147         row.prop(rd, "motion_blur_shutter")
148
149
150 class CyclesRender_PT_film(CyclesButtonsPanel, Panel):
151     bl_label = "Film"
152
153     def draw(self, context):
154         layout = self.layout
155
156         scene = context.scene
157         cscene = scene.cycles
158
159         split = layout.split()
160
161         col = split.column()
162         col.prop(cscene, "film_exposure")
163         col.prop(cscene, "film_transparent")
164
165         col = split.column()
166         sub = col.column(align=True)
167         sub.prop(cscene, "filter_type", text="")
168         if cscene.filter_type != 'BOX':
169             sub.prop(cscene, "filter_width", text="Width")
170
171
172 class CyclesRender_PT_performance(CyclesButtonsPanel, Panel):
173     bl_label = "Performance"
174     bl_options = {'DEFAULT_CLOSED'}
175
176     def draw(self, context):
177         layout = self.layout
178
179         scene = context.scene
180         rd = scene.render
181         cscene = scene.cycles
182
183         split = layout.split()
184
185         col = split.column(align=True)
186
187         col.label(text="Threads:")
188         col.row().prop(rd, "threads_mode", expand=True)
189         sub = col.column()
190         sub.enabled = rd.threads_mode == 'FIXED'
191         sub.prop(rd, "threads")
192
193         sub = col.column(align=True)
194         sub.label(text="Tile Size:")
195
196         sub.prop(rd, "tile_x", text="X")
197         sub.prop(rd, "tile_y", text="Y")
198
199         sub.prop(cscene, "use_progressive_refine")
200
201         subsub = sub.column()
202         subsub.enabled = not rd.use_border
203         subsub.prop(rd, "use_save_buffers")
204
205         col = split.column()
206
207         sub = col.column(align=True)
208         sub.label(text="Acceleration structure:")
209         sub.prop(cscene, "debug_bvh_type", text="")
210         sub.prop(cscene, "debug_use_spatial_splits")
211         sub.prop(cscene, "use_cache")
212
213         sub = col.column(align=True)
214         sub.label(text="Viewport:")
215         sub.prop(cscene, "preview_start_resolution")
216
217         sub = col.column(align=True)
218         sub.label(text="Final Render:")
219         sub.prop(rd, "use_persistent_data", text="Persistent Images")
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
441 class Cycles_PT_mesh_normals(CyclesButtonsPanel, Panel):
442     bl_label = "Normals"
443     bl_context = "data"
444
445     @classmethod
446     def poll(cls, context):
447         return CyclesButtonsPanel.poll(context) and context.mesh
448
449     def draw(self, context):
450         layout = self.layout
451
452         mesh = context.mesh
453
454         split = layout.split()
455
456         col = split.column()
457         col.prop(mesh, "show_double_sided")
458
459         col = split.column()
460         col.label()
461
462
463 class CyclesObject_PT_ray_visibility(CyclesButtonsPanel, Panel):
464     bl_label = "Ray Visibility"
465     bl_context = "object"
466     bl_options = {'DEFAULT_CLOSED'}
467
468     @classmethod
469     def poll(cls, context):
470         ob = context.object
471         return CyclesButtonsPanel.poll(context) and ob and ob.type in {'MESH', 'CURVE', 'CURVE', 'SURFACE', 'FONT', 'META'}  # todo: 'LAMP'
472
473     def draw(self, context):
474         layout = self.layout
475
476         ob = context.object
477         visibility = ob.cycles_visibility
478
479         flow = layout.column_flow()
480
481         flow.prop(visibility, "camera")
482         flow.prop(visibility, "diffuse")
483         flow.prop(visibility, "glossy")
484         flow.prop(visibility, "transmission")
485         flow.prop(visibility, "shadow")
486
487
488 def find_node(material, nodetype):
489     if material and material.node_tree:
490         ntree = material.node_tree
491
492         for node in ntree.nodes:
493             if getattr(node, "type", None) == nodetype:
494                 return node
495
496     return None
497
498
499 def find_node_input(node, name):
500     for input in node.inputs:
501         if input.name == name:
502             return input
503
504     return None
505
506
507 def panel_node_draw(layout, id_data, output_type, input_name):
508     if not id_data.use_nodes:
509         layout.prop(id_data, "use_nodes", icon='NODETREE')
510         return False
511
512     ntree = id_data.node_tree
513
514     node = find_node(id_data, output_type)
515     if not node:
516         layout.label(text="No output node.")
517     else:
518         input = find_node_input(node, input_name)
519         layout.template_node_view(ntree, node, input)
520
521     return True
522
523
524 class CyclesLamp_PT_lamp(CyclesButtonsPanel, Panel):
525     bl_label = "Lamp"
526     bl_context = "data"
527
528     @classmethod
529     def poll(cls, context):
530         return context.lamp and CyclesButtonsPanel.poll(context)
531
532     def draw(self, context):
533         layout = self.layout
534
535         lamp = context.lamp
536         clamp = lamp.cycles
537         cscene = context.scene.cycles
538         device_type = context.user_preferences.system.compute_device_type
539
540         layout.prop(lamp, "type", expand=True)
541
542         split = layout.split()
543         col = split.column(align=True)
544
545         if lamp.type in {'POINT', 'SUN', 'SPOT'}:
546             col.prop(lamp, "shadow_soft_size", text="Size")
547         elif lamp.type == 'AREA':
548             col.prop(lamp, "shape", text="")
549             sub = col.column(align=True)
550
551             if lamp.shape == 'SQUARE':
552                 sub.prop(lamp, "size")
553             elif lamp.shape == 'RECTANGLE':
554                 sub.prop(lamp, "size", text="Size X")
555                 sub.prop(lamp, "size_y", text="Size Y")
556
557         if not cscene.progressive and (device_type == 'NONE' or cscene.device == 'CPU'):
558             col.prop(clamp, "samples")
559
560         col = split.column()
561         col.prop(clamp, "cast_shadow")
562
563         if lamp.type == 'HEMI':
564             layout.label(text="Not supported, interpreted as sun lamp.")
565
566
567 class CyclesLamp_PT_nodes(CyclesButtonsPanel, Panel):
568     bl_label = "Nodes"
569     bl_context = "data"
570
571     @classmethod
572     def poll(cls, context):
573         return context.lamp and CyclesButtonsPanel.poll(context)
574
575     def draw(self, context):
576         layout = self.layout
577
578         lamp = context.lamp
579         if not panel_node_draw(layout, lamp, 'OUTPUT_LAMP', 'Surface'):
580             layout.prop(lamp, "color")
581
582
583 class CyclesLamp_PT_spot(CyclesButtonsPanel, Panel):
584     bl_label = "Spot Shape"
585     bl_context = "data"
586
587     @classmethod
588     def poll(cls, context):
589         lamp = context.lamp
590         return (lamp and lamp.type == 'SPOT') and CyclesButtonsPanel.poll(context)
591
592     def draw(self, context):
593         layout = self.layout
594
595         lamp = context.lamp
596
597         split = layout.split()
598
599         col = split.column()
600         sub = col.column()
601         sub.prop(lamp, "spot_size", text="Size")
602         sub.prop(lamp, "spot_blend", text="Blend", slider=True)
603
604         col = split.column()
605         col.prop(lamp, "show_cone")
606
607
608 class CyclesWorld_PT_surface(CyclesButtonsPanel, Panel):
609     bl_label = "Surface"
610     bl_context = "world"
611
612     @classmethod
613     def poll(cls, context):
614         return context.world and CyclesButtonsPanel.poll(context)
615
616     def draw(self, context):
617         layout = self.layout
618
619         world = context.world
620
621         if not panel_node_draw(layout, world, 'OUTPUT_WORLD', 'Surface'):
622             layout.prop(world, "horizon_color", text="Color")
623
624
625 class CyclesWorld_PT_volume(CyclesButtonsPanel, Panel):
626     bl_label = "Volume"
627     bl_context = "world"
628     bl_options = {'DEFAULT_CLOSED'}
629
630     @classmethod
631     def poll(cls, context):
632         # world = context.world
633         # world and world.node_tree and CyclesButtonsPanel.poll(context)
634         return False
635
636     def draw(self, context):
637         layout = self.layout
638         layout.active = False
639
640         world = context.world
641         panel_node_draw(layout, world, 'OUTPUT_WORLD', 'Volume')
642
643
644 class CyclesWorld_PT_ambient_occlusion(CyclesButtonsPanel, Panel):
645     bl_label = "Ambient Occlusion"
646     bl_context = "world"
647
648     @classmethod
649     def poll(cls, context):
650         return context.world and CyclesButtonsPanel.poll(context)
651
652     def draw_header(self, context):
653         light = context.world.light_settings
654         self.layout.prop(light, "use_ambient_occlusion", text="")
655
656     def draw(self, context):
657         layout = self.layout
658         light = context.world.light_settings
659
660         layout.active = light.use_ambient_occlusion
661
662         row = layout.row()
663         row.prop(light, "ao_factor", text="Factor")
664         row.prop(light, "distance", text="Distance")
665
666
667 class CyclesWorld_PT_settings(CyclesButtonsPanel, Panel):
668     bl_label = "Settings"
669     bl_context = "world"
670     bl_options = {'DEFAULT_CLOSED'}
671
672     @classmethod
673     def poll(cls, context):
674         return context.world and CyclesButtonsPanel.poll(context)
675
676     def draw(self, context):
677         layout = self.layout
678
679         world = context.world
680         cworld = world.cycles
681         cscene = context.scene.cycles
682         device_type = context.user_preferences.system.compute_device_type
683
684         col = layout.column()
685
686         col.prop(cworld, "sample_as_light")
687         sub = col.row(align=True)
688         sub.active = cworld.sample_as_light
689         sub.prop(cworld, "sample_map_resolution")
690         if not cscene.progressive and (device_type == 'NONE' or cscene.device == 'CPU'):
691             sub.prop(cworld, "samples")
692
693
694 class CyclesMaterial_PT_surface(CyclesButtonsPanel, Panel):
695     bl_label = "Surface"
696     bl_context = "material"
697
698     @classmethod
699     def poll(cls, context):
700         return context.material and CyclesButtonsPanel.poll(context)
701
702     def draw(self, context):
703         layout = self.layout
704
705         mat = context.material
706         if not panel_node_draw(layout, mat, 'OUTPUT_MATERIAL', 'Surface'):
707             layout.prop(mat, "diffuse_color")
708
709
710 class CyclesMaterial_PT_volume(CyclesButtonsPanel, Panel):
711     bl_label = "Volume"
712     bl_context = "material"
713     bl_options = {'DEFAULT_CLOSED'}
714
715     @classmethod
716     def poll(cls, context):
717         # mat = context.material
718         # mat and mat.node_tree and CyclesButtonsPanel.poll(context)
719         return False
720
721     def draw(self, context):
722         layout = self.layout
723         layout.active = False
724
725         mat = context.material
726         cmat = mat.cycles
727
728         panel_node_draw(layout, mat, 'OUTPUT_MATERIAL', 'Volume')
729
730         layout.prop(cmat, "homogeneous_volume")
731
732
733 class CyclesMaterial_PT_displacement(CyclesButtonsPanel, Panel):
734     bl_label = "Displacement"
735     bl_context = "material"
736
737     @classmethod
738     def poll(cls, context):
739         mat = context.material
740         return mat and mat.node_tree and CyclesButtonsPanel.poll(context)
741
742     def draw(self, context):
743         layout = self.layout
744
745         mat = context.material
746         panel_node_draw(layout, mat, 'OUTPUT_MATERIAL', 'Displacement')
747
748
749 class CyclesMaterial_PT_settings(CyclesButtonsPanel, Panel):
750     bl_label = "Settings"
751     bl_context = "material"
752     bl_options = {'DEFAULT_CLOSED'}
753
754     @classmethod
755     def poll(cls, context):
756         return context.material and CyclesButtonsPanel.poll(context)
757
758     def draw(self, context):
759         layout = self.layout
760
761         mat = context.material
762         cmat = mat.cycles
763
764         split = layout.split()
765
766         col = split.column()
767         col.prop(mat, "diffuse_color", text="Viewport Color")
768
769         col = split.column()
770         col.prop(cmat, "sample_as_light")
771         col.prop(mat, "pass_index")
772
773
774 class CyclesTexture_PT_context(CyclesButtonsPanel, Panel):
775     bl_label = ""
776     bl_context = "texture"
777     bl_options = {'HIDE_HEADER'}
778     COMPAT_ENGINES = {'CYCLES'}
779
780     def draw(self, context):
781         layout = self.layout
782
783         tex = context.texture
784         space = context.space_data
785         pin_id = space.pin_id
786         use_pin_id = space.use_pin_id
787         user = context.texture_user
788
789         if not use_pin_id or not isinstance(pin_id, bpy.types.Texture):
790             pin_id = None
791
792         if not pin_id:
793             layout.template_texture_user()
794
795         if user:
796             layout.separator()
797
798             split = layout.split(percentage=0.65)
799             col = split.column()
800
801             if pin_id:
802                 col.template_ID(space, "pin_id")
803             elif user:
804                 col.template_ID(user, "texture", new="texture.new")
805
806             if tex:
807                 split = layout.split(percentage=0.2)
808                 split.label(text="Type:")
809                 split.prop(tex, "type", text="")
810
811
812 class CyclesTexture_PT_nodes(CyclesButtonsPanel, Panel):
813     bl_label = "Nodes"
814     bl_context = "texture"
815
816     @classmethod
817     def poll(cls, context):
818         tex = context.texture
819         return (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         panel_node_draw(layout, tex, 'OUTPUT_TEXTURE', 'Color')
826
827
828 class CyclesTexture_PT_node(CyclesButtonsPanel, Panel):
829     bl_label = "Node"
830     bl_context = "texture"
831
832     @classmethod
833     def poll(cls, context):
834         node = context.texture_node
835         return node and CyclesButtonsPanel.poll(context)
836
837     def draw(self, context):
838         layout = self.layout
839
840         node = context.texture_node
841         ntree = node.id_data
842         layout.template_node_view(ntree, node, None)
843
844
845 class CyclesTexture_PT_mapping(CyclesButtonsPanel, Panel):
846     bl_label = "Mapping"
847     bl_context = "texture"
848
849     @classmethod
850     def poll(cls, context):
851         tex = context.texture
852         node = context.texture_node
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.texture_mapping
862
863         row = layout.row()
864
865         row.column().prop(mapping, "translation")
866         row.column().prop(mapping, "rotation")
867         row.column().prop(mapping, "scale")
868
869         layout.label(text="Projection:")
870
871         row = layout.row()
872         row.prop(mapping, "mapping_x", text="")
873         row.prop(mapping, "mapping_y", text="")
874         row.prop(mapping, "mapping_z", text="")
875
876
877 class CyclesTexture_PT_colors(CyclesButtonsPanel, Panel):
878     bl_label = "Color"
879     bl_context = "texture"
880     bl_options = {'DEFAULT_CLOSED'}
881
882     @classmethod
883     def poll(cls, context):
884         # tex = context.texture
885         # node = context.texture_node
886         return False
887         #return (node or (tex and tex.use_nodes)) and CyclesButtonsPanel.poll(context)
888
889     def draw(self, context):
890         layout = self.layout
891
892         # tex = context.texture
893         node = context.texture_node
894
895         mapping = node.color_mapping
896
897         split = layout.split()
898
899         col = split.column()
900         col.label(text="Blend:")
901         col.prop(mapping, "blend_type", text="")
902         col.prop(mapping, "blend_factor", text="Factor")
903         col.prop(mapping, "blend_color", text="")
904
905         col = split.column()
906         col.label(text="Adjust:")
907         col.prop(mapping, "brightness")
908         col.prop(mapping, "contrast")
909         col.prop(mapping, "saturation")
910
911         layout.separator()
912
913         layout.prop(mapping, "use_color_ramp", text="Ramp")
914         if mapping.use_color_ramp:
915             layout.template_color_ramp(mapping, "color_ramp", expand=True)
916
917
918 class CyclesScene_PT_simplify(CyclesButtonsPanel, Panel):
919     bl_label = "Simplify"
920     bl_context = "scene"
921     COMPAT_ENGINES = {'CYCLES'}
922
923     def draw_header(self, context):
924         rd = context.scene.render
925         self.layout.prop(rd, "use_simplify", text="")
926
927     def draw(self, context):
928         layout = self.layout
929
930         rd = context.scene.render
931
932         layout.active = rd.use_simplify
933
934         split = layout.split()
935
936         col = split.column()
937         col.prop(rd, "simplify_subdivision", text="Subdivision")
938
939         col = split.column()
940         col.prop(rd, "simplify_child_particles", text="Child Particles")
941
942
943 def draw_device(self, context):
944     scene = context.scene
945     layout = self.layout
946
947     if scene.render.engine == 'CYCLES':
948         from . import engine
949         cscene = scene.cycles
950
951         layout.prop(cscene, "feature_set")
952
953         device_type = context.user_preferences.system.compute_device_type
954         if device_type == 'CUDA':
955             layout.prop(cscene, "device")
956         elif device_type == 'OPENCL' and cscene.feature_set == 'EXPERIMENTAL':
957             layout.prop(cscene, "device")
958
959         if engine.with_osl() and (cscene.device == 'CPU' or device_type == 'NONE'):
960             layout.prop(cscene, "shading_system")
961
962
963 def draw_pause(self, context):
964     layout = self.layout
965     scene = context.scene
966
967     if scene.render.engine == "CYCLES":
968         view = context.space_data
969
970         if view.viewport_shade == 'RENDERED':
971             cscene = scene.cycles
972             layername = scene.render.layers.active.name
973             layout.prop(cscene, "preview_pause", icon="PAUSE", text="")
974             layout.prop(cscene, "preview_active_layer", icon="RENDERLAYERS", text=layername)
975
976
977 def get_panels():
978     return (
979         bpy.types.RENDER_PT_render,
980         bpy.types.RENDER_PT_output,
981         bpy.types.RENDER_PT_encoding,
982         bpy.types.RENDER_PT_dimensions,
983         bpy.types.RENDER_PT_stamp,
984         bpy.types.SCENE_PT_scene,
985         bpy.types.SCENE_PT_audio,
986         bpy.types.SCENE_PT_unit,
987         bpy.types.SCENE_PT_keying_sets,
988         bpy.types.SCENE_PT_keying_set_paths,
989         bpy.types.SCENE_PT_physics,
990         bpy.types.WORLD_PT_context_world,
991         bpy.types.DATA_PT_context_mesh,
992         bpy.types.DATA_PT_context_camera,
993         bpy.types.DATA_PT_context_lamp,
994         bpy.types.DATA_PT_context_speaker,
995         bpy.types.DATA_PT_texture_space,
996         bpy.types.DATA_PT_curve_texture_space,
997         bpy.types.DATA_PT_mball_texture_space,
998         bpy.types.DATA_PT_vertex_groups,
999         bpy.types.DATA_PT_shape_keys,
1000         bpy.types.DATA_PT_uv_texture,
1001         bpy.types.DATA_PT_vertex_colors,
1002         bpy.types.DATA_PT_camera,
1003         bpy.types.DATA_PT_camera_display,
1004         bpy.types.DATA_PT_lens,
1005         bpy.types.DATA_PT_speaker,
1006         bpy.types.DATA_PT_distance,
1007         bpy.types.DATA_PT_cone,
1008         bpy.types.DATA_PT_customdata,
1009         bpy.types.DATA_PT_custom_props_mesh,
1010         bpy.types.DATA_PT_custom_props_camera,
1011         bpy.types.DATA_PT_custom_props_lamp,
1012         bpy.types.DATA_PT_custom_props_speaker,
1013         bpy.types.TEXTURE_PT_clouds,
1014         bpy.types.TEXTURE_PT_wood,
1015         bpy.types.TEXTURE_PT_marble,
1016         bpy.types.TEXTURE_PT_magic,
1017         bpy.types.TEXTURE_PT_blend,
1018         bpy.types.TEXTURE_PT_stucci,
1019         bpy.types.TEXTURE_PT_image,
1020         bpy.types.TEXTURE_PT_image_sampling,
1021         bpy.types.TEXTURE_PT_image_mapping,
1022         bpy.types.TEXTURE_PT_musgrave,
1023         bpy.types.TEXTURE_PT_voronoi,
1024         bpy.types.TEXTURE_PT_distortednoise,
1025         bpy.types.TEXTURE_PT_voxeldata,
1026         bpy.types.TEXTURE_PT_pointdensity,
1027         bpy.types.TEXTURE_PT_pointdensity_turbulence,
1028         bpy.types.TEXTURE_PT_mapping,
1029         bpy.types.TEXTURE_PT_influence,
1030         bpy.types.PARTICLE_PT_context_particles,
1031         bpy.types.PARTICLE_PT_emission,
1032         bpy.types.PARTICLE_PT_hair_dynamics,
1033         bpy.types.PARTICLE_PT_cache,
1034         bpy.types.PARTICLE_PT_velocity,
1035         bpy.types.PARTICLE_PT_rotation,
1036         bpy.types.PARTICLE_PT_physics,
1037         bpy.types.PARTICLE_PT_boidbrain,
1038         bpy.types.PARTICLE_PT_render,
1039         bpy.types.PARTICLE_PT_draw,
1040         bpy.types.PARTICLE_PT_children,
1041         bpy.types.PARTICLE_PT_field_weights,
1042         bpy.types.PARTICLE_PT_force_fields,
1043         bpy.types.PARTICLE_PT_vertexgroups,
1044         bpy.types.PARTICLE_PT_custom_props,
1045         )
1046
1047
1048 def register():
1049     bpy.types.RENDER_PT_render.append(draw_device)
1050     bpy.types.VIEW3D_HT_header.append(draw_pause)
1051
1052     for panel in get_panels():
1053         panel.COMPAT_ENGINES.add('CYCLES')
1054
1055
1056 def unregister():
1057     bpy.types.RENDER_PT_render.remove(draw_device)
1058     bpy.types.VIEW3D_HT_header.remove(draw_pause)
1059
1060     for panel in get_panels():
1061         panel.COMPAT_ENGINES.remove('CYCLES')