533d79d520daa7c5d6da97994cf41306ebaf34d1
[blender.git] / intern / cycles / blender / addon / ui.py
1 #
2 # Copyright 2011-2013 Blender Foundation
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License
15 #
16
17 # <pep8 compliant>
18
19 import bpy
20
21 from bpy.types import Panel, Menu, Operator
22
23
24 class CYCLES_MT_sampling_presets(Menu):
25     bl_label = "Sampling Presets"
26     preset_subdir = "cycles/sampling"
27     preset_operator = "script.execute_preset"
28     COMPAT_ENGINES = {'CYCLES'}
29     draw = Menu.draw_preset
30
31
32 class CYCLES_MT_integrator_presets(Menu):
33     bl_label = "Integrator Presets"
34     preset_subdir = "cycles/integrator"
35     preset_operator = "script.execute_preset"
36     COMPAT_ENGINES = {'CYCLES'}
37     draw = Menu.draw_preset
38
39
40 class CyclesButtonsPanel():
41     bl_space_type = "PROPERTIES"
42     bl_region_type = "WINDOW"
43     bl_context = "render"
44
45     @classmethod
46     def poll(cls, context):
47         rd = context.scene.render
48         return rd.engine == 'CYCLES'
49
50
51 class CyclesRender_PT_sampling(CyclesButtonsPanel, Panel):
52     bl_label = "Sampling"
53     bl_options = {'DEFAULT_CLOSED'}
54
55     def draw(self, context):
56         layout = self.layout
57
58         scene = context.scene
59         cscene = scene.cycles
60         device_type = context.user_preferences.system.compute_device_type
61         
62         row = layout.row(align=True)
63         row.menu("CYCLES_MT_sampling_presets", text=bpy.types.CYCLES_MT_sampling_presets.bl_label)
64         row.operator("render.cycles_sampling_preset_add", text="", icon="ZOOMIN")
65         row.operator("render.cycles_sampling_preset_add", text="", icon="ZOOMOUT").remove_active = True
66
67         row = layout.row()
68         row.prop(cscene, "progressive")
69         
70         if not cscene.progressive:
71             row.prop(cscene, "squared_samples")
72         
73         split = layout.split()
74         
75         col = split.column()
76         sub = col.column(align=True)
77         sub.label("Settings:")
78         sub.prop(cscene, "seed")
79         sub.prop(cscene, "sample_clamp")
80
81         if cscene.progressive:
82             col = split.column()
83             sub = col.column(align=True)
84             sub.label(text="Samples:")
85             sub.prop(cscene, "samples", text="Render")
86             sub.prop(cscene, "preview_samples", text="Preview")
87         else:
88             sub.label(text="AA Samples:")
89             sub.prop(cscene, "aa_samples", text="Render")
90             sub.prop(cscene, "preview_aa_samples", text="Preview")
91
92             col = split.column()
93             sub = col.column(align=True)
94             sub.label(text="Samples:")
95             sub.prop(cscene, "diffuse_samples", text="Diffuse")
96             sub.prop(cscene, "glossy_samples", text="Glossy")
97             sub.prop(cscene, "transmission_samples", text="Transmission")
98             sub.prop(cscene, "ao_samples", text="AO")
99             sub.prop(cscene, "mesh_light_samples", text="Mesh Light")
100             sub.prop(cscene, "subsurface_samples", text="Subsurface")
101
102         if cscene.feature_set == 'EXPERIMENTAL' and (device_type == 'NONE' or cscene.device == 'CPU'):
103             layout.row().prop(cscene, "sampling_pattern", text="Pattern")
104
105         for rl in scene.render.layers:
106             if rl.samples > 0:
107                 layout.separator()
108                 layout.row().prop(cscene, "use_layer_samples")
109                 break
110
111
112 class CyclesRender_PT_light_paths(CyclesButtonsPanel, Panel):
113     bl_label = "Light Paths"
114     bl_options = {'DEFAULT_CLOSED'}
115
116     def draw(self, context):
117         layout = self.layout
118
119         scene = context.scene
120         cscene = scene.cycles
121
122         row = layout.row(align=True)
123         row.menu("CYCLES_MT_integrator_presets", text=bpy.types.CYCLES_MT_integrator_presets.bl_label)
124         row.operator("render.cycles_integrator_preset_add", text="", icon="ZOOMIN")
125         row.operator("render.cycles_integrator_preset_add", text="", icon="ZOOMOUT").remove_active = True
126
127         split = layout.split()
128
129         col = split.column()
130
131         sub = col.column(align=True)
132         sub.label("Transparency:")
133         sub.prop(cscene, "transparent_max_bounces", text="Max")
134         sub.prop(cscene, "transparent_min_bounces", text="Min")
135         sub.prop(cscene, "use_transparent_shadows", text="Shadows")
136
137         col.separator()
138
139         col.prop(cscene, "no_caustics")
140         col.prop(cscene, "blur_glossy")
141
142         col = split.column()
143
144         sub = col.column(align=True)
145         sub.label(text="Bounces:")
146         sub.prop(cscene, "max_bounces", text="Max")
147         sub.prop(cscene, "min_bounces", text="Min")
148
149         sub = col.column(align=True)
150         sub.prop(cscene, "diffuse_bounces", text="Diffuse")
151         sub.prop(cscene, "glossy_bounces", text="Glossy")
152         sub.prop(cscene, "transmission_bounces", text="Transmission")
153
154
155 class CyclesRender_PT_motion_blur(CyclesButtonsPanel, Panel):
156     bl_label = "Motion Blur"
157     bl_options = {'DEFAULT_CLOSED'}
158
159     def draw_header(self, context):
160         rd = context.scene.render
161
162         self.layout.prop(rd, "use_motion_blur", text="")
163
164     def draw(self, context):
165         layout = self.layout
166
167         rd = context.scene.render
168         layout.active = rd.use_motion_blur
169
170         row = layout.row()
171         row.prop(rd, "motion_blur_shutter")
172
173
174 class CyclesRender_PT_film(CyclesButtonsPanel, Panel):
175     bl_label = "Film"
176
177     def draw(self, context):
178         layout = self.layout
179
180         scene = context.scene
181         cscene = scene.cycles
182
183         split = layout.split()
184
185         col = split.column()
186         col.prop(cscene, "film_exposure")
187         col.prop(cscene, "film_transparent")
188
189         col = split.column()
190         sub = col.column(align=True)
191         sub.prop(cscene, "filter_type", text="")
192         if cscene.filter_type != 'BOX':
193             sub.prop(cscene, "filter_width", text="Width")
194
195
196 class CyclesRender_PT_performance(CyclesButtonsPanel, Panel):
197     bl_label = "Performance"
198     bl_options = {'DEFAULT_CLOSED'}
199
200     def draw(self, context):
201         layout = self.layout
202
203         scene = context.scene
204         rd = scene.render
205         cscene = scene.cycles
206
207         split = layout.split()
208
209         col = split.column(align=True)
210
211         col.label(text="Threads:")
212         col.row().prop(rd, "threads_mode", expand=True)
213         sub = col.column()
214         sub.enabled = rd.threads_mode == 'FIXED'
215         sub.prop(rd, "threads")
216
217         sub = col.column(align=True)
218         sub.label(text="Tiles:")
219         sub.prop(cscene, "tile_order", text="")
220
221         sub.prop(rd, "tile_x", text="X")
222         sub.prop(rd, "tile_y", text="Y")
223
224         sub.prop(cscene, "use_progressive_refine")
225
226         subsub = sub.column()
227         subsub.enabled = not rd.use_border
228         subsub.prop(rd, "use_save_buffers")
229
230         col = split.column(align=True)
231
232         col.label(text="Viewport:")
233         col.prop(cscene, "debug_bvh_type", text="")
234         col.separator()
235         col.prop(cscene, "preview_start_resolution")
236
237         col.separator()
238
239         col.label(text="Final Render:")
240         col.prop(cscene, "use_cache")
241         col.prop(rd, "use_persistent_data", text="Persistent Images")
242
243         col.separator()
244
245         col.label(text="Acceleration structure:")   
246         col.prop(cscene, "debug_use_spatial_splits")
247
248
249 class CyclesRender_PT_opengl(CyclesButtonsPanel, Panel):
250     bl_label = "OpenGL Render"
251     bl_options = {'DEFAULT_CLOSED'}
252
253     def draw(self, context):
254         layout = self.layout
255
256         rd = context.scene.render
257
258         split = layout.split()
259
260         col = split.column()
261         col.prop(rd, "use_antialiasing")
262         sub = col.row()
263         sub.active = rd.use_antialiasing
264         sub.prop(rd, "antialiasing_samples", expand=True)
265
266         col = split.column()
267         col.label(text="Alpha:")
268         col.prop(rd, "alpha_mode", text="")
269
270
271 class CyclesRender_PT_layers(CyclesButtonsPanel, Panel):
272     bl_label = "Layer List"
273     bl_context = "render_layer"
274     bl_options = {'HIDE_HEADER'}
275
276     def draw(self, context):
277         layout = self.layout
278
279         scene = context.scene
280         rd = scene.render
281         rl = rd.layers.active
282
283         row = layout.row()
284         row.template_list("RENDERLAYER_UL_renderlayers", "", rd, "layers", rd.layers, "active_index", rows=2)
285
286         col = row.column(align=True)
287         col.operator("scene.render_layer_add", icon='ZOOMIN', text="")
288         col.operator("scene.render_layer_remove", icon='ZOOMOUT', text="")
289
290         row = layout.row()
291         if rl:
292             row.prop(rl, "name")
293         row.prop(rd, "use_single_layer", text="", icon_only=True)
294
295
296 class CyclesRender_PT_layer_options(CyclesButtonsPanel, Panel):
297     bl_label = "Layer"
298     bl_context = "render_layer"
299
300     def draw(self, context):
301         layout = self.layout
302
303         scene = context.scene
304         rd = scene.render
305         rl = rd.layers.active
306
307         split = layout.split()
308
309         col = split.column()
310         col.prop(scene, "layers", text="Scene")
311         col.prop(rl, "layers_exclude", text="Exclude")
312
313         col = split.column()
314         col.prop(rl, "layers", text="Layer")
315         col.prop(rl, "layers_zmask", text="Mask Layer")
316
317         split = layout.split()
318
319         col = split.column()
320         col.label(text="Material:")
321         col.prop(rl, "material_override", text="")
322         col.separator()
323         col.prop(rl, "samples")
324
325         col = split.column()
326         col.prop(rl, "use_sky", "Use Environment")
327         col.prop(rl, "use_solid", "Use Surfaces")
328         col.prop(rl, "use_strand", "Use Hair")
329
330
331 class CyclesRender_PT_layer_passes(CyclesButtonsPanel, Panel):
332     bl_label = "Passes"
333     bl_context = "render_layer"
334     bl_options = {'DEFAULT_CLOSED'}
335
336     def draw(self, context):
337         layout = self.layout
338
339         scene = context.scene
340         rd = scene.render
341         rl = rd.layers.active
342
343         split = layout.split()
344
345         col = split.column()
346         col.prop(rl, "use_pass_combined")
347         col.prop(rl, "use_pass_z")
348         col.prop(rl, "use_pass_mist")
349         col.prop(rl, "use_pass_normal")
350         col.prop(rl, "use_pass_vector")
351         col.prop(rl, "use_pass_uv")
352         col.prop(rl, "use_pass_object_index")
353         col.prop(rl, "use_pass_material_index")
354         col.separator()
355         col.prop(rl, "use_pass_shadow")
356         col.prop(rl, "use_pass_ambient_occlusion")
357
358         col = split.column()
359         col.label(text="Diffuse:")
360         row = col.row(align=True)
361         row.prop(rl, "use_pass_diffuse_direct", text="Direct", toggle=True)
362         row.prop(rl, "use_pass_diffuse_indirect", text="Indirect", toggle=True)
363         row.prop(rl, "use_pass_diffuse_color", text="Color", toggle=True)
364         col.label(text="Glossy:")
365         row = col.row(align=True)
366         row.prop(rl, "use_pass_glossy_direct", text="Direct", toggle=True)
367         row.prop(rl, "use_pass_glossy_indirect", text="Indirect", toggle=True)
368         row.prop(rl, "use_pass_glossy_color", text="Color", toggle=True)
369         col.label(text="Transmission:")
370         row = col.row(align=True)
371         row.prop(rl, "use_pass_transmission_direct", text="Direct", toggle=True)
372         row.prop(rl, "use_pass_transmission_indirect", text="Indirect", toggle=True)
373         row.prop(rl, "use_pass_transmission_color", text="Color", toggle=True)
374         col.label(text="Subsurface:")
375         row = col.row(align=True)
376         row.prop(rl, "use_pass_subsurface_direct", text="Direct", toggle=True)
377         row.prop(rl, "use_pass_subsurface_indirect", text="Indirect", toggle=True)
378         row.prop(rl, "use_pass_subsurface_color", text="Color", toggle=True)
379         
380         col.separator()
381         col.prop(rl, "use_pass_emit", text="Emission")
382         col.prop(rl, "use_pass_environment")
383
384
385 class Cycles_PT_post_processing(CyclesButtonsPanel, Panel):
386     bl_label = "Post Processing"
387     bl_options = {'DEFAULT_CLOSED'}
388
389     def draw(self, context):
390         layout = self.layout
391
392         rd = context.scene.render
393
394         split = layout.split()
395
396         col = split.column()
397         col.prop(rd, "use_compositing")
398         col.prop(rd, "use_sequencer")
399
400         col = split.column()
401         col.prop(rd, "dither_intensity", text="Dither", slider=True)
402
403
404 class CyclesCamera_PT_dof(CyclesButtonsPanel, Panel):
405     bl_label = "Depth of Field"
406     bl_context = "data"
407
408     @classmethod
409     def poll(cls, context):
410         return context.camera and CyclesButtonsPanel.poll(context)
411
412     def draw(self, context):
413         layout = self.layout
414
415         cam = context.camera
416         ccam = cam.cycles
417
418         split = layout.split()
419
420         col = split.column()
421         col.label("Focus:")
422         col.prop(cam, "dof_object", text="")
423
424         sub = col.row()
425         sub.active = cam.dof_object is None
426         sub.prop(cam, "dof_distance", text="Distance")
427
428         col = split.column()
429
430         col.label("Aperture:")
431         sub = col.column(align=True)
432         sub.prop(ccam, "aperture_type", text="")
433         if ccam.aperture_type == 'RADIUS':
434             sub.prop(ccam, "aperture_size", text="Size")
435         elif ccam.aperture_type == 'FSTOP':
436             sub.prop(ccam, "aperture_fstop", text="Number")
437
438         sub = col.column(align=True)
439         sub.prop(ccam, "aperture_blades", text="Blades")
440         sub.prop(ccam, "aperture_rotation", text="Rotation")
441
442
443 class Cycles_PT_context_material(CyclesButtonsPanel, Panel):
444     bl_label = ""
445     bl_context = "material"
446     bl_options = {'HIDE_HEADER'}
447
448     @classmethod
449     def poll(cls, context):
450         return (context.material or context.object) and CyclesButtonsPanel.poll(context)
451
452     def draw(self, context):
453         layout = self.layout
454
455         mat = context.material
456         ob = context.object
457         slot = context.material_slot
458         space = context.space_data
459
460         if ob:
461             row = layout.row()
462
463             row.template_list("MATERIAL_UL_matslots", "", ob, "material_slots", ob, "active_material_index", rows=2)
464
465             col = row.column(align=True)
466             col.operator("object.material_slot_add", icon='ZOOMIN', text="")
467             col.operator("object.material_slot_remove", icon='ZOOMOUT', text="")
468
469             col.menu("MATERIAL_MT_specials", icon='DOWNARROW_HLT', text="")
470
471             if ob.mode == 'EDIT':
472                 row = layout.row(align=True)
473                 row.operator("object.material_slot_assign", text="Assign")
474                 row.operator("object.material_slot_select", text="Select")
475                 row.operator("object.material_slot_deselect", text="Deselect")
476
477         split = layout.split(percentage=0.65)
478
479         if ob:
480             split.template_ID(ob, "active_material", new="material.new")
481             row = split.row()
482
483             if slot:
484                 row.prop(slot, "link", text="")
485             else:
486                 row.label()
487         elif mat:
488             split.template_ID(space, "pin_id")
489             split.separator()
490
491
492 class Cycles_PT_mesh_displacement(CyclesButtonsPanel, Panel):
493     bl_label = "Displacement"
494     bl_context = "data"
495
496     @classmethod
497     def poll(cls, context):
498         if CyclesButtonsPanel.poll(context):
499             if context.mesh or context.curve or context.meta_ball:
500                 if context.scene.cycles.feature_set == 'EXPERIMENTAL':
501                     return True
502
503         return False
504
505     def draw(self, context):
506         layout = self.layout
507
508         mesh = context.mesh
509         curve = context.curve
510         mball = context.meta_ball
511
512         if mesh:
513             cdata = mesh.cycles
514         elif curve:
515             cdata = curve.cycles
516         elif mball:
517             cdata = mball.cycles
518
519         layout.prop(cdata, "displacement_method", text="Method")
520         layout.prop(cdata, "use_subdivision")
521         layout.prop(cdata, "dicing_rate")
522
523
524 class Cycles_PT_mesh_normals(CyclesButtonsPanel, Panel):
525     bl_label = "Normals"
526     bl_context = "data"
527
528     @classmethod
529     def poll(cls, context):
530         return CyclesButtonsPanel.poll(context) and context.mesh
531
532     def draw(self, context):
533         layout = self.layout
534
535         mesh = context.mesh
536
537         split = layout.split()
538
539         col = split.column()
540         col.prop(mesh, "show_double_sided")
541
542         col = split.column()
543         col.label()
544
545
546 class CyclesObject_PT_ray_visibility(CyclesButtonsPanel, Panel):
547     bl_label = "Ray Visibility"
548     bl_context = "object"
549     bl_options = {'DEFAULT_CLOSED'}
550
551     @classmethod
552     def poll(cls, context):
553         ob = context.object
554         return CyclesButtonsPanel.poll(context) and ob and ob.type in {'MESH', 'CURVE', 'CURVE', 'SURFACE', 'FONT', 'META', 'LAMP'}
555
556     def draw(self, context):
557         layout = self.layout
558
559         ob = context.object
560         visibility = ob.cycles_visibility
561
562         flow = layout.column_flow()
563
564         flow.prop(visibility, "camera")
565         flow.prop(visibility, "diffuse")
566         flow.prop(visibility, "glossy")
567         flow.prop(visibility, "transmission")
568
569         if ob.type != 'LAMP':
570             flow.prop(visibility, "shadow")
571
572
573 class CYCLES_OT_use_shading_nodes(Operator):
574     """Enable nodes on a material, world or lamp"""
575     bl_idname = "cycles.use_shading_nodes"
576     bl_label = "Use Nodes"
577
578     @classmethod
579     def poll(cls, context):
580         return context.material or context.world or context.lamp
581
582     def execute(self, context):
583         if context.material:
584             context.material.use_nodes = True
585         elif context.world:
586             context.world.use_nodes = True
587         elif context.lamp:
588             context.lamp.use_nodes = True
589
590         return {'FINISHED'}
591
592
593 def find_node(material, nodetype):
594     if material and material.node_tree:
595         ntree = material.node_tree
596
597         for node in ntree.nodes:
598             if getattr(node, "type", None) == nodetype:
599                 return node
600
601     return None
602
603
604 def find_node_input(node, name):
605     for input in node.inputs:
606         if input.name == name:
607             return input
608
609     return None
610
611
612 def panel_node_draw(layout, id_data, output_type, input_name):
613     if not id_data.use_nodes:
614         layout.operator("cycles.use_shading_nodes", icon='NODETREE')
615         return False
616
617     ntree = id_data.node_tree
618
619     node = find_node(id_data, output_type)
620     if not node:
621         layout.label(text="No output node")
622     else:
623         input = find_node_input(node, input_name)
624         layout.template_node_view(ntree, node, input)
625
626     return True
627
628
629 class CyclesLamp_PT_preview(CyclesButtonsPanel, Panel):
630     bl_label = "Preview"
631     bl_context = "data"
632     bl_options = {'DEFAULT_CLOSED'}
633
634     @classmethod
635     def poll(cls, context):
636         return context.lamp and CyclesButtonsPanel.poll(context)
637
638     def draw(self, context):
639         self.layout.template_preview(context.lamp)
640
641
642 class CyclesLamp_PT_lamp(CyclesButtonsPanel, Panel):
643     bl_label = "Lamp"
644     bl_context = "data"
645
646     @classmethod
647     def poll(cls, context):
648         return context.lamp and CyclesButtonsPanel.poll(context)
649
650     def draw(self, context):
651         layout = self.layout
652
653         lamp = context.lamp
654         clamp = lamp.cycles
655         cscene = context.scene.cycles
656
657         layout.prop(lamp, "type", expand=True)
658
659         split = layout.split()
660         col = split.column(align=True)
661
662         if lamp.type in {'POINT', 'SUN', 'SPOT'}:
663             col.prop(lamp, "shadow_soft_size", text="Size")
664         elif lamp.type == 'AREA':
665             col.prop(lamp, "shape", text="")
666             sub = col.column(align=True)
667
668             if lamp.shape == 'SQUARE':
669                 sub.prop(lamp, "size")
670             elif lamp.shape == 'RECTANGLE':
671                 sub.prop(lamp, "size", text="Size X")
672                 sub.prop(lamp, "size_y", text="Size Y")
673
674         if not cscene.progressive:
675             col.prop(clamp, "samples")
676
677         col = split.column()
678         col.prop(clamp, "cast_shadow")
679
680         layout.prop(clamp, "use_multiple_importance_sampling")
681
682         if lamp.type == 'HEMI':
683             layout.label(text="Not supported, interpreted as sun lamp")
684
685
686 class CyclesLamp_PT_nodes(CyclesButtonsPanel, Panel):
687     bl_label = "Nodes"
688     bl_context = "data"
689
690     @classmethod
691     def poll(cls, context):
692         return context.lamp and CyclesButtonsPanel.poll(context)
693
694     def draw(self, context):
695         layout = self.layout
696
697         lamp = context.lamp
698         if not panel_node_draw(layout, lamp, 'OUTPUT_LAMP', 'Surface'):
699             layout.prop(lamp, "color")
700
701
702 class CyclesLamp_PT_spot(CyclesButtonsPanel, Panel):
703     bl_label = "Spot Shape"
704     bl_context = "data"
705
706     @classmethod
707     def poll(cls, context):
708         lamp = context.lamp
709         return (lamp and lamp.type == 'SPOT') and CyclesButtonsPanel.poll(context)
710
711     def draw(self, context):
712         layout = self.layout
713
714         lamp = context.lamp
715
716         split = layout.split()
717
718         col = split.column()
719         sub = col.column()
720         sub.prop(lamp, "spot_size", text="Size")
721         sub.prop(lamp, "spot_blend", text="Blend", slider=True)
722
723         col = split.column()
724         col.prop(lamp, "show_cone")
725
726
727 class CyclesWorld_PT_preview(CyclesButtonsPanel, Panel):
728     bl_label = "Preview"
729     bl_context = "world"
730     bl_options = {'DEFAULT_CLOSED'}
731
732     @classmethod
733     def poll(cls, context):
734         return context.world and CyclesButtonsPanel.poll(context)
735
736     def draw(self, context):
737         self.layout.template_preview(context.world)
738
739
740 class CyclesWorld_PT_surface(CyclesButtonsPanel, Panel):
741     bl_label = "Surface"
742     bl_context = "world"
743
744     @classmethod
745     def poll(cls, context):
746         return context.world and CyclesButtonsPanel.poll(context)
747
748     def draw(self, context):
749         layout = self.layout
750
751         world = context.world
752
753         if not panel_node_draw(layout, world, 'OUTPUT_WORLD', 'Surface'):
754             layout.prop(world, "horizon_color", text="Color")
755
756
757 class CyclesWorld_PT_volume(CyclesButtonsPanel, Panel):
758     bl_label = "Volume"
759     bl_context = "world"
760     bl_options = {'DEFAULT_CLOSED'}
761
762     @classmethod
763     def poll(cls, context):
764         # world = context.world
765         # world and world.node_tree and CyclesButtonsPanel.poll(context)
766         return False
767
768     def draw(self, context):
769         layout = self.layout
770         layout.active = False
771
772         world = context.world
773         panel_node_draw(layout, world, 'OUTPUT_WORLD', 'Volume')
774
775
776 class CyclesWorld_PT_ambient_occlusion(CyclesButtonsPanel, Panel):
777     bl_label = "Ambient Occlusion"
778     bl_context = "world"
779
780     @classmethod
781     def poll(cls, context):
782         return context.world and CyclesButtonsPanel.poll(context)
783
784     def draw_header(self, context):
785         light = context.world.light_settings
786         self.layout.prop(light, "use_ambient_occlusion", text="")
787
788     def draw(self, context):
789         layout = self.layout
790         light = context.world.light_settings
791
792         layout.active = light.use_ambient_occlusion
793
794         row = layout.row()
795         row.prop(light, "ao_factor", text="Factor")
796         row.prop(light, "distance", text="Distance")
797
798
799 class CyclesWorld_PT_mist(CyclesButtonsPanel, Panel):
800     bl_label = "Mist Pass"
801     bl_context = "world"
802     bl_options = {'DEFAULT_CLOSED'}
803
804     @classmethod
805     def poll(cls, context):
806         if CyclesButtonsPanel.poll(context):
807             for rl in context.scene.render.layers:
808                 if rl.use_pass_mist:
809                     return True
810
811         return False
812
813     def draw(self, context):
814         layout = self.layout
815
816         world = context.world
817
818         split = layout.split(align=True)
819         split.prop(world.mist_settings, "start")
820         split.prop(world.mist_settings, "depth")
821
822         layout.prop(world.mist_settings, "falloff")
823
824
825 class CyclesWorld_PT_ray_visibility(CyclesButtonsPanel, Panel):
826     bl_label = "Ray Visibility"
827     bl_context = "world"
828     bl_options = {'DEFAULT_CLOSED'}
829
830     @classmethod
831     def poll(cls, context):
832         return CyclesButtonsPanel.poll(context) and context.world
833
834     def draw(self, context):
835         layout = self.layout
836
837         world = context.world
838         visibility = world.cycles_visibility
839
840         flow = layout.column_flow()
841
842         flow.prop(visibility, "camera")
843         flow.prop(visibility, "diffuse")
844         flow.prop(visibility, "glossy")
845         flow.prop(visibility, "transmission")
846
847
848 class CyclesWorld_PT_settings(CyclesButtonsPanel, Panel):
849     bl_label = "Settings"
850     bl_context = "world"
851     bl_options = {'DEFAULT_CLOSED'}
852
853     @classmethod
854     def poll(cls, context):
855         return context.world and CyclesButtonsPanel.poll(context)
856
857     def draw(self, context):
858         layout = self.layout
859
860         world = context.world
861         cworld = world.cycles
862         cscene = context.scene.cycles
863
864         col = layout.column()
865
866         col.prop(cworld, "sample_as_light")
867         sub = col.row(align=True)
868         sub.active = cworld.sample_as_light
869         sub.prop(cworld, "sample_map_resolution")
870         if not cscene.progressive:
871             sub.prop(cworld, "samples")
872
873
874 class CyclesMaterial_PT_preview(CyclesButtonsPanel, Panel):
875     bl_label = "Preview"
876     bl_context = "material"
877     bl_options = {'DEFAULT_CLOSED'}
878
879     @classmethod
880     def poll(cls, context):
881         return context.material and CyclesButtonsPanel.poll(context)
882
883     def draw(self, context):
884         self.layout.template_preview(context.material)
885
886
887 class CyclesMaterial_PT_surface(CyclesButtonsPanel, Panel):
888     bl_label = "Surface"
889     bl_context = "material"
890
891     @classmethod
892     def poll(cls, context):
893         return context.material and CyclesButtonsPanel.poll(context)
894
895     def draw(self, context):
896         layout = self.layout
897
898         mat = context.material
899         if not panel_node_draw(layout, mat, 'OUTPUT_MATERIAL', 'Surface'):
900             layout.prop(mat, "diffuse_color")
901
902
903 class CyclesMaterial_PT_volume(CyclesButtonsPanel, Panel):
904     bl_label = "Volume"
905     bl_context = "material"
906     bl_options = {'DEFAULT_CLOSED'}
907
908     @classmethod
909     def poll(cls, context):
910         # mat = context.material
911         # mat and mat.node_tree and CyclesButtonsPanel.poll(context)
912         return False
913
914     def draw(self, context):
915         layout = self.layout
916         layout.active = False
917
918         mat = context.material
919         cmat = mat.cycles
920
921         panel_node_draw(layout, mat, 'OUTPUT_MATERIAL', 'Volume')
922
923         layout.prop(cmat, "homogeneous_volume")
924
925
926 class CyclesMaterial_PT_displacement(CyclesButtonsPanel, Panel):
927     bl_label = "Displacement"
928     bl_context = "material"
929
930     @classmethod
931     def poll(cls, context):
932         mat = context.material
933         return mat and mat.node_tree and CyclesButtonsPanel.poll(context)
934
935     def draw(self, context):
936         layout = self.layout
937
938         mat = context.material
939         panel_node_draw(layout, mat, 'OUTPUT_MATERIAL', 'Displacement')
940
941
942 class CyclesMaterial_PT_settings(CyclesButtonsPanel, Panel):
943     bl_label = "Settings"
944     bl_context = "material"
945     bl_options = {'DEFAULT_CLOSED'}
946
947     @classmethod
948     def poll(cls, context):
949         return context.material and CyclesButtonsPanel.poll(context)
950
951     def draw(self, context):
952         layout = self.layout
953
954         mat = context.material
955         cmat = mat.cycles
956
957         split = layout.split()
958
959         col = split.column()
960         col.prop(mat, "diffuse_color", text="Viewport Color")
961
962         col = split.column(align=True)
963         col.label()
964         col.prop(mat, "pass_index")
965
966         col = layout.column()
967         col.prop(cmat, "sample_as_light")
968         col.prop(cmat, "use_transparent_shadow")
969
970
971 class CyclesTexture_PT_context(CyclesButtonsPanel, Panel):
972     bl_label = ""
973     bl_context = "texture"
974     bl_options = {'HIDE_HEADER'}
975     COMPAT_ENGINES = {'CYCLES'}
976
977     def draw(self, context):
978         layout = self.layout
979
980         tex = context.texture
981         space = context.space_data
982         pin_id = space.pin_id
983         use_pin_id = space.use_pin_id
984         user = context.texture_user
985
986         space.use_limited_texture_context = False
987
988         if not (use_pin_id and isinstance(pin_id, bpy.types.Texture)):
989             pin_id = None
990
991         if not pin_id:
992             layout.template_texture_user()
993
994         if user or pin_id:
995             layout.separator()
996
997             split = layout.split(percentage=0.65)
998             col = split.column()
999
1000             if pin_id:
1001                 col.template_ID(space, "pin_id")
1002             else:
1003                 propname = context.texture_user_property.identifier
1004                 col.template_ID(user, propname, new="texture.new")
1005
1006             if tex:
1007                 split = layout.split(percentage=0.2)
1008                 split.label(text="Type:")
1009                 split.prop(tex, "type", text="")
1010
1011
1012 class CyclesTexture_PT_node(CyclesButtonsPanel, Panel):
1013     bl_label = "Node"
1014     bl_context = "texture"
1015
1016     @classmethod
1017     def poll(cls, context):
1018         node = context.texture_node
1019         return node and CyclesButtonsPanel.poll(context)
1020
1021     def draw(self, context):
1022         layout = self.layout
1023
1024         node = context.texture_node
1025         ntree = node.id_data
1026         layout.template_node_view(ntree, node, None)
1027
1028
1029 class CyclesTexture_PT_mapping(CyclesButtonsPanel, Panel):
1030     bl_label = "Mapping"
1031     bl_context = "texture"
1032
1033     @classmethod
1034     def poll(cls, context):
1035         node = context.texture_node
1036         return node and CyclesButtonsPanel.poll(context)
1037
1038     def draw(self, context):
1039         layout = self.layout
1040
1041         node = context.texture_node
1042
1043         mapping = node.texture_mapping
1044
1045         row = layout.row()
1046
1047         row.column().prop(mapping, "translation")
1048         row.column().prop(mapping, "rotation")
1049         row.column().prop(mapping, "scale")
1050
1051         layout.label(text="Projection:")
1052
1053         row = layout.row()
1054         row.prop(mapping, "mapping_x", text="")
1055         row.prop(mapping, "mapping_y", text="")
1056         row.prop(mapping, "mapping_z", text="")
1057
1058
1059 class CyclesTexture_PT_colors(CyclesButtonsPanel, Panel):
1060     bl_label = "Color"
1061     bl_context = "texture"
1062     bl_options = {'DEFAULT_CLOSED'}
1063
1064     @classmethod
1065     def poll(cls, context):
1066         # node = context.texture_node
1067         return False
1068         #return node and CyclesButtonsPanel.poll(context)
1069
1070     def draw(self, context):
1071         layout = self.layout
1072
1073         node = context.texture_node
1074
1075         mapping = node.color_mapping
1076
1077         split = layout.split()
1078
1079         col = split.column()
1080         col.label(text="Blend:")
1081         col.prop(mapping, "blend_type", text="")
1082         col.prop(mapping, "blend_factor", text="Factor")
1083         col.prop(mapping, "blend_color", text="")
1084
1085         col = split.column()
1086         col.label(text="Adjust:")
1087         col.prop(mapping, "brightness")
1088         col.prop(mapping, "contrast")
1089         col.prop(mapping, "saturation")
1090
1091         layout.separator()
1092
1093         layout.prop(mapping, "use_color_ramp", text="Ramp")
1094         if mapping.use_color_ramp:
1095             layout.template_color_ramp(mapping, "color_ramp", expand=True)
1096
1097
1098 class CyclesParticle_PT_textures(CyclesButtonsPanel, Panel):
1099     bl_label = "Textures"
1100     bl_context = "particle"
1101     bl_options = {'DEFAULT_CLOSED'}
1102
1103     @classmethod
1104     def poll(cls, context):
1105         psys = context.particle_system
1106         return psys and CyclesButtonsPanel.poll(context)
1107
1108     def draw(self, context):
1109         layout = self.layout
1110
1111         psys = context.particle_system
1112         part = psys.settings
1113
1114         row = layout.row()
1115         row.template_list("TEXTURE_UL_texslots", "", part, "texture_slots", part, "active_texture_index", rows=2)
1116
1117         col = row.column(align=True)
1118         col.operator("texture.slot_move", text="", icon='TRIA_UP').type = 'UP'
1119         col.operator("texture.slot_move", text="", icon='TRIA_DOWN').type = 'DOWN'
1120         col.menu("TEXTURE_MT_specials", icon='DOWNARROW_HLT', text="")
1121
1122         if not part.active_texture:
1123             layout.template_ID(part, "active_texture", new="texture.new")
1124         else:
1125             slot = part.texture_slots[part.active_texture_index]
1126             layout.template_ID(slot, "texture", new="texture.new")
1127
1128
1129 class CyclesRender_PT_CurveRendering(CyclesButtonsPanel, Panel):
1130     bl_label = "Cycles Hair Rendering"
1131     bl_context = "particle"
1132
1133     @classmethod
1134     def poll(cls, context):
1135         scene = context.scene
1136         cscene = scene.cycles
1137         psys = context.particle_system
1138         experimental = (cscene.feature_set == 'EXPERIMENTAL')
1139         return CyclesButtonsPanel.poll(context) and experimental and psys
1140
1141     def draw_header(self, context):
1142         ccscene = context.scene.cycles_curves
1143         self.layout.prop(ccscene, "use_curves", text="")
1144
1145     def draw(self, context):
1146         layout = self.layout
1147
1148         scene = context.scene
1149         ccscene = scene.cycles_curves
1150
1151         layout.active = ccscene.use_curves
1152
1153         layout.prop(ccscene, "primitive", text="Primitive")
1154         layout.prop(ccscene, "shape", text="Shape")
1155
1156         if ccscene.primitive == 'TRIANGLES':
1157             if ccscene.shape == 'THICK':
1158                 layout.prop(ccscene, "resolution", text="Resolution")
1159         elif ccscene.primitive == 'LINE_SEGMENTS':
1160             layout.prop(ccscene, "cull_backfacing", text="Cull back-faces")
1161         elif ccscene.primitive in {'CURVE_SEGMENTS', 'CURVE_RIBBONS'}:
1162             layout.prop(ccscene, "cull_backfacing", text="Cull back-faces")
1163             layout.prop(ccscene, "subdivisions", text="Curve subdivisions")
1164
1165         row = layout.row()
1166         row.prop(ccscene, "minimum_width", text="Min Pixels")
1167         row.prop(ccscene, "maximum_width", text="Max Ext.")
1168
1169
1170 class CyclesParticle_PT_CurveSettings(CyclesButtonsPanel, Panel):
1171     bl_label = "Cycles Hair Settings"
1172     bl_context = "particle"
1173
1174     @classmethod
1175     def poll(cls, context):
1176         scene = context.scene
1177         cscene = scene.cycles
1178         ccscene = scene.cycles_curves
1179         use_curves = ccscene.use_curves and context.particle_system
1180         experimental = cscene.feature_set == 'EXPERIMENTAL'
1181         return CyclesButtonsPanel.poll(context) and experimental and use_curves
1182
1183     def draw(self, context):
1184         layout = self.layout
1185
1186         psys = context.particle_settings
1187         cpsys = psys.cycles
1188
1189         row = layout.row()
1190         row.prop(cpsys, "shape", text="Shape")
1191
1192         layout.label(text="Thickness:")
1193         row = layout.row()
1194         row.prop(cpsys, "root_width", text="Root")
1195         row.prop(cpsys, "tip_width", text="Tip")
1196
1197         row = layout.row()
1198         row.prop(cpsys, "radius_scale", text="Scaling")
1199         row.prop(cpsys, "use_closetip", text="Close tip")
1200
1201
1202 class CyclesScene_PT_simplify(CyclesButtonsPanel, Panel):
1203     bl_label = "Simplify"
1204     bl_context = "scene"
1205     COMPAT_ENGINES = {'CYCLES'}
1206
1207     def draw_header(self, context):
1208         rd = context.scene.render
1209         self.layout.prop(rd, "use_simplify", text="")
1210
1211     def draw(self, context):
1212         layout = self.layout
1213
1214         rd = context.scene.render
1215
1216         layout.active = rd.use_simplify
1217
1218         row = layout.row()
1219         row.prop(rd, "simplify_subdivision", text="Subdivision")
1220         row.prop(rd, "simplify_child_particles", text="Child Particles")
1221
1222
1223 def draw_device(self, context):
1224     scene = context.scene
1225     layout = self.layout
1226
1227     if scene.render.engine == 'CYCLES':
1228         from . import engine
1229         cscene = scene.cycles
1230
1231         layout.prop(cscene, "feature_set")
1232
1233         device_type = context.user_preferences.system.compute_device_type
1234         if device_type == 'CUDA':
1235             layout.prop(cscene, "device")
1236         elif device_type == 'OPENCL':
1237             layout.prop(cscene, "device")
1238
1239         if engine.with_osl() and (cscene.device == 'CPU' or device_type == 'NONE'):
1240             layout.prop(cscene, "shading_system")
1241
1242
1243 def draw_pause(self, context):
1244     layout = self.layout
1245     scene = context.scene
1246
1247     if scene.render.engine == "CYCLES":
1248         view = context.space_data
1249
1250         if view.viewport_shade == 'RENDERED':
1251             cscene = scene.cycles
1252             layername = scene.render.layers.active.name
1253             layout.prop(cscene, "preview_pause", icon="PAUSE", text="")
1254             layout.prop(cscene, "preview_active_layer", icon="RENDERLAYERS", text=layername)
1255
1256
1257 def get_panels():
1258     types = bpy.types
1259     return (
1260         types.RENDER_PT_render,
1261         types.RENDER_PT_output,
1262         types.RENDER_PT_encoding,
1263         types.RENDER_PT_dimensions,
1264         types.RENDER_PT_stamp,
1265         types.SCENE_PT_scene,
1266         types.SCENE_PT_color_management,
1267         types.SCENE_PT_custom_props,
1268         types.SCENE_PT_audio,
1269         types.SCENE_PT_unit,
1270         types.SCENE_PT_keying_sets,
1271         types.SCENE_PT_keying_set_paths,
1272         types.SCENE_PT_physics,
1273         types.WORLD_PT_context_world,
1274         types.WORLD_PT_custom_props,
1275         types.DATA_PT_context_mesh,
1276         types.DATA_PT_context_camera,
1277         types.DATA_PT_context_lamp,
1278         types.DATA_PT_context_speaker,
1279         types.DATA_PT_texture_space,
1280         types.DATA_PT_curve_texture_space,
1281         types.DATA_PT_mball_texture_space,
1282         types.DATA_PT_vertex_groups,
1283         types.DATA_PT_shape_keys,
1284         types.DATA_PT_uv_texture,
1285         types.DATA_PT_vertex_colors,
1286         types.DATA_PT_camera,
1287         types.DATA_PT_camera_display,
1288         types.DATA_PT_lens,
1289         types.DATA_PT_speaker,
1290         types.DATA_PT_distance,
1291         types.DATA_PT_cone,
1292         types.DATA_PT_customdata,
1293         types.DATA_PT_custom_props_mesh,
1294         types.DATA_PT_custom_props_camera,
1295         types.DATA_PT_custom_props_lamp,
1296         types.DATA_PT_custom_props_speaker,
1297         types.DATA_PT_custom_props_arm,
1298         types.DATA_PT_custom_props_curve,
1299         types.DATA_PT_custom_props_lattice,
1300         types.DATA_PT_custom_props_metaball,
1301         types.TEXTURE_PT_custom_props,
1302         types.TEXTURE_PT_clouds,
1303         types.TEXTURE_PT_wood,
1304         types.TEXTURE_PT_marble,
1305         types.TEXTURE_PT_magic,
1306         types.TEXTURE_PT_blend,
1307         types.TEXTURE_PT_stucci,
1308         types.TEXTURE_PT_image,
1309         types.TEXTURE_PT_image_sampling,
1310         types.TEXTURE_PT_image_mapping,
1311         types.TEXTURE_PT_musgrave,
1312         types.TEXTURE_PT_voronoi,
1313         types.TEXTURE_PT_distortednoise,
1314         types.TEXTURE_PT_voxeldata,
1315         types.TEXTURE_PT_pointdensity,
1316         types.TEXTURE_PT_pointdensity_turbulence,
1317         types.TEXTURE_PT_mapping,
1318         types.TEXTURE_PT_influence,
1319         types.TEXTURE_PT_colors,
1320         types.PARTICLE_PT_context_particles,
1321         types.PARTICLE_PT_custom_props,
1322         types.PARTICLE_PT_emission,
1323         types.PARTICLE_PT_hair_dynamics,
1324         types.PARTICLE_PT_cache,
1325         types.PARTICLE_PT_velocity,
1326         types.PARTICLE_PT_rotation,
1327         types.PARTICLE_PT_physics,
1328         types.SCENE_PT_rigid_body_world,
1329         types.SCENE_PT_rigid_body_cache,
1330         types.SCENE_PT_rigid_body_field_weights,
1331         types.PARTICLE_PT_boidbrain,
1332         types.PARTICLE_PT_render,
1333         types.PARTICLE_PT_draw,
1334         types.PARTICLE_PT_children,
1335         types.PARTICLE_PT_field_weights,
1336         types.PARTICLE_PT_force_fields,
1337         types.PARTICLE_PT_vertexgroups,
1338         types.MATERIAL_PT_custom_props,
1339         types.BONE_PT_custom_props,
1340         types.OBJECT_PT_custom_props,
1341         )
1342
1343
1344 def register():
1345     bpy.types.RENDER_PT_render.append(draw_device)
1346     bpy.types.VIEW3D_HT_header.append(draw_pause)
1347
1348     for panel in get_panels():
1349         panel.COMPAT_ENGINES.add('CYCLES')
1350
1351
1352 def unregister():
1353     bpy.types.RENDER_PT_render.remove(draw_device)
1354     bpy.types.VIEW3D_HT_header.remove(draw_pause)
1355
1356     for panel in get_panels():
1357         panel.COMPAT_ENGINES.remove('CYCLES')