Cycles: change preview "resolution divider" that gave the number of lower
[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
441 class CyclesObject_PT_ray_visibility(CyclesButtonsPanel, Panel):
442     bl_label = "Ray Visibility"
443     bl_context = "object"
444     bl_options = {'DEFAULT_CLOSED'}
445
446     @classmethod
447     def poll(cls, context):
448         ob = context.object
449         return CyclesButtonsPanel.poll(context) and ob and ob.type in {'MESH', 'CURVE', 'CURVE', 'SURFACE', 'FONT', 'META'}  # todo: 'LAMP'
450
451     def draw(self, context):
452         layout = self.layout
453
454         ob = context.object
455         visibility = ob.cycles_visibility
456
457         flow = layout.column_flow()
458
459         flow.prop(visibility, "camera")
460         flow.prop(visibility, "diffuse")
461         flow.prop(visibility, "glossy")
462         flow.prop(visibility, "transmission")
463         flow.prop(visibility, "shadow")
464
465
466 def find_node(material, nodetype):
467     if material and material.node_tree:
468         ntree = material.node_tree
469
470         for node in ntree.nodes:
471             if getattr(node, "type", None) == nodetype:
472                 return node
473
474     return None
475
476
477 def find_node_input(node, name):
478     for input in node.inputs:
479         if input.name == name:
480             return input
481
482     return None
483
484
485 def panel_node_draw(layout, id_data, output_type, input_name):
486     if not id_data.use_nodes:
487         layout.prop(id_data, "use_nodes", icon='NODETREE')
488         return False
489
490     ntree = id_data.node_tree
491
492     node = find_node(id_data, output_type)
493     if not node:
494         layout.label(text="No output node.")
495     else:
496         input = find_node_input(node, input_name)
497         layout.template_node_view(ntree, node, input)
498
499     return True
500
501
502 class CyclesLamp_PT_lamp(CyclesButtonsPanel, Panel):
503     bl_label = "Lamp"
504     bl_context = "data"
505
506     @classmethod
507     def poll(cls, context):
508         return context.lamp and CyclesButtonsPanel.poll(context)
509
510     def draw(self, context):
511         layout = self.layout
512
513         lamp = context.lamp
514         clamp = lamp.cycles
515         cscene = context.scene.cycles
516
517         layout.prop(lamp, "type", expand=True)
518
519         split = layout.split()
520         col = split.column(align=True)
521
522         if lamp.type in {'POINT', 'SUN', 'SPOT'}:
523             col.prop(lamp, "shadow_soft_size", text="Size")
524         elif lamp.type == 'AREA':
525             col.prop(lamp, "shape", text="")
526             sub = col.column(align=True)
527
528             if lamp.shape == 'SQUARE':
529                 sub.prop(lamp, "size")
530             elif lamp.shape == 'RECTANGLE':
531                 sub.prop(lamp, "size", text="Size X")
532                 sub.prop(lamp, "size_y", text="Size Y")
533
534         if not cscene.progressive and cscene.device == 'CPU':
535             col.prop(clamp, "samples")
536
537         col = split.column()
538         col.prop(clamp, "cast_shadow")
539
540         if lamp.type == 'HEMI':
541             layout.label(text="Not supported, interpreted as sun lamp.")
542
543
544 class CyclesLamp_PT_nodes(CyclesButtonsPanel, Panel):
545     bl_label = "Nodes"
546     bl_context = "data"
547
548     @classmethod
549     def poll(cls, context):
550         return context.lamp and CyclesButtonsPanel.poll(context)
551
552     def draw(self, context):
553         layout = self.layout
554
555         lamp = context.lamp
556         if not panel_node_draw(layout, lamp, 'OUTPUT_LAMP', 'Surface'):
557             layout.prop(lamp, "color")
558
559
560 class CyclesLamp_PT_spot(CyclesButtonsPanel, Panel):
561     bl_label = "Spot Shape"
562     bl_context = "data"
563
564     @classmethod
565     def poll(cls, context):
566         lamp = context.lamp
567         return (lamp and lamp.type == 'SPOT') and CyclesButtonsPanel.poll(context)
568
569     def draw(self, context):
570         layout = self.layout
571
572         lamp = context.lamp
573
574         split = layout.split()
575
576         col = split.column()
577         sub = col.column()
578         sub.prop(lamp, "spot_size", text="Size")
579         sub.prop(lamp, "spot_blend", text="Blend", slider=True)
580
581         col = split.column()
582         col.prop(lamp, "show_cone")
583
584
585 class CyclesWorld_PT_surface(CyclesButtonsPanel, Panel):
586     bl_label = "Surface"
587     bl_context = "world"
588
589     @classmethod
590     def poll(cls, context):
591         return context.world and CyclesButtonsPanel.poll(context)
592
593     def draw(self, context):
594         layout = self.layout
595
596         world = context.world
597
598         if not panel_node_draw(layout, world, 'OUTPUT_WORLD', 'Surface'):
599             layout.prop(world, "horizon_color", text="Color")
600
601
602 class CyclesWorld_PT_volume(CyclesButtonsPanel, Panel):
603     bl_label = "Volume"
604     bl_context = "world"
605     bl_options = {'DEFAULT_CLOSED'}
606
607     @classmethod
608     def poll(cls, context):
609         # world = context.world
610         # world and world.node_tree and CyclesButtonsPanel.poll(context)
611         return False
612
613     def draw(self, context):
614         layout = self.layout
615         layout.active = False
616
617         world = context.world
618         panel_node_draw(layout, world, 'OUTPUT_WORLD', 'Volume')
619
620
621 class CyclesWorld_PT_ambient_occlusion(CyclesButtonsPanel, Panel):
622     bl_label = "Ambient Occlusion"
623     bl_context = "world"
624
625     @classmethod
626     def poll(cls, context):
627         return context.world and CyclesButtonsPanel.poll(context)
628
629     def draw_header(self, context):
630         light = context.world.light_settings
631         self.layout.prop(light, "use_ambient_occlusion", text="")
632
633     def draw(self, context):
634         layout = self.layout
635         light = context.world.light_settings
636
637         layout.active = light.use_ambient_occlusion
638
639         row = layout.row()
640         row.prop(light, "ao_factor", text="Factor")
641         row.prop(light, "distance", text="Distance")
642
643
644 class CyclesWorld_PT_settings(CyclesButtonsPanel, Panel):
645     bl_label = "Settings"
646     bl_context = "world"
647     bl_options = {'DEFAULT_CLOSED'}
648
649     @classmethod
650     def poll(cls, context):
651         return context.world and CyclesButtonsPanel.poll(context)
652
653     def draw(self, context):
654         layout = self.layout
655
656         world = context.world
657         cworld = world.cycles
658         cscene = context.scene.cycles
659
660         col = layout.column()
661
662         col.prop(cworld, "sample_as_light")
663         sub = col.row(align=True)
664         sub.active = cworld.sample_as_light
665         sub.prop(cworld, "sample_map_resolution")
666         if not cscene.progressive and cscene.device == 'CPU':
667             sub.prop(cworld, "samples")
668
669
670 class CyclesMaterial_PT_surface(CyclesButtonsPanel, Panel):
671     bl_label = "Surface"
672     bl_context = "material"
673
674     @classmethod
675     def poll(cls, context):
676         return context.material and CyclesButtonsPanel.poll(context)
677
678     def draw(self, context):
679         layout = self.layout
680
681         mat = context.material
682         if not panel_node_draw(layout, mat, 'OUTPUT_MATERIAL', 'Surface'):
683             layout.prop(mat, "diffuse_color")
684
685
686 class CyclesMaterial_PT_volume(CyclesButtonsPanel, Panel):
687     bl_label = "Volume"
688     bl_context = "material"
689     bl_options = {'DEFAULT_CLOSED'}
690
691     @classmethod
692     def poll(cls, context):
693         # mat = context.material
694         # mat and mat.node_tree and CyclesButtonsPanel.poll(context)
695         return False
696
697     def draw(self, context):
698         layout = self.layout
699         layout.active = False
700
701         mat = context.material
702         cmat = mat.cycles
703
704         panel_node_draw(layout, mat, 'OUTPUT_MATERIAL', 'Volume')
705
706         layout.prop(cmat, "homogeneous_volume")
707
708
709 class CyclesMaterial_PT_displacement(CyclesButtonsPanel, Panel):
710     bl_label = "Displacement"
711     bl_context = "material"
712
713     @classmethod
714     def poll(cls, context):
715         mat = context.material
716         return mat and mat.node_tree and CyclesButtonsPanel.poll(context)
717
718     def draw(self, context):
719         layout = self.layout
720
721         mat = context.material
722         panel_node_draw(layout, mat, 'OUTPUT_MATERIAL', 'Displacement')
723
724
725 class CyclesMaterial_PT_settings(CyclesButtonsPanel, Panel):
726     bl_label = "Settings"
727     bl_context = "material"
728     bl_options = {'DEFAULT_CLOSED'}
729
730     @classmethod
731     def poll(cls, context):
732         return context.material and CyclesButtonsPanel.poll(context)
733
734     def draw(self, context):
735         layout = self.layout
736
737         mat = context.material
738         cmat = mat.cycles
739
740         split = layout.split()
741
742         col = split.column()
743         col.prop(mat, "diffuse_color", text="Viewport Color")
744
745         col = split.column()
746         col.prop(cmat, "sample_as_light")
747         col.prop(mat, "pass_index")
748
749
750 class CyclesTexture_PT_context(CyclesButtonsPanel, Panel):
751     bl_label = ""
752     bl_context = "texture"
753     bl_options = {'HIDE_HEADER'}
754     COMPAT_ENGINES = {'CYCLES'}
755
756     def draw(self, context):
757         layout = self.layout
758
759         tex = context.texture
760         space = context.space_data
761         pin_id = space.pin_id
762         use_pin_id = space.use_pin_id
763         user = context.texture_user
764
765         if not use_pin_id or not isinstance(pin_id, bpy.types.Texture):
766             pin_id = None
767
768         if not pin_id:
769             layout.template_texture_user()
770
771         if user:
772             layout.separator()
773
774             split = layout.split(percentage=0.65)
775             col = split.column()
776
777             if pin_id:
778                 col.template_ID(space, "pin_id")
779             elif user:
780                 col.template_ID(user, "texture", new="texture.new")
781
782             if tex:
783                 split = layout.split(percentage=0.2)
784                 split.label(text="Type:")
785                 split.prop(tex, "type", text="")
786
787
788 class CyclesTexture_PT_nodes(CyclesButtonsPanel, Panel):
789     bl_label = "Nodes"
790     bl_context = "texture"
791
792     @classmethod
793     def poll(cls, context):
794         tex = context.texture
795         return (tex and tex.use_nodes) and CyclesButtonsPanel.poll(context)
796
797     def draw(self, context):
798         layout = self.layout
799
800         tex = context.texture
801         panel_node_draw(layout, tex, 'OUTPUT_TEXTURE', 'Color')
802
803
804 class CyclesTexture_PT_node(CyclesButtonsPanel, Panel):
805     bl_label = "Node"
806     bl_context = "texture"
807
808     @classmethod
809     def poll(cls, context):
810         node = context.texture_node
811         return node and CyclesButtonsPanel.poll(context)
812
813     def draw(self, context):
814         layout = self.layout
815
816         node = context.texture_node
817         ntree = node.id_data
818         layout.template_node_view(ntree, node, None)
819
820
821 class CyclesTexture_PT_mapping(CyclesButtonsPanel, Panel):
822     bl_label = "Mapping"
823     bl_context = "texture"
824
825     @classmethod
826     def poll(cls, context):
827         tex = context.texture
828         node = context.texture_node
829         return (node or (tex and tex.use_nodes)) and CyclesButtonsPanel.poll(context)
830
831     def draw(self, context):
832         layout = self.layout
833
834         # tex = context.texture
835         node = context.texture_node
836
837         mapping = node.texture_mapping
838
839         row = layout.row()
840
841         row.column().prop(mapping, "translation")
842         row.column().prop(mapping, "rotation")
843         row.column().prop(mapping, "scale")
844
845         layout.label(text="Projection:")
846
847         row = layout.row()
848         row.prop(mapping, "mapping_x", text="")
849         row.prop(mapping, "mapping_y", text="")
850         row.prop(mapping, "mapping_z", text="")
851
852
853 class CyclesTexture_PT_colors(CyclesButtonsPanel, Panel):
854     bl_label = "Color"
855     bl_context = "texture"
856     bl_options = {'DEFAULT_CLOSED'}
857
858     @classmethod
859     def poll(cls, context):
860         # tex = context.texture
861         # node = context.texture_node
862         return False
863         #return (node or (tex and tex.use_nodes)) and CyclesButtonsPanel.poll(context)
864
865     def draw(self, context):
866         layout = self.layout
867
868         # tex = context.texture
869         node = context.texture_node
870
871         mapping = node.color_mapping
872
873         split = layout.split()
874
875         col = split.column()
876         col.label(text="Blend:")
877         col.prop(mapping, "blend_type", text="")
878         col.prop(mapping, "blend_factor", text="Factor")
879         col.prop(mapping, "blend_color", text="")
880
881         col = split.column()
882         col.label(text="Adjust:")
883         col.prop(mapping, "brightness")
884         col.prop(mapping, "contrast")
885         col.prop(mapping, "saturation")
886
887         layout.separator()
888
889         layout.prop(mapping, "use_color_ramp", text="Ramp")
890         if mapping.use_color_ramp:
891             layout.template_color_ramp(mapping, "color_ramp", expand=True)
892
893
894 class CyclesScene_PT_simplify(CyclesButtonsPanel, Panel):
895     bl_label = "Simplify"
896     bl_context = "scene"
897     COMPAT_ENGINES = {'CYCLES'}
898
899     def draw_header(self, context):
900         rd = context.scene.render
901         self.layout.prop(rd, "use_simplify", text="")
902
903     def draw(self, context):
904         layout = self.layout
905
906         rd = context.scene.render
907
908         layout.active = rd.use_simplify
909
910         split = layout.split()
911
912         col = split.column()
913         col.prop(rd, "simplify_subdivision", text="Subdivision")
914
915         col = split.column()
916         col.prop(rd, "simplify_child_particles", text="Child Particles")
917
918
919 def draw_device(self, context):
920     scene = context.scene
921     layout = self.layout
922
923     if scene.render.engine == 'CYCLES':
924         cscene = scene.cycles
925
926         layout.prop(cscene, "feature_set")
927
928         device_type = context.user_preferences.system.compute_device_type
929         if device_type == 'CUDA':
930             layout.prop(cscene, "device")
931         elif device_type == 'OPENCL' and cscene.feature_set == 'EXPERIMENTAL':
932             layout.prop(cscene, "device")
933             
934         if cscene.feature_set == 'EXPERIMENTAL' and cscene.device == 'CPU' and engine.with_osl():
935             layout.prop(cscene, "shading_system")
936
937
938 def draw_pause(self, context):
939     layout = self.layout
940     scene = context.scene
941
942     if scene.render.engine == "CYCLES":
943         view = context.space_data
944
945         if view.viewport_shade == 'RENDERED':
946             cscene = scene.cycles
947             layername = scene.render.layers.active.name
948             layout.prop(cscene, "preview_pause", icon="PAUSE", text="")
949             layout.prop(cscene, "preview_active_layer", icon="RENDERLAYERS", text=layername)
950
951
952 def get_panels():
953     return (
954         bpy.types.RENDER_PT_render,
955         bpy.types.RENDER_PT_output,
956         bpy.types.RENDER_PT_encoding,
957         bpy.types.RENDER_PT_dimensions,
958         bpy.types.RENDER_PT_stamp,
959         bpy.types.SCENE_PT_scene,
960         bpy.types.SCENE_PT_audio,
961         bpy.types.SCENE_PT_unit,
962         bpy.types.SCENE_PT_keying_sets,
963         bpy.types.SCENE_PT_keying_set_paths,
964         bpy.types.SCENE_PT_physics,
965         bpy.types.WORLD_PT_context_world,
966         bpy.types.DATA_PT_context_mesh,
967         bpy.types.DATA_PT_context_camera,
968         bpy.types.DATA_PT_context_lamp,
969         bpy.types.DATA_PT_texture_space,
970         bpy.types.DATA_PT_curve_texture_space,
971         bpy.types.DATA_PT_mball_texture_space,
972         bpy.types.DATA_PT_vertex_groups,
973         bpy.types.DATA_PT_shape_keys,
974         bpy.types.DATA_PT_uv_texture,
975         bpy.types.DATA_PT_vertex_colors,
976         bpy.types.DATA_PT_camera,
977         bpy.types.DATA_PT_camera_display,
978         bpy.types.DATA_PT_lens,
979         bpy.types.DATA_PT_custom_props_mesh,
980         bpy.types.DATA_PT_custom_props_camera,
981         bpy.types.DATA_PT_custom_props_lamp,
982         bpy.types.TEXTURE_PT_clouds,
983         bpy.types.TEXTURE_PT_wood,
984         bpy.types.TEXTURE_PT_marble,
985         bpy.types.TEXTURE_PT_magic,
986         bpy.types.TEXTURE_PT_blend,
987         bpy.types.TEXTURE_PT_stucci,
988         bpy.types.TEXTURE_PT_image,
989         bpy.types.TEXTURE_PT_image_sampling,
990         bpy.types.TEXTURE_PT_image_mapping,
991         bpy.types.TEXTURE_PT_musgrave,
992         bpy.types.TEXTURE_PT_voronoi,
993         bpy.types.TEXTURE_PT_distortednoise,
994         bpy.types.TEXTURE_PT_voxeldata,
995         bpy.types.TEXTURE_PT_pointdensity,
996         bpy.types.TEXTURE_PT_pointdensity_turbulence,
997         bpy.types.PARTICLE_PT_context_particles,
998         bpy.types.PARTICLE_PT_emission,
999         bpy.types.PARTICLE_PT_hair_dynamics,
1000         bpy.types.PARTICLE_PT_cache,
1001         bpy.types.PARTICLE_PT_velocity,
1002         bpy.types.PARTICLE_PT_rotation,
1003         bpy.types.PARTICLE_PT_physics,
1004         bpy.types.PARTICLE_PT_boidbrain,
1005         bpy.types.PARTICLE_PT_render,
1006         bpy.types.PARTICLE_PT_draw,
1007         bpy.types.PARTICLE_PT_children,
1008         bpy.types.PARTICLE_PT_field_weights,
1009         bpy.types.PARTICLE_PT_force_fields,
1010         bpy.types.PARTICLE_PT_vertexgroups,
1011         bpy.types.PARTICLE_PT_custom_props,
1012         )
1013
1014
1015 def register():
1016     bpy.types.RENDER_PT_render.append(draw_device)
1017     bpy.types.VIEW3D_HT_header.append(draw_pause)
1018
1019     for panel in get_panels():
1020         panel.COMPAT_ENGINES.add('CYCLES')
1021
1022
1023 def unregister():
1024     bpy.types.RENDER_PT_render.remove(draw_device)
1025     bpy.types.VIEW3D_HT_header.remove(draw_pause)
1026
1027     for panel in get_panels():
1028         panel.COMPAT_ENGINES.remove('CYCLES')