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