5bb0ea1c2ddcc6c81a24c96513dc0ab2a2eab48a
[blender-staging.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 (
22         Panel,
23         Menu,
24         Operator,
25         )
26
27
28 class CYCLES_MT_sampling_presets(Menu):
29     bl_label = "Sampling Presets"
30     preset_subdir = "cycles/sampling"
31     preset_operator = "script.execute_preset"
32     COMPAT_ENGINES = {'CYCLES'}
33     draw = Menu.draw_preset
34
35
36 class CYCLES_MT_integrator_presets(Menu):
37     bl_label = "Integrator Presets"
38     preset_subdir = "cycles/integrator"
39     preset_operator = "script.execute_preset"
40     COMPAT_ENGINES = {'CYCLES'}
41     draw = Menu.draw_preset
42
43
44 class CyclesButtonsPanel:
45     bl_space_type = "PROPERTIES"
46     bl_region_type = "WINDOW"
47     bl_context = "render"
48     COMPAT_ENGINES = {'CYCLES'}
49
50     @classmethod
51     def poll(cls, context):
52         rd = context.scene.render
53         return rd.engine in cls.COMPAT_ENGINES
54
55
56 def get_device_type(context):
57     return context.user_preferences.addons[__package__].preferences.compute_device_type
58
59
60 def use_cpu(context):
61     cscene = context.scene.cycles
62
63     return (get_device_type(context) == 'NONE' or cscene.device == 'CPU')
64
65
66 def use_opencl(context):
67     cscene = context.scene.cycles
68
69     return (get_device_type(context) == 'OPENCL' and cscene.device == 'GPU')
70
71
72 def use_cuda(context):
73     cscene = context.scene.cycles
74
75     return (get_device_type(context) == 'CUDA' and cscene.device == 'GPU')
76
77
78 def use_branched_path(context):
79     cscene = context.scene.cycles
80
81     return (cscene.progressive == 'BRANCHED_PATH')
82
83
84 def use_sample_all_lights(context):
85     cscene = context.scene.cycles
86
87     return cscene.sample_all_lights_direct or cscene.sample_all_lights_indirect
88
89 def show_device_active(context):
90     cscene = context.scene.cycles
91     if cscene.device != 'GPU':
92         return True
93     return context.user_preferences.addons[__package__].preferences.has_active_device()
94
95
96 def draw_samples_info(layout, context):
97     cscene = context.scene.cycles
98     integrator = cscene.progressive
99
100     # Calculate sample values
101     if integrator == 'PATH':
102         aa = cscene.samples
103         if cscene.use_square_samples:
104             aa = aa * aa
105     else:
106         aa = cscene.aa_samples
107         d = cscene.diffuse_samples
108         g = cscene.glossy_samples
109         t = cscene.transmission_samples
110         ao = cscene.ao_samples
111         ml = cscene.mesh_light_samples
112         sss = cscene.subsurface_samples
113         vol = cscene.volume_samples
114
115         if cscene.use_square_samples:
116             aa = aa * aa
117             d = d * d
118             g = g * g
119             t = t * t
120             ao = ao * ao
121             ml = ml * ml
122             sss = sss * sss
123             vol = vol * vol
124
125     # Draw interface
126     # Do not draw for progressive, when Square Samples are disabled
127     if use_branched_path(context) or (cscene.use_square_samples and integrator == 'PATH'):
128         col = layout.column(align=True)
129         col.scale_y = 0.6
130         col.label("Total Samples:")
131         col.separator()
132         if integrator == 'PATH':
133             col.label("%s AA" % aa)
134         else:
135             col.label("%s AA, %s Diffuse, %s Glossy, %s Transmission" %
136                       (aa, d * aa, g * aa, t * aa))
137             col.separator()
138             col.label("%s AO, %s Mesh Light, %s Subsurface, %s Volume" %
139                       (ao * aa, ml * aa, sss * aa, vol * aa))
140
141
142 class CYCLES_RENDER_PT_sampling(CyclesButtonsPanel, Panel):
143     bl_label = "Sampling"
144     bl_options = {'DEFAULT_CLOSED'}
145
146     def draw(self, context):
147         layout = self.layout
148
149         scene = context.scene
150         cscene = scene.cycles
151
152         row = layout.row(align=True)
153         row.menu("CYCLES_MT_sampling_presets", text=bpy.types.CYCLES_MT_sampling_presets.bl_label)
154         row.operator("render.cycles_sampling_preset_add", text="", icon="ZOOMIN")
155         row.operator("render.cycles_sampling_preset_add", text="", icon="ZOOMOUT").remove_active = True
156
157         row = layout.row()
158         sub = row.row()
159         sub.prop(cscene, "progressive", text="")
160         row.prop(cscene, "use_square_samples")
161
162         split = layout.split()
163
164         col = split.column()
165         sub = col.column(align=True)
166         sub.label("Settings:")
167
168         seed_sub = sub.row(align=True)
169         seed_sub.prop(cscene, "seed")
170         seed_sub.prop(cscene, "use_animated_seed", text="", icon="TIME")
171
172         sub.prop(cscene, "sample_clamp_direct")
173         sub.prop(cscene, "sample_clamp_indirect")
174         sub.prop(cscene, "light_sampling_threshold")
175
176         if cscene.progressive == 'PATH' or use_branched_path(context) is False:
177             col = split.column()
178             sub = col.column(align=True)
179             sub.label(text="Samples:")
180             sub.prop(cscene, "samples", text="Render")
181             sub.prop(cscene, "preview_samples", text="Preview")
182         else:
183             sub.label(text="AA Samples:")
184             sub.prop(cscene, "aa_samples", text="Render")
185             sub.prop(cscene, "preview_aa_samples", text="Preview")
186
187             col = split.column()
188             sub = col.column(align=True)
189             sub.label(text="Samples:")
190             sub.prop(cscene, "diffuse_samples", text="Diffuse")
191             sub.prop(cscene, "glossy_samples", text="Glossy")
192             sub.prop(cscene, "transmission_samples", text="Transmission")
193             sub.prop(cscene, "ao_samples", text="AO")
194
195             subsub = sub.row(align=True)
196             subsub.active = use_sample_all_lights(context)
197             subsub.prop(cscene, "mesh_light_samples", text="Mesh Light")
198
199             sub.prop(cscene, "subsurface_samples", text="Subsurface")
200             sub.prop(cscene, "volume_samples", text="Volume")
201
202             col = layout.column(align=True)
203             col.prop(cscene, "sample_all_lights_direct")
204             col.prop(cscene, "sample_all_lights_indirect")
205
206         layout.row().prop(cscene, "sampling_pattern", text="Pattern")
207
208         for rl in scene.render.layers:
209             if rl.samples > 0:
210                 layout.separator()
211                 layout.row().prop(cscene, "use_layer_samples")
212                 break
213
214         draw_samples_info(layout, context)
215
216
217 class CYCLES_RENDER_PT_geometry(CyclesButtonsPanel, Panel):
218     bl_label = "Geometry"
219     bl_options = {'DEFAULT_CLOSED'}
220
221     def draw(self, context):
222         layout = self.layout
223
224         scene = context.scene
225         cscene = scene.cycles
226         ccscene = scene.cycles_curves
227
228         row = layout.row()
229         row.label("Volume Sampling:")
230         row = layout.row()
231         row.prop(cscene, "volume_step_size")
232         row.prop(cscene, "volume_max_steps")
233
234         layout.separator()
235
236         if cscene.feature_set == 'EXPERIMENTAL':
237             layout.label("Subdivision Rate:")
238             split = layout.split()
239
240             col = split.column()
241             sub = col.column(align=True)
242             sub.prop(cscene, "dicing_rate", text="Render")
243             sub.prop(cscene, "preview_dicing_rate", text="Preview")
244
245             col = split.column()
246             col.prop(cscene, "offscreen_dicing_scale", text="Offscreen Scale")
247             col.prop(cscene, "max_subdivisions")
248
249             layout.prop(cscene, "dicing_camera")
250
251             layout.separator()
252
253         layout.label("Hair:")
254         layout.prop(ccscene, "use_curves", text="Use Hair")
255         col = layout.column()
256         col.active = ccscene.use_curves
257
258         col.prop(ccscene, "primitive", text="Primitive")
259         col.prop(ccscene, "shape", text="Shape")
260
261         if not (ccscene.primitive in {'CURVE_SEGMENTS', 'LINE_SEGMENTS'} and ccscene.shape == 'RIBBONS'):
262             col.prop(ccscene, "cull_backfacing", text="Cull back-faces")
263
264         if ccscene.primitive == 'TRIANGLES' and ccscene.shape == 'THICK':
265             col.prop(ccscene, "resolution", text="Resolution")
266         elif ccscene.primitive == 'CURVE_SEGMENTS':
267             col.prop(ccscene, "subdivisions", text="Curve subdivisions")
268
269         row = col.row()
270         row.prop(ccscene, "minimum_width", text="Min Pixels")
271         row.prop(ccscene, "maximum_width", text="Max Extension")
272
273
274 class CYCLES_RENDER_PT_light_paths(CyclesButtonsPanel, Panel):
275     bl_label = "Light Paths"
276     bl_options = {'DEFAULT_CLOSED'}
277
278     def draw(self, context):
279         layout = self.layout
280
281         scene = context.scene
282         cscene = scene.cycles
283
284         row = layout.row(align=True)
285         row.menu("CYCLES_MT_integrator_presets", text=bpy.types.CYCLES_MT_integrator_presets.bl_label)
286         row.operator("render.cycles_integrator_preset_add", text="", icon="ZOOMIN")
287         row.operator("render.cycles_integrator_preset_add", text="", icon="ZOOMOUT").remove_active = True
288
289         split = layout.split()
290
291         col = split.column()
292
293         sub = col.column(align=True)
294         sub.label("Transparency:")
295         sub.prop(cscene, "transparent_max_bounces", text="Max")
296
297         col.separator()
298
299         col.prop(cscene, "caustics_reflective")
300         col.prop(cscene, "caustics_refractive")
301         col.prop(cscene, "blur_glossy")
302
303         col = split.column()
304
305         sub = col.column(align=True)
306         sub.label(text="Bounces:")
307         sub.prop(cscene, "max_bounces", text="Max")
308
309         sub = col.column(align=True)
310         sub.prop(cscene, "diffuse_bounces", text="Diffuse")
311         sub.prop(cscene, "glossy_bounces", text="Glossy")
312         sub.prop(cscene, "transmission_bounces", text="Transmission")
313         sub.prop(cscene, "volume_bounces", text="Volume")
314
315
316 class CYCLES_RENDER_PT_motion_blur(CyclesButtonsPanel, Panel):
317     bl_label = "Motion Blur"
318     bl_options = {'DEFAULT_CLOSED'}
319
320     def draw_header(self, context):
321         rd = context.scene.render
322
323         self.layout.prop(rd, "use_motion_blur", text="")
324
325     def draw(self, context):
326         layout = self.layout
327
328         scene = context.scene
329         cscene = scene.cycles
330         rd = scene.render
331         layout.active = rd.use_motion_blur
332
333         col = layout.column()
334         col.prop(cscene, "motion_blur_position", text="Position")
335         col.prop(rd, "motion_blur_shutter")
336
337         col = layout.column()
338         col.label("Shutter curve:")
339         col.template_curve_mapping(rd, "motion_blur_shutter_curve")
340
341         col = layout.column(align=True)
342         row = col.row(align=True)
343         row.operator("render.shutter_curve_preset", icon='SMOOTHCURVE', text="").shape = 'SMOOTH'
344         row.operator("render.shutter_curve_preset", icon='SPHERECURVE', text="").shape = 'ROUND'
345         row.operator("render.shutter_curve_preset", icon='ROOTCURVE', text="").shape = 'ROOT'
346         row.operator("render.shutter_curve_preset", icon='SHARPCURVE', text="").shape = 'SHARP'
347         row.operator("render.shutter_curve_preset", icon='LINCURVE', text="").shape = 'LINE'
348         row.operator("render.shutter_curve_preset", icon='NOCURVE', text="").shape = 'MAX'
349
350         col = layout.column()
351         col.prop(cscene, "rolling_shutter_type")
352         row = col.row()
353         row.active = cscene.rolling_shutter_type != 'NONE'
354         row.prop(cscene, "rolling_shutter_duration")
355
356
357 class CYCLES_RENDER_PT_film(CyclesButtonsPanel, Panel):
358     bl_label = "Film"
359
360     def draw(self, context):
361         layout = self.layout
362
363         scene = context.scene
364         cscene = scene.cycles
365
366         split = layout.split()
367
368         col = split.column()
369         col.prop(cscene, "film_exposure")
370         col.prop(cscene, "film_transparent")
371
372         col = split.column()
373         sub = col.column(align=True)
374         sub.prop(cscene, "pixel_filter_type", text="")
375         if cscene.pixel_filter_type != 'BOX':
376             sub.prop(cscene, "filter_width", text="Width")
377
378
379 class CYCLES_RENDER_PT_performance(CyclesButtonsPanel, Panel):
380     bl_label = "Performance"
381     bl_options = {'DEFAULT_CLOSED'}
382
383     def draw(self, context):
384         layout = self.layout
385
386         scene = context.scene
387         rd = scene.render
388         cscene = scene.cycles
389
390         split = layout.split()
391
392         col = split.column(align=True)
393
394         col.label(text="Threads:")
395         col.row(align=True).prop(rd, "threads_mode", expand=True)
396         sub = col.column(align=True)
397         sub.enabled = rd.threads_mode == 'FIXED'
398         sub.prop(rd, "threads")
399
400         col.separator()
401
402         sub = col.column(align=True)
403         sub.label(text="Tiles:")
404         sub.prop(cscene, "tile_order", text="")
405
406         sub.prop(rd, "tile_x", text="X")
407         sub.prop(rd, "tile_y", text="Y")
408
409         subsub = sub.column()
410         subsub.active = not rd.use_save_buffers
411         for rl in rd.layers:
412             if rl.cycles.use_denoising:
413                 subsub.active = False
414         subsub.prop(cscene, "use_progressive_refine")
415
416         col = split.column()
417
418         col.label(text="Final Render:")
419         col.prop(rd, "use_save_buffers")
420         col.prop(rd, "use_persistent_data", text="Persistent Images")
421
422         col.separator()
423
424         col.label(text="Acceleration structure:")
425         col.prop(cscene, "debug_use_spatial_splits")
426         col.prop(cscene, "debug_use_hair_bvh")
427
428         row = col.row()
429         row.active = not cscene.debug_use_spatial_splits
430         row.prop(cscene, "debug_bvh_time_steps")
431
432         col = layout.column()
433         col.label(text="Viewport Resolution:")
434         split = col.split()
435         split.prop(rd, "preview_pixel_size", text="")
436         split.prop(cscene, "preview_start_resolution")
437
438
439 class CYCLES_RENDER_PT_layer_options(CyclesButtonsPanel, Panel):
440     bl_label = "Layer"
441     bl_context = "render_layer"
442
443     def draw(self, context):
444         layout = self.layout
445
446         scene = context.scene
447         rd = scene.render
448         rl = rd.layers.active
449
450         split = layout.split()
451
452         col = split.column()
453         col.prop(scene, "layers", text="Scene")
454         col.prop(rl, "layers_exclude", text="Exclude")
455
456         col = split.column()
457         col.prop(rl, "layers", text="Layer")
458         col.prop(rl, "layers_zmask", text="Mask Layer")
459
460         split = layout.split()
461
462         col = split.column()
463         col.label(text="Material:")
464         col.prop(rl, "material_override", text="")
465         col.separator()
466         col.prop(rl, "samples")
467
468         col = split.column()
469         col.prop(rl, "use_sky", "Use Environment")
470         col.prop(rl, "use_ao", "Use AO")
471         col.prop(rl, "use_solid", "Use Surfaces")
472         col.prop(rl, "use_strand", "Use Hair")
473
474
475 class CYCLES_RENDER_PT_layer_passes(CyclesButtonsPanel, Panel):
476     bl_label = "Passes"
477     bl_context = "render_layer"
478     bl_options = {'DEFAULT_CLOSED'}
479
480     def draw(self, context):
481         import _cycles
482
483         layout = self.layout
484
485         scene = context.scene
486         rd = scene.render
487         rl = rd.layers.active
488         crl = rl.cycles
489
490         split = layout.split()
491
492         col = split.column()
493         col.prop(rl, "use_pass_combined")
494         col.prop(rl, "use_pass_z")
495         col.prop(rl, "use_pass_mist")
496         col.prop(rl, "use_pass_normal")
497         row = col.row()
498         row.prop(rl, "use_pass_vector")
499         row.active = not rd.use_motion_blur
500         col.prop(rl, "use_pass_uv")
501         col.prop(rl, "use_pass_object_index")
502         col.prop(rl, "use_pass_material_index")
503         col.separator()
504         col.prop(rl, "use_pass_shadow")
505         col.prop(rl, "use_pass_ambient_occlusion")
506         col.separator()
507         col.prop(rl, "pass_alpha_threshold")
508
509         col = split.column()
510         col.label(text="Diffuse:")
511         row = col.row(align=True)
512         row.prop(rl, "use_pass_diffuse_direct", text="Direct", toggle=True)
513         row.prop(rl, "use_pass_diffuse_indirect", text="Indirect", toggle=True)
514         row.prop(rl, "use_pass_diffuse_color", text="Color", toggle=True)
515         col.label(text="Glossy:")
516         row = col.row(align=True)
517         row.prop(rl, "use_pass_glossy_direct", text="Direct", toggle=True)
518         row.prop(rl, "use_pass_glossy_indirect", text="Indirect", toggle=True)
519         row.prop(rl, "use_pass_glossy_color", text="Color", toggle=True)
520         col.label(text="Transmission:")
521         row = col.row(align=True)
522         row.prop(rl, "use_pass_transmission_direct", text="Direct", toggle=True)
523         row.prop(rl, "use_pass_transmission_indirect", text="Indirect", toggle=True)
524         row.prop(rl, "use_pass_transmission_color", text="Color", toggle=True)
525         col.label(text="Subsurface:")
526         row = col.row(align=True)
527         row.prop(rl, "use_pass_subsurface_direct", text="Direct", toggle=True)
528         row.prop(rl, "use_pass_subsurface_indirect", text="Indirect", toggle=True)
529         row.prop(rl, "use_pass_subsurface_color", text="Color", toggle=True)
530         col.label(text="Volume:")
531         row = col.row(align=True)
532         row.prop(crl, "use_pass_volume_direct", text="Direct", toggle=True)
533         row.prop(crl, "use_pass_volume_indirect", text="Indirect", toggle=True)
534
535         col.separator()
536         col.prop(rl, "use_pass_emit", text="Emission")
537         col.prop(rl, "use_pass_environment")
538
539         if context.scene.cycles.feature_set == 'EXPERIMENTAL':
540             col.separator()
541             sub = col.column()
542             sub.active = crl.use_denoising
543             sub.prop(crl, "denoising_store_passes", text="Denoising")
544
545         col = layout.column()
546         col.prop(crl, "pass_debug_render_time")
547         if _cycles.with_cycles_debug:
548             col.prop(crl, "pass_debug_bvh_traversed_nodes")
549             col.prop(crl, "pass_debug_bvh_traversed_instances")
550             col.prop(crl, "pass_debug_bvh_intersections")
551             col.prop(crl, "pass_debug_ray_bounces")
552
553
554 class CYCLES_RENDER_PT_views(CyclesButtonsPanel, Panel):
555     bl_label = "Views"
556     bl_context = "render_layer"
557     bl_options = {'DEFAULT_CLOSED'}
558
559     def draw_header(self, context):
560         rd = context.scene.render
561         self.layout.prop(rd, "use_multiview", text="")
562
563     def draw(self, context):
564         layout = self.layout
565
566         scene = context.scene
567         rd = scene.render
568         rv = rd.views.active
569
570         layout.active = rd.use_multiview
571         basic_stereo = (rd.views_format == 'STEREO_3D')
572
573         row = layout.row()
574         row.prop(rd, "views_format", expand=True)
575
576         if basic_stereo:
577             row = layout.row()
578             row.template_list("RENDERLAYER_UL_renderviews", "name", rd, "stereo_views", rd.views, "active_index", rows=2)
579
580             row = layout.row()
581             row.label(text="File Suffix:")
582             row.prop(rv, "file_suffix", text="")
583
584         else:
585             row = layout.row()
586             row.template_list("RENDERLAYER_UL_renderviews", "name", rd, "views", rd.views, "active_index", rows=2)
587
588             col = row.column(align=True)
589             col.operator("scene.render_view_add", icon='ZOOMIN', text="")
590             col.operator("scene.render_view_remove", icon='ZOOMOUT', text="")
591
592             row = layout.row()
593             row.label(text="Camera Suffix:")
594             row.prop(rv, "camera_suffix", text="")
595
596
597 class CYCLES_RENDER_PT_denoising(CyclesButtonsPanel, Panel):
598     bl_label = "Denoising"
599     bl_context = "render_layer"
600     bl_options = {'DEFAULT_CLOSED'}
601
602     def draw_header(self, context):
603         rd = context.scene.render
604         rl = rd.layers.active
605         crl = rl.cycles
606         cscene = context.scene.cycles
607         layout = self.layout
608
609         layout.prop(crl, "use_denoising", text="")
610
611     def draw(self, context):
612         layout = self.layout
613
614         scene = context.scene
615         cscene = scene.cycles
616         rd = scene.render
617         rl = rd.layers.active
618         crl = rl.cycles
619
620         layout.active = crl.use_denoising
621
622         split = layout.split()
623
624         col = split.column()
625         sub = col.column(align=True)
626         sub.prop(crl, "denoising_radius", text="Radius")
627         sub.prop(crl, "denoising_strength", slider=True, text="Strength")
628
629         col = split.column()
630         sub = col.column(align=True)
631         sub.prop(crl, "denoising_feature_strength", slider=True, text="Feature Strength")
632         sub.prop(crl, "denoising_relative_pca")
633
634         layout.separator()
635
636         row = layout.row()
637         row.label(text="Diffuse:")
638         sub = row.row(align=True)
639         sub.prop(crl, "denoising_diffuse_direct", text="Direct", toggle=True)
640         sub.prop(crl, "denoising_diffuse_indirect", text="Indirect", toggle=True)
641
642         row = layout.row()
643         row.label(text="Glossy:")
644         sub = row.row(align=True)
645         sub.prop(crl, "denoising_glossy_direct", text="Direct", toggle=True)
646         sub.prop(crl, "denoising_glossy_indirect", text="Indirect", toggle=True)
647
648         row = layout.row()
649         row.label(text="Transmission:")
650         sub = row.row(align=True)
651         sub.prop(crl, "denoising_transmission_direct", text="Direct", toggle=True)
652         sub.prop(crl, "denoising_transmission_indirect", text="Indirect", toggle=True)
653
654         row = layout.row()
655         row.label(text="Subsurface:")
656         sub = row.row(align=True)
657         sub.prop(crl, "denoising_subsurface_direct", text="Direct", toggle=True)
658         sub.prop(crl, "denoising_subsurface_indirect", text="Indirect", toggle=True)
659
660
661 class CYCLES_PT_post_processing(CyclesButtonsPanel, Panel):
662     bl_label = "Post Processing"
663     bl_options = {'DEFAULT_CLOSED'}
664
665     def draw(self, context):
666         layout = self.layout
667
668         rd = context.scene.render
669
670         split = layout.split()
671
672         col = split.column()
673         col.prop(rd, "use_compositing")
674         col.prop(rd, "use_sequencer")
675
676         col = split.column()
677         col.prop(rd, "dither_intensity", text="Dither", slider=True)
678
679
680 class CYCLES_CAMERA_PT_dof(CyclesButtonsPanel, Panel):
681     bl_label = "Depth of Field"
682     bl_context = "data"
683
684     @classmethod
685     def poll(cls, context):
686         return context.camera and CyclesButtonsPanel.poll(context)
687
688     def draw(self, context):
689         layout = self.layout
690
691         cam = context.camera
692         ccam = cam.cycles
693         dof_options = cam.gpu_dof
694
695         split = layout.split()
696
697         col = split.column()
698         col.label("Focus:")
699         col.prop(cam, "dof_object", text="")
700
701         sub = col.row()
702         sub.active = cam.dof_object is None
703         sub.prop(cam, "dof_distance", text="Distance")
704
705         hq_support = dof_options.is_hq_supported
706         sub = col.column(align=True)
707         sub.label("Viewport:")
708         subhq = sub.column()
709         subhq.active = hq_support
710         subhq.prop(dof_options, "use_high_quality")
711         sub.prop(dof_options, "fstop")
712         if dof_options.use_high_quality and hq_support:
713             sub.prop(dof_options, "blades")
714
715         col = split.column()
716
717         col.label("Aperture:")
718         sub = col.column(align=True)
719         sub.prop(ccam, "aperture_type", text="")
720         if ccam.aperture_type == 'RADIUS':
721             sub.prop(ccam, "aperture_size", text="Size")
722         elif ccam.aperture_type == 'FSTOP':
723             sub.prop(ccam, "aperture_fstop", text="Number")
724
725         sub = col.column(align=True)
726         sub.prop(ccam, "aperture_blades", text="Blades")
727         sub.prop(ccam, "aperture_rotation", text="Rotation")
728         sub.prop(ccam, "aperture_ratio", text="Ratio")
729
730
731 class CYCLES_PT_context_material(CyclesButtonsPanel, Panel):
732     bl_label = ""
733     bl_context = "material"
734     bl_options = {'HIDE_HEADER'}
735
736     @classmethod
737     def poll(cls, context):
738         return (context.material or context.object) and CyclesButtonsPanel.poll(context)
739
740     def draw(self, context):
741         layout = self.layout
742
743         mat = context.material
744         ob = context.object
745         slot = context.material_slot
746         space = context.space_data
747
748         if ob:
749             is_sortable = len(ob.material_slots) > 1
750             rows = 1
751             if (is_sortable):
752                 rows = 4
753
754             row = layout.row()
755
756             row.template_list("MATERIAL_UL_matslots", "", ob, "material_slots", ob, "active_material_index", rows=rows)
757
758             col = row.column(align=True)
759             col.operator("object.material_slot_add", icon='ZOOMIN', text="")
760             col.operator("object.material_slot_remove", icon='ZOOMOUT', text="")
761
762             col.menu("MATERIAL_MT_specials", icon='DOWNARROW_HLT', text="")
763
764             if is_sortable:
765                 col.separator()
766
767                 col.operator("object.material_slot_move", icon='TRIA_UP', text="").direction = 'UP'
768                 col.operator("object.material_slot_move", icon='TRIA_DOWN', text="").direction = 'DOWN'
769
770             if ob.mode == 'EDIT':
771                 row = layout.row(align=True)
772                 row.operator("object.material_slot_assign", text="Assign")
773                 row.operator("object.material_slot_select", text="Select")
774                 row.operator("object.material_slot_deselect", text="Deselect")
775
776         split = layout.split(percentage=0.65)
777
778         if ob:
779             split.template_ID(ob, "active_material", new="material.new")
780             row = split.row()
781
782             if slot:
783                 row.prop(slot, "link", text="")
784             else:
785                 row.label()
786         elif mat:
787             split.template_ID(space, "pin_id")
788             split.separator()
789
790
791 class CYCLES_OBJECT_PT_motion_blur(CyclesButtonsPanel, Panel):
792     bl_label = "Motion Blur"
793     bl_context = "object"
794     bl_options = {'DEFAULT_CLOSED'}
795
796     @classmethod
797     def poll(cls, context):
798         ob = context.object
799         if CyclesButtonsPanel.poll(context) and ob:
800             if ob.type in {'MESH', 'CURVE', 'CURVE', 'SURFACE', 'FONT', 'META'}:
801                 return True
802             if ob.dupli_type == 'GROUP' and ob.dupli_group:
803                 return True
804             # TODO(sergey): More duplicator types here?
805         return False
806
807     def draw_header(self, context):
808         layout = self.layout
809
810         rd = context.scene.render
811         # scene = context.scene
812
813         layout.active = rd.use_motion_blur
814
815         ob = context.object
816         cob = ob.cycles
817
818         layout.prop(cob, "use_motion_blur", text="")
819
820     def draw(self, context):
821         layout = self.layout
822
823         rd = context.scene.render
824         # scene = context.scene
825
826         ob = context.object
827         cob = ob.cycles
828
829         layout.active = (rd.use_motion_blur and cob.use_motion_blur)
830
831         row = layout.row()
832         row.prop(cob, "use_deform_motion", text="Deformation")
833
834         sub = row.row()
835         sub.active = cob.use_deform_motion
836         sub.prop(cob, "motion_steps", text="Steps")
837
838
839 class CYCLES_OBJECT_PT_cycles_settings(CyclesButtonsPanel, Panel):
840     bl_label = "Cycles Settings"
841     bl_context = "object"
842     bl_options = {'DEFAULT_CLOSED'}
843
844     @classmethod
845     def poll(cls, context):
846         ob = context.object
847         return (CyclesButtonsPanel.poll(context) and
848                 ob and ((ob.type in {'MESH', 'CURVE', 'SURFACE', 'FONT', 'META', 'LAMP'}) or
849                         (ob.dupli_type == 'GROUP' and ob.dupli_group)))
850
851     def draw(self, context):
852         layout = self.layout
853
854         scene = context.scene
855         cscene = scene.cycles
856         ob = context.object
857         cob = ob.cycles
858         visibility = ob.cycles_visibility
859
860         layout.label(text="Ray Visibility:")
861         flow = layout.column_flow()
862
863         flow.prop(visibility, "camera")
864         flow.prop(visibility, "diffuse")
865         flow.prop(visibility, "glossy")
866         flow.prop(visibility, "transmission")
867         flow.prop(visibility, "scatter")
868
869         if ob.type != 'LAMP':
870             flow.prop(visibility, "shadow")
871
872         row = layout.row()
873         row.prop(cob, "is_shadow_catcher")
874         row.prop(cob, "is_holdout")
875
876         col = layout.column()
877         col.label(text="Performance:")
878         row = col.row()
879         sub = row.row()
880         sub.active = scene.render.use_simplify and cscene.use_camera_cull
881         sub.prop(cob, "use_camera_cull")
882
883         sub = row.row()
884         sub.active = scene.render.use_simplify and cscene.use_distance_cull
885         sub.prop(cob, "use_distance_cull")
886
887
888 class CYCLES_OT_use_shading_nodes(Operator):
889     """Enable nodes on a material, world or lamp"""
890     bl_idname = "cycles.use_shading_nodes"
891     bl_label = "Use Nodes"
892
893     @classmethod
894     def poll(cls, context):
895         return (getattr(context, "material", False) or getattr(context, "world", False) or
896                 getattr(context, "lamp", False))
897
898     def execute(self, context):
899         if context.material:
900             context.material.use_nodes = True
901         elif context.world:
902             context.world.use_nodes = True
903         elif context.lamp:
904             context.lamp.use_nodes = True
905
906         return {'FINISHED'}
907
908
909 def find_node(material, nodetype):
910     if material and material.node_tree:
911         ntree = material.node_tree
912
913         active_output_node = None
914         for node in ntree.nodes:
915             if getattr(node, "type", None) == nodetype:
916                 if getattr(node, "is_active_output", True):
917                     return node
918                 if not active_output_node:
919                     active_output_node = node
920         return active_output_node
921
922     return None
923
924
925 def find_node_input(node, name):
926     for input in node.inputs:
927         if input.name == name:
928             return input
929
930     return None
931
932
933 def panel_node_draw(layout, id_data, output_type, input_name):
934     if not id_data.use_nodes:
935         layout.operator("cycles.use_shading_nodes", icon='NODETREE')
936         return False
937
938     ntree = id_data.node_tree
939
940     node = find_node(id_data, output_type)
941     if not node:
942         layout.label(text="No output node")
943     else:
944         input = find_node_input(node, input_name)
945         layout.template_node_view(ntree, node, input)
946
947     return True
948
949
950 class CYCLES_LAMP_PT_preview(CyclesButtonsPanel, Panel):
951     bl_label = "Preview"
952     bl_context = "data"
953     bl_options = {'DEFAULT_CLOSED'}
954
955     @classmethod
956     def poll(cls, context):
957         return context.lamp and \
958                not (context.lamp.type == 'AREA' and
959                     context.lamp.cycles.is_portal) \
960                and CyclesButtonsPanel.poll(context)
961
962     def draw(self, context):
963         self.layout.template_preview(context.lamp)
964
965
966 class CYCLES_LAMP_PT_lamp(CyclesButtonsPanel, Panel):
967     bl_label = "Lamp"
968     bl_context = "data"
969
970     @classmethod
971     def poll(cls, context):
972         return context.lamp and CyclesButtonsPanel.poll(context)
973
974     def draw(self, context):
975         layout = self.layout
976
977         lamp = context.lamp
978         clamp = lamp.cycles
979         # cscene = context.scene.cycles
980
981         layout.prop(lamp, "type", expand=True)
982
983         split = layout.split()
984         col = split.column(align=True)
985
986         if lamp.type in {'POINT', 'SUN', 'SPOT'}:
987             col.prop(lamp, "shadow_soft_size", text="Size")
988         elif lamp.type == 'AREA':
989             col.prop(lamp, "shape", text="")
990             sub = col.column(align=True)
991
992             if lamp.shape == 'SQUARE':
993                 sub.prop(lamp, "size")
994             elif lamp.shape == 'RECTANGLE':
995                 sub.prop(lamp, "size", text="Size X")
996                 sub.prop(lamp, "size_y", text="Size Y")
997
998         if not (lamp.type == 'AREA' and clamp.is_portal):
999             sub = col.column(align=True)
1000             if use_branched_path(context):
1001                 subsub = sub.row(align=True)
1002                 subsub.active = use_sample_all_lights(context)
1003                 subsub.prop(clamp, "samples")
1004             sub.prop(clamp, "max_bounces")
1005
1006         col = split.column()
1007
1008         sub = col.column(align=True)
1009         sub.active = not (lamp.type == 'AREA' and clamp.is_portal)
1010         sub.prop(clamp, "cast_shadow")
1011         sub.prop(clamp, "use_multiple_importance_sampling", text="Multiple Importance")
1012
1013         if lamp.type == 'AREA':
1014             col.prop(clamp, "is_portal", text="Portal")
1015
1016         if lamp.type == 'HEMI':
1017             layout.label(text="Not supported, interpreted as sun lamp")
1018
1019
1020 class CYCLES_LAMP_PT_nodes(CyclesButtonsPanel, Panel):
1021     bl_label = "Nodes"
1022     bl_context = "data"
1023
1024     @classmethod
1025     def poll(cls, context):
1026         return context.lamp and not (context.lamp.type == 'AREA' and
1027                                      context.lamp.cycles.is_portal) and \
1028                CyclesButtonsPanel.poll(context)
1029
1030     def draw(self, context):
1031         layout = self.layout
1032
1033         lamp = context.lamp
1034         if not panel_node_draw(layout, lamp, 'OUTPUT_LAMP', 'Surface'):
1035             layout.prop(lamp, "color")
1036
1037
1038 class CYCLES_LAMP_PT_spot(CyclesButtonsPanel, Panel):
1039     bl_label = "Spot Shape"
1040     bl_context = "data"
1041
1042     @classmethod
1043     def poll(cls, context):
1044         lamp = context.lamp
1045         return (lamp and lamp.type == 'SPOT') and CyclesButtonsPanel.poll(context)
1046
1047     def draw(self, context):
1048         layout = self.layout
1049
1050         lamp = context.lamp
1051
1052         split = layout.split()
1053
1054         col = split.column()
1055         sub = col.column()
1056         sub.prop(lamp, "spot_size", text="Size")
1057         sub.prop(lamp, "spot_blend", text="Blend", slider=True)
1058
1059         col = split.column()
1060         col.prop(lamp, "show_cone")
1061
1062
1063 class CYCLES_WORLD_PT_preview(CyclesButtonsPanel, Panel):
1064     bl_label = "Preview"
1065     bl_context = "world"
1066     bl_options = {'DEFAULT_CLOSED'}
1067
1068     @classmethod
1069     def poll(cls, context):
1070         return context.world and CyclesButtonsPanel.poll(context)
1071
1072     def draw(self, context):
1073         self.layout.template_preview(context.world)
1074
1075
1076 class CYCLES_WORLD_PT_surface(CyclesButtonsPanel, Panel):
1077     bl_label = "Surface"
1078     bl_context = "world"
1079
1080     @classmethod
1081     def poll(cls, context):
1082         return context.world and CyclesButtonsPanel.poll(context)
1083
1084     def draw(self, context):
1085         layout = self.layout
1086
1087         world = context.world
1088
1089         if not panel_node_draw(layout, world, 'OUTPUT_WORLD', 'Surface'):
1090             layout.prop(world, "horizon_color", text="Color")
1091
1092
1093 class CYCLES_WORLD_PT_volume(CyclesButtonsPanel, Panel):
1094     bl_label = "Volume"
1095     bl_context = "world"
1096     bl_options = {'DEFAULT_CLOSED'}
1097
1098     @classmethod
1099     def poll(cls, context):
1100         world = context.world
1101         return world and world.node_tree and CyclesButtonsPanel.poll(context)
1102
1103     def draw(self, context):
1104         layout = self.layout
1105
1106         world = context.world
1107         panel_node_draw(layout, world, 'OUTPUT_WORLD', 'Volume')
1108
1109
1110 class CYCLES_WORLD_PT_ambient_occlusion(CyclesButtonsPanel, Panel):
1111     bl_label = "Ambient Occlusion"
1112     bl_context = "world"
1113
1114     @classmethod
1115     def poll(cls, context):
1116         return context.world and CyclesButtonsPanel.poll(context)
1117
1118     def draw_header(self, context):
1119         light = context.world.light_settings
1120         self.layout.prop(light, "use_ambient_occlusion", text="")
1121
1122     def draw(self, context):
1123         layout = self.layout
1124
1125         light = context.world.light_settings
1126         scene = context.scene
1127
1128         row = layout.row()
1129         sub = row.row()
1130         sub.active = light.use_ambient_occlusion or scene.render.use_simplify
1131         sub.prop(light, "ao_factor", text="Factor")
1132         row.prop(light, "distance", text="Distance")
1133
1134
1135 class CYCLES_WORLD_PT_mist(CyclesButtonsPanel, Panel):
1136     bl_label = "Mist Pass"
1137     bl_context = "world"
1138     bl_options = {'DEFAULT_CLOSED'}
1139
1140     @classmethod
1141     def poll(cls, context):
1142         if CyclesButtonsPanel.poll(context):
1143             if context.world:
1144                 for rl in context.scene.render.layers:
1145                     if rl.use_pass_mist:
1146                         return True
1147
1148         return False
1149
1150     def draw(self, context):
1151         layout = self.layout
1152
1153         world = context.world
1154
1155         split = layout.split(align=True)
1156         split.prop(world.mist_settings, "start")
1157         split.prop(world.mist_settings, "depth")
1158
1159         layout.prop(world.mist_settings, "falloff")
1160
1161
1162 class CYCLES_WORLD_PT_ray_visibility(CyclesButtonsPanel, Panel):
1163     bl_label = "Ray Visibility"
1164     bl_context = "world"
1165     bl_options = {'DEFAULT_CLOSED'}
1166
1167     @classmethod
1168     def poll(cls, context):
1169         return CyclesButtonsPanel.poll(context) and context.world
1170
1171     def draw(self, context):
1172         layout = self.layout
1173
1174         world = context.world
1175         visibility = world.cycles_visibility
1176
1177         flow = layout.column_flow()
1178
1179         flow.prop(visibility, "camera")
1180         flow.prop(visibility, "diffuse")
1181         flow.prop(visibility, "glossy")
1182         flow.prop(visibility, "transmission")
1183         flow.prop(visibility, "scatter")
1184
1185
1186 class CYCLES_WORLD_PT_settings(CyclesButtonsPanel, Panel):
1187     bl_label = "Settings"
1188     bl_context = "world"
1189     bl_options = {'DEFAULT_CLOSED'}
1190
1191     @classmethod
1192     def poll(cls, context):
1193         return context.world and CyclesButtonsPanel.poll(context)
1194
1195     def draw(self, context):
1196         layout = self.layout
1197
1198         world = context.world
1199         cworld = world.cycles
1200         # cscene = context.scene.cycles
1201
1202         split = layout.split()
1203
1204         col = split.column()
1205
1206         col.label(text="Surface:")
1207         col.prop(cworld, "sample_as_light", text="Multiple Importance")
1208
1209         sub = col.column(align=True)
1210         sub.active = cworld.sample_as_light
1211         sub.prop(cworld, "sample_map_resolution")
1212         if use_branched_path(context):
1213             subsub = sub.row(align=True)
1214             subsub.active = use_sample_all_lights(context)
1215             subsub.prop(cworld, "samples")
1216         sub.prop(cworld, "max_bounces")
1217
1218         col = split.column()
1219         col.label(text="Volume:")
1220         sub = col.column()
1221         sub.active = use_cpu(context)
1222         sub.prop(cworld, "volume_sampling", text="")
1223         col.prop(cworld, "volume_interpolation", text="")
1224         col.prop(cworld, "homogeneous_volume", text="Homogeneous")
1225
1226
1227 class CYCLES_MATERIAL_PT_preview(CyclesButtonsPanel, Panel):
1228     bl_label = "Preview"
1229     bl_context = "material"
1230     bl_options = {'DEFAULT_CLOSED'}
1231
1232     @classmethod
1233     def poll(cls, context):
1234         return context.material and CyclesButtonsPanel.poll(context)
1235
1236     def draw(self, context):
1237         self.layout.template_preview(context.material)
1238
1239
1240 class CYCLES_MATERIAL_PT_surface(CyclesButtonsPanel, Panel):
1241     bl_label = "Surface"
1242     bl_context = "material"
1243
1244     @classmethod
1245     def poll(cls, context):
1246         return context.material and CyclesButtonsPanel.poll(context)
1247
1248     def draw(self, context):
1249         layout = self.layout
1250
1251         mat = context.material
1252         if not panel_node_draw(layout, mat, 'OUTPUT_MATERIAL', 'Surface'):
1253             layout.prop(mat, "diffuse_color")
1254
1255
1256 class CYCLES_MATERIAL_PT_volume(CyclesButtonsPanel, Panel):
1257     bl_label = "Volume"
1258     bl_context = "material"
1259     bl_options = {'DEFAULT_CLOSED'}
1260
1261     @classmethod
1262     def poll(cls, context):
1263         mat = context.material
1264         return mat and mat.node_tree and CyclesButtonsPanel.poll(context)
1265
1266     def draw(self, context):
1267         layout = self.layout
1268
1269         mat = context.material
1270         # cmat = mat.cycles
1271
1272         panel_node_draw(layout, mat, 'OUTPUT_MATERIAL', 'Volume')
1273
1274
1275 class CYCLES_MATERIAL_PT_displacement(CyclesButtonsPanel, Panel):
1276     bl_label = "Displacement"
1277     bl_context = "material"
1278
1279     @classmethod
1280     def poll(cls, context):
1281         mat = context.material
1282         return mat and mat.node_tree and CyclesButtonsPanel.poll(context)
1283
1284     def draw(self, context):
1285         layout = self.layout
1286
1287         mat = context.material
1288         panel_node_draw(layout, mat, 'OUTPUT_MATERIAL', 'Displacement')
1289
1290
1291 class CYCLES_MATERIAL_PT_settings(CyclesButtonsPanel, Panel):
1292     bl_label = "Settings"
1293     bl_context = "material"
1294     bl_options = {'DEFAULT_CLOSED'}
1295
1296     @classmethod
1297     def poll(cls, context):
1298         return context.material and CyclesButtonsPanel.poll(context)
1299
1300     def draw(self, context):
1301         layout = self.layout
1302
1303         mat = context.material
1304         cmat = mat.cycles
1305
1306         split = layout.split()
1307         col = split.column()
1308         col.label(text="Surface:")
1309         col.prop(cmat, "sample_as_light", text="Multiple Importance")
1310         col.prop(cmat, "use_transparent_shadow")
1311
1312         if context.scene.cycles.feature_set == 'EXPERIMENTAL':
1313             col.separator()
1314             col.label(text="Displacement:")
1315             col.prop(cmat, "displacement_method", text="")
1316
1317         col = split.column()
1318         col.label(text="Volume:")
1319         sub = col.column()
1320         sub.active = use_cpu(context)
1321         sub.prop(cmat, "volume_sampling", text="")
1322         col.prop(cmat, "volume_interpolation", text="")
1323         col.prop(cmat, "homogeneous_volume", text="Homogeneous")
1324
1325         layout.separator()
1326         split = layout.split()
1327
1328         col = split.column(align=True)
1329         col.label("Viewport Color:")
1330         col.prop(mat, "diffuse_color", text="")
1331         col.prop(mat, "alpha")
1332
1333         col.separator()
1334         col.label("Viewport Alpha:")
1335         col.prop(mat.game_settings, "alpha_blend", text="")
1336
1337         col = split.column(align=True)
1338         col.label("Viewport Specular:")
1339         col.prop(mat, "specular_color", text="")
1340         col.prop(mat, "specular_hardness", text="Hardness")
1341
1342         col.separator()
1343         col.prop(mat, "pass_index")
1344
1345
1346 class CYCLES_TEXTURE_PT_context(CyclesButtonsPanel, Panel):
1347     bl_label = ""
1348     bl_context = "texture"
1349     bl_options = {'HIDE_HEADER'}
1350     COMPAT_ENGINES = {'CYCLES'}
1351
1352     def draw(self, context):
1353         layout = self.layout
1354
1355         tex = context.texture
1356         space = context.space_data
1357         pin_id = space.pin_id
1358         use_pin_id = space.use_pin_id
1359         user = context.texture_user
1360
1361         space.use_limited_texture_context = False
1362
1363         if not (use_pin_id and isinstance(pin_id, bpy.types.Texture)):
1364             pin_id = None
1365
1366         if not pin_id:
1367             layout.template_texture_user()
1368
1369         if user or pin_id:
1370             layout.separator()
1371
1372             split = layout.split(percentage=0.65)
1373             col = split.column()
1374
1375             if pin_id:
1376                 col.template_ID(space, "pin_id")
1377             else:
1378                 propname = context.texture_user_property.identifier
1379                 col.template_ID(user, propname, new="texture.new")
1380
1381             if tex:
1382                 split = layout.split(percentage=0.2)
1383                 split.label(text="Type:")
1384                 split.prop(tex, "type", text="")
1385
1386
1387 class CYCLES_TEXTURE_PT_node(CyclesButtonsPanel, Panel):
1388     bl_label = "Node"
1389     bl_context = "texture"
1390
1391     @classmethod
1392     def poll(cls, context):
1393         node = context.texture_node
1394         return node and CyclesButtonsPanel.poll(context)
1395
1396     def draw(self, context):
1397         layout = self.layout
1398
1399         node = context.texture_node
1400         ntree = node.id_data
1401         layout.template_node_view(ntree, node, None)
1402
1403
1404 class CYCLES_TEXTURE_PT_mapping(CyclesButtonsPanel, Panel):
1405     bl_label = "Mapping"
1406     bl_context = "texture"
1407
1408     @classmethod
1409     def poll(cls, context):
1410         node = context.texture_node
1411         # TODO(sergey): perform a faster/nicer check?
1412         return node and hasattr(node, 'texture_mapping') and CyclesButtonsPanel.poll(context)
1413
1414     def draw(self, context):
1415         layout = self.layout
1416
1417         node = context.texture_node
1418
1419         mapping = node.texture_mapping
1420
1421         layout.prop(mapping, "vector_type", expand=True)
1422
1423         row = layout.row()
1424
1425         row.column().prop(mapping, "translation")
1426         row.column().prop(mapping, "rotation")
1427         row.column().prop(mapping, "scale")
1428
1429         layout.label(text="Projection:")
1430
1431         row = layout.row()
1432         row.prop(mapping, "mapping_x", text="")
1433         row.prop(mapping, "mapping_y", text="")
1434         row.prop(mapping, "mapping_z", text="")
1435
1436
1437 class CYCLES_TEXTURE_PT_colors(CyclesButtonsPanel, Panel):
1438     bl_label = "Color"
1439     bl_context = "texture"
1440     bl_options = {'DEFAULT_CLOSED'}
1441
1442     @classmethod
1443     def poll(cls, context):
1444         # node = context.texture_node
1445         return False
1446         # return node and CyclesButtonsPanel.poll(context)
1447
1448     def draw(self, context):
1449         layout = self.layout
1450
1451         node = context.texture_node
1452
1453         mapping = node.color_mapping
1454
1455         split = layout.split()
1456
1457         col = split.column()
1458         col.label(text="Blend:")
1459         col.prop(mapping, "blend_type", text="")
1460         col.prop(mapping, "blend_factor", text="Factor")
1461         col.prop(mapping, "blend_color", text="")
1462
1463         col = split.column()
1464         col.label(text="Adjust:")
1465         col.prop(mapping, "brightness")
1466         col.prop(mapping, "contrast")
1467         col.prop(mapping, "saturation")
1468
1469         layout.separator()
1470
1471         layout.prop(mapping, "use_color_ramp", text="Ramp")
1472         if mapping.use_color_ramp:
1473             layout.template_color_ramp(mapping, "color_ramp", expand=True)
1474
1475
1476 class CYCLES_PARTICLE_PT_textures(CyclesButtonsPanel, Panel):
1477     bl_label = "Textures"
1478     bl_context = "particle"
1479     bl_options = {'DEFAULT_CLOSED'}
1480
1481     @classmethod
1482     def poll(cls, context):
1483         psys = context.particle_system
1484         return psys and CyclesButtonsPanel.poll(context)
1485
1486     def draw(self, context):
1487         layout = self.layout
1488
1489         psys = context.particle_system
1490         part = psys.settings
1491
1492         row = layout.row()
1493         row.template_list("TEXTURE_UL_texslots", "", part, "texture_slots", part, "active_texture_index", rows=2)
1494
1495         col = row.column(align=True)
1496         col.operator("texture.slot_move", text="", icon='TRIA_UP').type = 'UP'
1497         col.operator("texture.slot_move", text="", icon='TRIA_DOWN').type = 'DOWN'
1498         col.menu("TEXTURE_MT_specials", icon='DOWNARROW_HLT', text="")
1499
1500         if not part.active_texture:
1501             layout.template_ID(part, "active_texture", new="texture.new")
1502         else:
1503             slot = part.texture_slots[part.active_texture_index]
1504             layout.template_ID(slot, "texture", new="texture.new")
1505
1506
1507 class CYCLES_RENDER_PT_bake(CyclesButtonsPanel, Panel):
1508     bl_label = "Bake"
1509     bl_context = "render"
1510     bl_options = {'DEFAULT_CLOSED'}
1511     COMPAT_ENGINES = {'CYCLES'}
1512
1513     def draw(self, context):
1514         layout = self.layout
1515
1516         scene = context.scene
1517         cscene = scene.cycles
1518         cbk = scene.render.bake
1519
1520         layout.operator("object.bake", icon='RENDER_STILL').type = cscene.bake_type
1521
1522         col = layout.column()
1523         col.prop(cscene, "bake_type")
1524
1525         col = layout.column()
1526
1527         if cscene.bake_type == 'NORMAL':
1528             col.prop(cbk, "normal_space", text="Space")
1529
1530             row = col.row(align=True)
1531             row.label(text="Swizzle:")
1532             row.prop(cbk, "normal_r", text="")
1533             row.prop(cbk, "normal_g", text="")
1534             row.prop(cbk, "normal_b", text="")
1535
1536         elif cscene.bake_type == 'COMBINED':
1537             row = col.row(align=True)
1538             row.prop(cbk, "use_pass_direct", toggle=True)
1539             row.prop(cbk, "use_pass_indirect", toggle=True)
1540
1541             split = col.split()
1542             split.active = cbk.use_pass_direct or cbk.use_pass_indirect
1543
1544             col = split.column()
1545             col.prop(cbk, "use_pass_diffuse")
1546             col.prop(cbk, "use_pass_glossy")
1547             col.prop(cbk, "use_pass_transmission")
1548
1549             col = split.column()
1550             col.prop(cbk, "use_pass_subsurface")
1551             col.prop(cbk, "use_pass_ambient_occlusion")
1552             col.prop(cbk, "use_pass_emit")
1553
1554         elif cscene.bake_type in {'DIFFUSE', 'GLOSSY', 'TRANSMISSION', 'SUBSURFACE'}:
1555             row = col.row(align=True)
1556             row.prop(cbk, "use_pass_direct", toggle=True)
1557             row.prop(cbk, "use_pass_indirect", toggle=True)
1558             row.prop(cbk, "use_pass_color", toggle=True)
1559
1560         layout.separator()
1561
1562         split = layout.split()
1563
1564         col = split.column()
1565         col.prop(cbk, "margin")
1566         col.prop(cbk, "use_clear")
1567
1568         col = split.column()
1569         col.prop(cbk, "use_selected_to_active")
1570         sub = col.column()
1571         sub.active = cbk.use_selected_to_active
1572         sub.prop(cbk, "use_cage", text="Cage")
1573         if cbk.use_cage:
1574             sub.prop(cbk, "cage_extrusion", text="Extrusion")
1575             sub.prop_search(cbk, "cage_object", scene, "objects", text="")
1576         else:
1577             sub.prop(cbk, "cage_extrusion", text="Ray Distance")
1578
1579
1580 class CYCLES_RENDER_PT_debug(CyclesButtonsPanel, Panel):
1581     bl_label = "Debug"
1582     bl_context = "render"
1583     bl_options = {'DEFAULT_CLOSED'}
1584     COMPAT_ENGINES = {'CYCLES'}
1585
1586     @classmethod
1587     def poll(cls, context):
1588         return CyclesButtonsPanel.poll(context) and bpy.app.debug_value == 256
1589
1590     def draw(self, context):
1591         layout = self.layout
1592
1593         scene = context.scene
1594         cscene = scene.cycles
1595
1596         col = layout.column()
1597
1598         col.label('CPU Flags:')
1599         row = col.row(align=True)
1600         row.prop(cscene, "debug_use_cpu_sse2", toggle=True)
1601         row.prop(cscene, "debug_use_cpu_sse3", toggle=True)
1602         row.prop(cscene, "debug_use_cpu_sse41", toggle=True)
1603         row.prop(cscene, "debug_use_cpu_avx", toggle=True)
1604         row.prop(cscene, "debug_use_cpu_avx2", toggle=True)
1605         col.prop(cscene, "debug_use_qbvh")
1606         col.prop(cscene, "debug_use_cpu_split_kernel")
1607
1608         col.separator()
1609
1610         col = layout.column()
1611         col.label('CUDA Flags:')
1612         col.prop(cscene, "debug_use_cuda_adaptive_compile")
1613         col.prop(cscene, "debug_use_cuda_split_kernel")
1614
1615         col.separator()
1616
1617         col = layout.column()
1618         col.label('OpenCL Flags:')
1619         col.prop(cscene, "debug_opencl_kernel_type", text="Kernel")
1620         col.prop(cscene, "debug_opencl_device_type", text="Device")
1621         col.prop(cscene, "debug_opencl_kernel_single_program", text="Single Program")
1622         col.prop(cscene, "debug_use_opencl_debug", text="Debug")
1623         col.prop(cscene, "debug_opencl_mem_limit")
1624
1625         col.separator()
1626
1627         col = layout.column()
1628         col.prop(cscene, "debug_bvh_type")
1629
1630
1631 class CYCLES_PARTICLE_PT_curve_settings(CyclesButtonsPanel, Panel):
1632     bl_label = "Cycles Hair Settings"
1633     bl_context = "particle"
1634
1635     @classmethod
1636     def poll(cls, context):
1637         scene = context.scene
1638         ccscene = scene.cycles_curves
1639         psys = context.particle_system
1640         use_curves = ccscene.use_curves and psys
1641         return CyclesButtonsPanel.poll(context) and use_curves and psys.settings.type == 'HAIR'
1642
1643     def draw(self, context):
1644         layout = self.layout
1645
1646         psys = context.particle_settings
1647         cpsys = psys.cycles
1648
1649         row = layout.row()
1650         row.prop(cpsys, "shape", text="Shape")
1651
1652         layout.label(text="Thickness:")
1653         row = layout.row()
1654         row.prop(cpsys, "root_width", text="Root")
1655         row.prop(cpsys, "tip_width", text="Tip")
1656
1657         row = layout.row()
1658         row.prop(cpsys, "radius_scale", text="Scaling")
1659         row.prop(cpsys, "use_closetip", text="Close tip")
1660
1661
1662 class CYCLES_SCENE_PT_simplify(CyclesButtonsPanel, Panel):
1663     bl_label = "Simplify"
1664     bl_context = "scene"
1665     COMPAT_ENGINES = {'CYCLES'}
1666
1667     def draw_header(self, context):
1668         rd = context.scene.render
1669         self.layout.prop(rd, "use_simplify", text="")
1670
1671     def draw(self, context):
1672         layout = self.layout
1673
1674         scene = context.scene
1675         rd = scene.render
1676         cscene = scene.cycles
1677
1678         layout.active = rd.use_simplify
1679
1680         col = layout.column(align=True)
1681         col.label(text="Subdivision")
1682         row = col.row(align=True)
1683         row.prop(rd, "simplify_subdivision", text="Viewport")
1684         row.prop(rd, "simplify_subdivision_render", text="Render")
1685
1686         col = layout.column(align=True)
1687         col.label(text="Child Particles")
1688         row = col.row(align=True)
1689         row.prop(rd, "simplify_child_particles", text="Viewport")
1690         row.prop(rd, "simplify_child_particles_render", text="Render")
1691
1692         col = layout.column(align=True)
1693         split = col.split()
1694         sub = split.column()
1695         sub.label(text="Texture Limit Viewport")
1696         sub.prop(cscene, "texture_limit", text="")
1697         sub = split.column()
1698         sub.label(text="Texture Limit Render")
1699         sub.prop(cscene, "texture_limit_render", text="")
1700
1701         split = layout.split()
1702         col = split.column()
1703         col.prop(cscene, "use_camera_cull")
1704         row = col.row()
1705         row.active = cscene.use_camera_cull
1706         row.prop(cscene, "camera_cull_margin")
1707
1708         col = split.column()
1709         col.prop(cscene, "use_distance_cull")
1710         row = col.row()
1711         row.active = cscene.use_distance_cull
1712         row.prop(cscene, "distance_cull_margin", text="Distance")
1713
1714         split = layout.split()
1715         col = split.column()
1716         col.prop(cscene, "ao_bounces")
1717
1718         col = split.column()
1719         col.prop(cscene, "ao_bounces_render")
1720
1721 def draw_device(self, context):
1722     scene = context.scene
1723     layout = self.layout
1724
1725     if scene.render.engine == 'CYCLES':
1726         from . import engine
1727         cscene = scene.cycles
1728
1729         layout.prop(cscene, "feature_set")
1730
1731         split = layout.split(percentage=1 / 3)
1732         split.label("Device:")
1733         row = split.row()
1734         row.active = show_device_active(context)
1735         row.prop(cscene, "device", text="")
1736
1737         if engine.with_osl() and use_cpu(context):
1738             layout.prop(cscene, "shading_system")
1739
1740
1741 def draw_pause(self, context):
1742     layout = self.layout
1743     scene = context.scene
1744
1745     if scene.render.engine == "CYCLES":
1746         view = context.space_data
1747
1748         if view.viewport_shade == 'RENDERED':
1749             cscene = scene.cycles
1750             layername = scene.render.layers.active.name
1751             layout.prop(cscene, "preview_pause", icon="PAUSE", text="")
1752             layout.prop(cscene, "preview_active_layer", icon="RENDERLAYERS", text=layername)
1753
1754
1755 def get_panels():
1756     exclude_panels = {
1757         'DATA_PT_area',
1758         'DATA_PT_camera_dof',
1759         'DATA_PT_falloff_curve',
1760         'DATA_PT_lamp',
1761         'DATA_PT_preview',
1762         'DATA_PT_shadow',
1763         'DATA_PT_spot',
1764         'DATA_PT_sunsky',
1765         'MATERIAL_PT_context_material',
1766         'MATERIAL_PT_diffuse',
1767         'MATERIAL_PT_flare',
1768         'MATERIAL_PT_halo',
1769         'MATERIAL_PT_mirror',
1770         'MATERIAL_PT_options',
1771         'MATERIAL_PT_pipeline',
1772         'MATERIAL_PT_preview',
1773         'MATERIAL_PT_shading',
1774         'MATERIAL_PT_shadow',
1775         'MATERIAL_PT_specular',
1776         'MATERIAL_PT_sss',
1777         'MATERIAL_PT_strand',
1778         'MATERIAL_PT_transp',
1779         'MATERIAL_PT_volume_density',
1780         'MATERIAL_PT_volume_integration',
1781         'MATERIAL_PT_volume_lighting',
1782         'MATERIAL_PT_volume_options',
1783         'MATERIAL_PT_volume_shading',
1784         'MATERIAL_PT_volume_transp',
1785         'RENDERLAYER_PT_layer_options',
1786         'RENDERLAYER_PT_layer_passes',
1787         'RENDERLAYER_PT_views',
1788         'RENDER_PT_antialiasing',
1789         'RENDER_PT_bake',
1790         'RENDER_PT_motion_blur',
1791         'RENDER_PT_performance',
1792         'RENDER_PT_post_processing',
1793         'RENDER_PT_shading',
1794         'SCENE_PT_simplify',
1795         'TEXTURE_PT_context_texture',
1796         'WORLD_PT_ambient_occlusion',
1797         'WORLD_PT_environment_lighting',
1798         'WORLD_PT_gather',
1799         'WORLD_PT_indirect_lighting',
1800         'WORLD_PT_mist',
1801         'WORLD_PT_preview',
1802         'WORLD_PT_world'
1803         }
1804
1805     panels = []
1806     for panel in bpy.types.Panel.__subclasses__():
1807         if hasattr(panel, 'COMPAT_ENGINES') and 'BLENDER_RENDER' in panel.COMPAT_ENGINES:
1808             if panel.__name__ not in exclude_panels:
1809                 panels.append(panel)
1810
1811     return panels
1812
1813
1814 classes = (
1815     CYCLES_MT_sampling_presets,
1816     CYCLES_MT_integrator_presets,
1817     CYCLES_RENDER_PT_sampling,
1818     CYCLES_RENDER_PT_geometry,
1819     CYCLES_RENDER_PT_light_paths,
1820     CYCLES_RENDER_PT_motion_blur,
1821     CYCLES_RENDER_PT_film,
1822     CYCLES_RENDER_PT_performance,
1823     CYCLES_RENDER_PT_layer_options,
1824     CYCLES_RENDER_PT_layer_passes,
1825     CYCLES_RENDER_PT_views,
1826     CYCLES_RENDER_PT_denoising,
1827     CYCLES_PT_post_processing,
1828     CYCLES_CAMERA_PT_dof,
1829     CYCLES_PT_context_material,
1830     CYCLES_OBJECT_PT_motion_blur,
1831     CYCLES_OBJECT_PT_cycles_settings,
1832     CYCLES_OT_use_shading_nodes,
1833     CYCLES_LAMP_PT_preview,
1834     CYCLES_LAMP_PT_lamp,
1835     CYCLES_LAMP_PT_nodes,
1836     CYCLES_LAMP_PT_spot,
1837     CYCLES_WORLD_PT_preview,
1838     CYCLES_WORLD_PT_surface,
1839     CYCLES_WORLD_PT_volume,
1840     CYCLES_WORLD_PT_ambient_occlusion,
1841     CYCLES_WORLD_PT_mist,
1842     CYCLES_WORLD_PT_ray_visibility,
1843     CYCLES_WORLD_PT_settings,
1844     CYCLES_MATERIAL_PT_preview,
1845     CYCLES_MATERIAL_PT_surface,
1846     CYCLES_MATERIAL_PT_volume,
1847     CYCLES_MATERIAL_PT_displacement,
1848     CYCLES_MATERIAL_PT_settings,
1849     CYCLES_TEXTURE_PT_context,
1850     CYCLES_TEXTURE_PT_node,
1851     CYCLES_TEXTURE_PT_mapping,
1852     CYCLES_TEXTURE_PT_colors,
1853     CYCLES_PARTICLE_PT_textures,
1854     CYCLES_RENDER_PT_bake,
1855     CYCLES_RENDER_PT_debug,
1856     CYCLES_PARTICLE_PT_curve_settings,
1857     CYCLES_SCENE_PT_simplify,
1858 )
1859
1860
1861 def register():
1862     from bpy.utils import register_class
1863
1864     bpy.types.RENDER_PT_render.append(draw_device)
1865     bpy.types.VIEW3D_HT_header.append(draw_pause)
1866
1867     for panel in get_panels():
1868         panel.COMPAT_ENGINES.add('CYCLES')
1869
1870     for cls in classes:
1871         register_class(cls)
1872
1873
1874 def unregister():
1875     from bpy.utils import unregister_class
1876
1877     bpy.types.RENDER_PT_render.remove(draw_device)
1878     bpy.types.VIEW3D_HT_header.remove(draw_pause)
1879
1880     for panel in get_panels():
1881         if 'CYCLES' in panel.COMPAT_ENGINES:
1882             panel.COMPAT_ENGINES.remove('CYCLES')
1883
1884     for cls in classes:
1885         unregister_class(cls)