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