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