Merge branch 'master' into blender2.8
[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 use_cpu(context):
57     cscene = context.scene.cycles
58     device_type = context.user_preferences.system.compute_device_type
59
60     return (device_type == 'NONE' or cscene.device == 'CPU')
61
62
63 def use_opencl(context):
64     cscene = context.scene.cycles
65     device_type = context.user_preferences.system.compute_device_type
66
67     return (device_type == 'OPENCL' and cscene.device == 'GPU')
68
69
70 def use_cuda(context):
71     cscene = context.scene.cycles
72     device_type = context.user_preferences.system.compute_device_type
73
74     return (device_type == 'CUDA' and cscene.device == 'GPU')
75
76
77 def use_branched_path(context):
78     cscene = context.scene.cycles
79
80     return (cscene.progressive == 'BRANCHED_PATH' and not use_opencl(context))
81
82
83 def use_sample_all_lights(context):
84     cscene = context.scene.cycles
85
86     return cscene.sample_all_lights_direct or cscene.sample_all_lights_indirect
87
88
89 def draw_samples_info(layout, context):
90     cscene = context.scene.cycles
91     integrator = cscene.progressive
92
93     # Calculate sample values
94     if integrator == 'PATH':
95         aa = cscene.samples
96         if cscene.use_square_samples:
97             aa = aa * aa
98     else:
99         aa = cscene.aa_samples
100         d = cscene.diffuse_samples
101         g = cscene.glossy_samples
102         t = cscene.transmission_samples
103         ao = cscene.ao_samples
104         ml = cscene.mesh_light_samples
105         sss = cscene.subsurface_samples
106         vol = cscene.volume_samples
107
108         if cscene.use_square_samples:
109             aa = aa * aa
110             d = d * d
111             g = g * g
112             t = t * t
113             ao = ao * ao
114             ml = ml * ml
115             sss = sss * sss
116             vol = vol * vol
117
118     # Draw interface
119     # Do not draw for progressive, when Square Samples are disabled
120     if use_branched_path(context) or (cscene.use_square_samples and integrator == 'PATH'):
121         col = layout.column(align=True)
122         col.scale_y = 0.6
123         col.label("Total Samples:")
124         col.separator()
125         if integrator == 'PATH':
126             col.label("%s AA" % aa)
127         else:
128             col.label("%s AA, %s Diffuse, %s Glossy, %s Transmission" %
129                       (aa, d * aa, g * aa, t * aa))
130             col.separator()
131             col.label("%s AO, %s Mesh Light, %s Subsurface, %s Volume" %
132                       (ao * aa, ml * aa, sss * aa, vol * aa))
133
134
135 class CyclesRender_PT_sampling(CyclesButtonsPanel, Panel):
136     bl_label = "Sampling"
137     bl_options = {'DEFAULT_CLOSED'}
138
139     def draw(self, context):
140         layout = self.layout
141
142         scene = context.scene
143         cscene = scene.cycles
144         device_type = context.user_preferences.system.compute_device_type
145
146         row = layout.row(align=True)
147         row.menu("CYCLES_MT_sampling_presets", text=bpy.types.CYCLES_MT_sampling_presets.bl_label)
148         row.operator("render.cycles_sampling_preset_add", text="", icon="ZOOMIN")
149         row.operator("render.cycles_sampling_preset_add", text="", icon="ZOOMOUT").remove_active = True
150
151         row = layout.row()
152         sub = row.row()
153         sub.active = device_type != 'OPENCL' or use_cpu(context)
154         sub.prop(cscene, "progressive", text="")
155         row.prop(cscene, "use_square_samples")
156
157         split = layout.split()
158
159         col = split.column()
160         sub = col.column(align=True)
161         sub.label("Settings:")
162
163         seed_sub = sub.row(align=True)
164         seed_sub.prop(cscene, "seed")
165         seed_sub.prop(cscene, "use_animated_seed", text="", icon="TIME")
166
167         sub.prop(cscene, "sample_clamp_direct")
168         sub.prop(cscene, "sample_clamp_indirect")
169
170         if cscene.progressive == 'PATH' or use_branched_path(context) is False:
171             col = split.column()
172             sub = col.column(align=True)
173             sub.label(text="Samples:")
174             sub.prop(cscene, "samples", text="Render")
175             sub.prop(cscene, "preview_samples", text="Preview")
176         else:
177             sub.label(text="AA Samples:")
178             sub.prop(cscene, "aa_samples", text="Render")
179             sub.prop(cscene, "preview_aa_samples", text="Preview")
180             sub.separator()
181             sub.prop(cscene, "sample_all_lights_direct")
182             sub.prop(cscene, "sample_all_lights_indirect")
183
184             col = split.column()
185             sub = col.column(align=True)
186             sub.label(text="Samples:")
187             sub.prop(cscene, "diffuse_samples", text="Diffuse")
188             sub.prop(cscene, "glossy_samples", text="Glossy")
189             sub.prop(cscene, "transmission_samples", text="Transmission")
190             sub.prop(cscene, "ao_samples", text="AO")
191
192             subsub = sub.row(align=True)
193             subsub.active = use_sample_all_lights(context)
194             subsub.prop(cscene, "mesh_light_samples", text="Mesh Light")
195
196             sub.prop(cscene, "subsurface_samples", text="Subsurface")
197             sub.prop(cscene, "volume_samples", text="Volume")
198
199         if not (use_opencl(context) and cscene.feature_set != 'EXPERIMENTAL'):
200             layout.row().prop(cscene, "sampling_pattern", text="Pattern")
201
202         for rl in scene.render.layers:
203             if rl.samples > 0:
204                 layout.separator()
205                 layout.row().prop(cscene, "use_layer_samples")
206                 break
207
208         draw_samples_info(layout, context)
209
210
211 class CyclesRender_PT_geometery(CyclesButtonsPanel, Panel):
212     bl_label = "Geometry"
213     bl_options = {'DEFAULT_CLOSED'}
214
215     def draw(self, context):
216         layout = self.layout
217
218         scene = context.scene
219         cscene = scene.cycles
220
221         if cscene.feature_set == 'EXPERIMENTAL':
222             split = layout.split()
223
224             col = split.column()
225
226             sub = col.column(align=True)
227             sub.label("Volume Sampling:")
228             sub.prop(cscene, "volume_step_size")
229             sub.prop(cscene, "volume_max_steps")
230
231             col = split.column()
232
233             sub = col.column(align=True)
234             sub.label("Subdivision Rate:")
235             sub.prop(cscene, "dicing_rate", text="Render")
236             sub.prop(cscene, "preview_dicing_rate", text="Preview")
237             sub.separator()
238             sub.prop(cscene, "max_subdivisions")
239         else:
240             row = layout.row()
241             row.label("Volume Sampling:")
242             row = layout.row()
243             row.prop(cscene, "volume_step_size")
244             row.prop(cscene, "volume_max_steps")
245
246
247 class CyclesRender_PT_light_paths(CyclesButtonsPanel, Panel):
248     bl_label = "Light Paths"
249     bl_options = {'DEFAULT_CLOSED'}
250
251     def draw(self, context):
252         layout = self.layout
253
254         scene = context.scene
255         cscene = scene.cycles
256
257         row = layout.row(align=True)
258         row.menu("CYCLES_MT_integrator_presets", text=bpy.types.CYCLES_MT_integrator_presets.bl_label)
259         row.operator("render.cycles_integrator_preset_add", text="", icon="ZOOMIN")
260         row.operator("render.cycles_integrator_preset_add", text="", icon="ZOOMOUT").remove_active = True
261
262         split = layout.split()
263
264         col = split.column()
265
266         sub = col.column(align=True)
267         sub.label("Transparency:")
268         sub.prop(cscene, "transparent_max_bounces", text="Max")
269         sub.prop(cscene, "transparent_min_bounces", text="Min")
270         sub.prop(cscene, "use_transparent_shadows", text="Shadows")
271
272         col.separator()
273
274         col.prop(cscene, "caustics_reflective")
275         col.prop(cscene, "caustics_refractive")
276         col.prop(cscene, "blur_glossy")
277
278         col = split.column()
279
280         sub = col.column(align=True)
281         sub.label(text="Bounces:")
282         sub.prop(cscene, "max_bounces", text="Max")
283         sub.prop(cscene, "min_bounces", text="Min")
284
285         sub = col.column(align=True)
286         sub.prop(cscene, "diffuse_bounces", text="Diffuse")
287         sub.prop(cscene, "glossy_bounces", text="Glossy")
288         sub.prop(cscene, "transmission_bounces", text="Transmission")
289         sub.prop(cscene, "volume_bounces", text="Volume")
290
291
292 class CyclesRender_PT_motion_blur(CyclesButtonsPanel, Panel):
293     bl_label = "Motion Blur"
294     bl_options = {'DEFAULT_CLOSED'}
295
296     def draw_header(self, context):
297         rd = context.scene.render
298
299         self.layout.prop(rd, "use_motion_blur", text="")
300
301     def draw(self, context):
302         layout = self.layout
303
304         scene = context.scene
305         cscene = scene.cycles
306         rd = scene.render
307         layout.active = rd.use_motion_blur
308
309         col = layout.column()
310         col.prop(cscene, "motion_blur_position", text="Position")
311         col.prop(rd, "motion_blur_shutter")
312
313         col = layout.column()
314         col.label("Shutter curve:")
315         col.template_curve_mapping(rd, "motion_blur_shutter_curve")
316
317         col = layout.column(align=True)
318         row = col.row(align=True)
319         row.operator("render.shutter_curve_preset", icon='SMOOTHCURVE', text="").shape = 'SMOOTH'
320         row.operator("render.shutter_curve_preset", icon='SPHERECURVE', text="").shape = 'ROUND'
321         row.operator("render.shutter_curve_preset", icon='ROOTCURVE', text="").shape = 'ROOT'
322         row.operator("render.shutter_curve_preset", icon='SHARPCURVE', text="").shape = 'SHARP'
323         row.operator("render.shutter_curve_preset", icon='LINCURVE', text="").shape = 'LINE'
324         row.operator("render.shutter_curve_preset", icon='NOCURVE', text="").shape = 'MAX'
325
326         col = layout.column()
327         col.prop(cscene, "rolling_shutter_type")
328         row = col.row()
329         row.active = cscene.rolling_shutter_type != 'NONE'
330         row.prop(cscene, "rolling_shutter_duration")
331
332
333 class CyclesRender_PT_film(CyclesButtonsPanel, Panel):
334     bl_label = "Film"
335
336     def draw(self, context):
337         layout = self.layout
338
339         scene = context.scene
340         cscene = scene.cycles
341
342         split = layout.split()
343
344         col = split.column()
345         col.prop(cscene, "film_exposure")
346         col.prop(cscene, "film_transparent")
347
348         col = split.column()
349         sub = col.column(align=True)
350         sub.prop(cscene, "pixel_filter_type", text="")
351         if cscene.pixel_filter_type != 'BOX':
352             sub.prop(cscene, "filter_width", text="Width")
353
354
355 class CyclesRender_PT_performance(CyclesButtonsPanel, Panel):
356     bl_label = "Performance"
357     bl_options = {'DEFAULT_CLOSED'}
358
359     def draw(self, context):
360         layout = self.layout
361
362         scene = context.scene
363         rd = scene.render
364         cscene = scene.cycles
365
366         split = layout.split()
367
368         col = split.column(align=True)
369
370         col.label(text="Threads:")
371         col.row(align=True).prop(rd, "threads_mode", expand=True)
372         sub = col.column(align=True)
373         sub.enabled = rd.threads_mode == 'FIXED'
374         sub.prop(rd, "threads")
375
376         sub = col.column(align=True)
377         sub.label(text="Tiles:")
378         sub.prop(cscene, "tile_order", text="")
379
380         sub.prop(rd, "tile_x", text="X")
381         sub.prop(rd, "tile_y", text="Y")
382
383         sub.prop(cscene, "use_progressive_refine")
384
385         subsub = sub.column(align=True)
386         subsub.enabled = not rd.use_border
387         subsub.prop(rd, "use_save_buffers")
388
389         col = split.column(align=True)
390
391         col.label(text="Viewport:")
392         col.prop(cscene, "debug_bvh_type", text="")
393         col.separator()
394         col.prop(cscene, "preview_start_resolution")
395
396         col.separator()
397
398         col.label(text="Final Render:")
399         col.prop(rd, "use_persistent_data", text="Persistent Images")
400
401         col.separator()
402
403         col.label(text="Acceleration structure:")
404         col.prop(cscene, "debug_use_spatial_splits")
405
406
407 class CyclesRender_PT_layer_options(CyclesButtonsPanel, Panel):
408     bl_label = "Layer"
409     bl_context = "render_layer"
410
411     def draw(self, context):
412         layout = self.layout
413
414         scene = context.scene
415         rd = scene.render
416         rl = rd.layers.active
417
418         split = layout.split()
419
420         col = split.column()
421         col.prop(scene, "layers", text="Scene")
422         col.prop(rl, "layers_exclude", text="Exclude")
423
424         col = split.column()
425         col.prop(rl, "layers", text="Layer")
426         col.prop(rl, "layers_zmask", text="Mask Layer")
427
428         split = layout.split()
429
430         col = split.column()
431         col.label(text="Material:")
432         col.prop(rl, "material_override", text="")
433         col.separator()
434         col.prop(rl, "samples")
435
436         col = split.column()
437         col.prop(rl, "use_sky", "Use Environment")
438         col.prop(rl, "use_ao", "Use AO")
439         col.prop(rl, "use_solid", "Use Surfaces")
440         col.prop(rl, "use_strand", "Use Hair")
441
442
443 class CyclesRender_PT_layer_passes(CyclesButtonsPanel, Panel):
444     bl_label = "Passes"
445     bl_context = "render_layer"
446     bl_options = {'DEFAULT_CLOSED'}
447
448     def draw(self, context):
449         layout = self.layout
450
451         scene = context.scene
452         rd = scene.render
453         rl = rd.layers.active
454
455         split = layout.split()
456
457         col = split.column()
458         col.prop(rl, "use_pass_combined")
459         col.prop(rl, "use_pass_z")
460         col.prop(rl, "use_pass_mist")
461         col.prop(rl, "use_pass_normal")
462         col.prop(rl, "use_pass_vector")
463         col.prop(rl, "use_pass_uv")
464         col.prop(rl, "use_pass_object_index")
465         col.prop(rl, "use_pass_material_index")
466         col.separator()
467         col.prop(rl, "use_pass_shadow")
468         col.prop(rl, "use_pass_ambient_occlusion")
469         col.separator()
470         col.prop(rl, "pass_alpha_threshold")
471
472         col = split.column()
473         col.label(text="Diffuse:")
474         row = col.row(align=True)
475         row.prop(rl, "use_pass_diffuse_direct", text="Direct", toggle=True)
476         row.prop(rl, "use_pass_diffuse_indirect", text="Indirect", toggle=True)
477         row.prop(rl, "use_pass_diffuse_color", text="Color", toggle=True)
478         col.label(text="Glossy:")
479         row = col.row(align=True)
480         row.prop(rl, "use_pass_glossy_direct", text="Direct", toggle=True)
481         row.prop(rl, "use_pass_glossy_indirect", text="Indirect", toggle=True)
482         row.prop(rl, "use_pass_glossy_color", text="Color", toggle=True)
483         col.label(text="Transmission:")
484         row = col.row(align=True)
485         row.prop(rl, "use_pass_transmission_direct", text="Direct", toggle=True)
486         row.prop(rl, "use_pass_transmission_indirect", text="Indirect", toggle=True)
487         row.prop(rl, "use_pass_transmission_color", text="Color", toggle=True)
488         col.label(text="Subsurface:")
489         row = col.row(align=True)
490         row.prop(rl, "use_pass_subsurface_direct", text="Direct", toggle=True)
491         row.prop(rl, "use_pass_subsurface_indirect", text="Indirect", toggle=True)
492         row.prop(rl, "use_pass_subsurface_color", text="Color", toggle=True)
493
494         col.separator()
495         col.prop(rl, "use_pass_emit", text="Emission")
496         col.prop(rl, "use_pass_environment")
497
498         if hasattr(rd, "debug_pass_type"):
499             layout.prop(rd, "debug_pass_type")
500
501
502 class CyclesRender_PT_views(CyclesButtonsPanel, Panel):
503     bl_label = "Views"
504     bl_context = "render_layer"
505     bl_options = {'DEFAULT_CLOSED'}
506
507     def draw_header(self, context):
508         rd = context.scene.render
509         self.layout.prop(rd, "use_multiview", text="")
510
511     def draw(self, context):
512         layout = self.layout
513
514         scene = context.scene
515         rd = scene.render
516         rv = rd.views.active
517
518         layout.active = rd.use_multiview
519         basic_stereo = (rd.views_format == 'STEREO_3D')
520
521         row = layout.row()
522         row.prop(rd, "views_format", expand=True)
523
524         if basic_stereo:
525             row = layout.row()
526             row.template_list("RENDERLAYER_UL_renderviews", "name", rd, "stereo_views", rd.views, "active_index", rows=2)
527
528             row = layout.row()
529             row.label(text="File Suffix:")
530             row.prop(rv, "file_suffix", text="")
531
532         else:
533             row = layout.row()
534             row.template_list("RENDERLAYER_UL_renderviews", "name", rd, "views", rd.views, "active_index", rows=2)
535
536             col = row.column(align=True)
537             col.operator("scene.render_view_add", icon='ZOOMIN', text="")
538             col.operator("scene.render_view_remove", icon='ZOOMOUT', text="")
539
540             row = layout.row()
541             row.label(text="Camera Suffix:")
542             row.prop(rv, "camera_suffix", text="")
543
544
545 class Cycles_PT_post_processing(CyclesButtonsPanel, Panel):
546     bl_label = "Post Processing"
547     bl_options = {'DEFAULT_CLOSED'}
548
549     def draw(self, context):
550         layout = self.layout
551
552         rd = context.scene.render
553
554         split = layout.split()
555
556         col = split.column()
557         col.prop(rd, "use_compositing")
558         col.prop(rd, "use_sequencer")
559
560         col = split.column()
561         col.prop(rd, "dither_intensity", text="Dither", slider=True)
562
563
564 class CyclesCamera_PT_dof(CyclesButtonsPanel, Panel):
565     bl_label = "Depth of Field"
566     bl_context = "data"
567
568     @classmethod
569     def poll(cls, context):
570         return context.camera and CyclesButtonsPanel.poll(context)
571
572     def draw(self, context):
573         layout = self.layout
574
575         cam = context.camera
576         ccam = cam.cycles
577         dof_options = cam.gpu_dof
578
579         split = layout.split()
580
581         col = split.column()
582         col.label("Focus:")
583         col.prop(cam, "dof_object", text="")
584
585         sub = col.row()
586         sub.active = cam.dof_object is None
587         sub.prop(cam, "dof_distance", text="Distance")
588
589         hq_support = dof_options.is_hq_supported
590         sub = col.column(align=True)
591         sub.label("Viewport:")
592         subhq = sub.column()
593         subhq.active = hq_support
594         subhq.prop(dof_options, "use_high_quality")
595         sub.prop(dof_options, "fstop")
596         if dof_options.use_high_quality and hq_support:
597             sub.prop(dof_options, "blades")
598
599         col = split.column()
600
601         col.label("Aperture:")
602         sub = col.column(align=True)
603         sub.prop(ccam, "aperture_type", text="")
604         if ccam.aperture_type == 'RADIUS':
605             sub.prop(ccam, "aperture_size", text="Size")
606         elif ccam.aperture_type == 'FSTOP':
607             sub.prop(ccam, "aperture_fstop", text="Number")
608
609         sub = col.column(align=True)
610         sub.prop(ccam, "aperture_blades", text="Blades")
611         sub.prop(ccam, "aperture_rotation", text="Rotation")
612         sub.prop(ccam, "aperture_ratio", text="Ratio")
613
614
615 class Cycles_PT_context_material(CyclesButtonsPanel, Panel):
616     bl_label = ""
617     bl_context = "material"
618     bl_options = {'HIDE_HEADER'}
619
620     @classmethod
621     def poll(cls, context):
622         return (context.material or context.object) and CyclesButtonsPanel.poll(context)
623
624     def draw(self, context):
625         layout = self.layout
626
627         mat = context.material
628         ob = context.object
629         slot = context.material_slot
630         space = context.space_data
631
632         if ob:
633             is_sortable = len(ob.material_slots) > 1
634             rows = 1
635             if (is_sortable):
636                 rows = 4
637
638             row = layout.row()
639
640             row.template_list("MATERIAL_UL_matslots", "", ob, "material_slots", ob, "active_material_index", rows=rows)
641
642             col = row.column(align=True)
643             col.operator("object.material_slot_add", icon='ZOOMIN', text="")
644             col.operator("object.material_slot_remove", icon='ZOOMOUT', text="")
645
646             col.menu("MATERIAL_MT_specials", icon='DOWNARROW_HLT', text="")
647
648             if is_sortable:
649                 col.separator()
650
651                 col.operator("object.material_slot_move", icon='TRIA_UP', text="").direction = 'UP'
652                 col.operator("object.material_slot_move", icon='TRIA_DOWN', text="").direction = 'DOWN'
653
654             if ob.mode == 'EDIT':
655                 row = layout.row(align=True)
656                 row.operator("object.material_slot_assign", text="Assign")
657                 row.operator("object.material_slot_select", text="Select")
658                 row.operator("object.material_slot_deselect", text="Deselect")
659
660         split = layout.split(percentage=0.65)
661
662         if ob:
663             split.template_ID(ob, "active_material", new="material.new")
664             row = split.row()
665
666             if slot:
667                 row.prop(slot, "link", text="")
668             else:
669                 row.label()
670         elif mat:
671             split.template_ID(space, "pin_id")
672             split.separator()
673
674
675 class Cycles_PT_mesh_displacement(CyclesButtonsPanel, Panel):
676     bl_label = "Displacement"
677     bl_context = "data"
678
679     @classmethod
680     def poll(cls, context):
681         if CyclesButtonsPanel.poll(context):
682             if context.mesh or context.curve or context.meta_ball:
683                 if context.scene.cycles.feature_set == 'EXPERIMENTAL':
684                     return True
685
686         return False
687
688     def draw(self, context):
689         layout = self.layout
690
691         mesh = context.mesh
692         curve = context.curve
693         mball = context.meta_ball
694
695         if mesh:
696             cdata = mesh.cycles
697         elif curve:
698             cdata = curve.cycles
699         elif mball:
700             cdata = mball.cycles
701
702         split = layout.split()
703
704         col = split.column()
705         sub = col.column(align=True)
706         sub.label(text="Displacement:")
707         sub.prop(cdata, "displacement_method", text="")
708
709         col = split.column()
710         sub = col.column(align=True)
711         sub.label(text="Subdivision:")
712         sub.prop(cdata, "subdivision_type", text="")
713
714         if cdata.subdivision_type != 'NONE':
715             sub.prop(cdata, "dicing_rate")
716
717 class CyclesObject_PT_motion_blur(CyclesButtonsPanel, Panel):
718     bl_label = "Motion Blur"
719     bl_context = "object"
720     bl_options = {'DEFAULT_CLOSED'}
721
722     @classmethod
723     def poll(cls, context):
724         ob = context.object
725         if CyclesButtonsPanel.poll(context) and ob:
726             if ob.type in {'MESH', 'CURVE', 'CURVE', 'SURFACE', 'FONT', 'META'}:
727                 return True
728             if ob.dupli_type == 'GROUP' and ob.dupli_group:
729                 return True
730             # TODO(sergey): More duplicator types here?
731         return False
732
733     def draw_header(self, context):
734         layout = self.layout
735
736         rd = context.scene.render
737         # scene = context.scene
738
739         layout.active = rd.use_motion_blur
740
741         ob = context.object
742         cob = ob.cycles
743
744         layout.prop(cob, "use_motion_blur", text="")
745
746     def draw(self, context):
747         layout = self.layout
748
749         rd = context.scene.render
750         # scene = context.scene
751
752         ob = context.object
753         cob = ob.cycles
754
755         layout.active = (rd.use_motion_blur and cob.use_motion_blur)
756
757         row = layout.row()
758         row.prop(cob, "use_deform_motion", text="Deformation")
759
760         sub = row.row()
761         sub.active = cob.use_deform_motion
762         sub.prop(cob, "motion_steps", text="Steps")
763
764
765 class CyclesObject_PT_cycles_settings(CyclesButtonsPanel, Panel):
766     bl_label = "Cycles Settings"
767     bl_context = "object"
768     bl_options = {'DEFAULT_CLOSED'}
769
770     @classmethod
771     def poll(cls, context):
772         ob = context.object
773         return (CyclesButtonsPanel.poll(context) and
774                 ob and ((ob.type in {'MESH', 'CURVE', 'SURFACE', 'FONT', 'META', 'LAMP'}) or
775                         (ob.dupli_type == 'GROUP' and ob.dupli_group)))
776
777     def draw(self, context):
778         layout = self.layout
779
780         scene = context.scene
781         cscene = scene.cycles
782         ob = context.object
783         cob = ob.cycles
784         visibility = ob.cycles_visibility
785
786         layout.label(text="Ray Visibility:")
787         flow = layout.column_flow()
788
789         flow.prop(visibility, "camera")
790         flow.prop(visibility, "diffuse")
791         flow.prop(visibility, "glossy")
792         flow.prop(visibility, "transmission")
793         flow.prop(visibility, "scatter")
794
795         if ob.type != 'LAMP':
796             flow.prop(visibility, "shadow")
797
798         col = layout.column()
799         col.label(text="Performance:")
800         row = col.row()
801         row.active = scene.render.use_simplify and cscene.use_camera_cull
802         row.prop(cob, "use_camera_cull")
803
804
805 class CYCLES_OT_use_shading_nodes(Operator):
806     """Enable nodes on a material, world or lamp"""
807     bl_idname = "cycles.use_shading_nodes"
808     bl_label = "Use Nodes"
809
810     @classmethod
811     def poll(cls, context):
812         return (getattr(context, "material", False) or getattr(context, "world", False) or
813                 getattr(context, "lamp", False))
814
815     def execute(self, context):
816         if context.material:
817             context.material.use_nodes = True
818         elif context.world:
819             context.world.use_nodes = True
820         elif context.lamp:
821             context.lamp.use_nodes = True
822
823         return {'FINISHED'}
824
825
826 def find_node(material, nodetype):
827     if material and material.node_tree:
828         ntree = material.node_tree
829
830         active_output_node = None
831         for node in ntree.nodes:
832             if getattr(node, "type", None) == nodetype:
833                 if getattr(node, "is_active_output", True):
834                     return node
835                 if not active_output_node:
836                     active_output_node = node
837         return active_output_node
838
839     return None
840
841
842 def find_node_input(node, name):
843     for input in node.inputs:
844         if input.name == name:
845             return input
846
847     return None
848
849
850 def panel_node_draw(layout, id_data, output_type, input_name):
851     if not id_data.use_nodes:
852         layout.operator("cycles.use_shading_nodes", icon='NODETREE')
853         return False
854
855     ntree = id_data.node_tree
856
857     node = find_node(id_data, output_type)
858     if not node:
859         layout.label(text="No output node")
860     else:
861         input = find_node_input(node, input_name)
862         layout.template_node_view(ntree, node, input)
863
864     return True
865
866
867 class CyclesLamp_PT_preview(CyclesButtonsPanel, Panel):
868     bl_label = "Preview"
869     bl_context = "data"
870     bl_options = {'DEFAULT_CLOSED'}
871
872     @classmethod
873     def poll(cls, context):
874         return context.lamp and \
875                not (context.lamp.type == 'AREA' and
876                     context.lamp.cycles.is_portal) \
877                and CyclesButtonsPanel.poll(context)
878
879     def draw(self, context):
880         self.layout.template_preview(context.lamp)
881
882
883 class CyclesLamp_PT_lamp(CyclesButtonsPanel, Panel):
884     bl_label = "Lamp"
885     bl_context = "data"
886
887     @classmethod
888     def poll(cls, context):
889         return context.lamp and CyclesButtonsPanel.poll(context)
890
891     def draw(self, context):
892         layout = self.layout
893
894         lamp = context.lamp
895         clamp = lamp.cycles
896         cscene = context.scene.cycles
897
898         layout.prop(lamp, "type", expand=True)
899
900         split = layout.split()
901         col = split.column(align=True)
902
903         if lamp.type in {'POINT', 'SUN', 'SPOT'}:
904             col.prop(lamp, "shadow_soft_size", text="Size")
905         elif lamp.type == 'AREA':
906             col.prop(lamp, "shape", text="")
907             sub = col.column(align=True)
908
909             if lamp.shape == 'SQUARE':
910                 sub.prop(lamp, "size")
911             elif lamp.shape == 'RECTANGLE':
912                 sub.prop(lamp, "size", text="Size X")
913                 sub.prop(lamp, "size_y", text="Size Y")
914
915         if not (lamp.type == 'AREA' and clamp.is_portal):
916             sub = col.column(align=True)
917             if use_branched_path(context):
918                 subsub = sub.row(align=True)
919                 subsub.active = use_sample_all_lights(context)
920                 subsub.prop(clamp, "samples")
921             sub.prop(clamp, "max_bounces")
922
923         col = split.column()
924
925         sub = col.column(align=True)
926         sub.active = not (lamp.type == 'AREA' and clamp.is_portal)
927         sub.prop(clamp, "cast_shadow")
928         sub.prop(clamp, "use_multiple_importance_sampling", text="Multiple Importance")
929
930         if lamp.type == 'AREA':
931             col.prop(clamp, "is_portal", text="Portal")
932
933         if lamp.type == 'HEMI':
934             layout.label(text="Not supported, interpreted as sun lamp")
935
936
937 class CyclesLamp_PT_nodes(CyclesButtonsPanel, Panel):
938     bl_label = "Nodes"
939     bl_context = "data"
940
941     @classmethod
942     def poll(cls, context):
943         return context.lamp and not (context.lamp.type == 'AREA' and
944                                      context.lamp.cycles.is_portal) and \
945                CyclesButtonsPanel.poll(context)
946
947     def draw(self, context):
948         layout = self.layout
949
950         lamp = context.lamp
951         if not panel_node_draw(layout, lamp, 'OUTPUT_LAMP', 'Surface'):
952             layout.prop(lamp, "color")
953
954
955 class CyclesLamp_PT_spot(CyclesButtonsPanel, Panel):
956     bl_label = "Spot Shape"
957     bl_context = "data"
958
959     @classmethod
960     def poll(cls, context):
961         lamp = context.lamp
962         return (lamp and lamp.type == 'SPOT') and CyclesButtonsPanel.poll(context)
963
964     def draw(self, context):
965         layout = self.layout
966
967         lamp = context.lamp
968
969         split = layout.split()
970
971         col = split.column()
972         sub = col.column()
973         sub.prop(lamp, "spot_size", text="Size")
974         sub.prop(lamp, "spot_blend", text="Blend", slider=True)
975
976         col = split.column()
977         col.prop(lamp, "show_cone")
978
979
980 class CyclesWorld_PT_preview(CyclesButtonsPanel, Panel):
981     bl_label = "Preview"
982     bl_context = "world"
983     bl_options = {'DEFAULT_CLOSED'}
984
985     @classmethod
986     def poll(cls, context):
987         return context.world and CyclesButtonsPanel.poll(context)
988
989     def draw(self, context):
990         self.layout.template_preview(context.world)
991
992
993 class CyclesWorld_PT_surface(CyclesButtonsPanel, Panel):
994     bl_label = "Surface"
995     bl_context = "world"
996
997     @classmethod
998     def poll(cls, context):
999         return context.world and CyclesButtonsPanel.poll(context)
1000
1001     def draw(self, context):
1002         layout = self.layout
1003
1004         world = context.world
1005
1006         if not panel_node_draw(layout, world, 'OUTPUT_WORLD', 'Surface'):
1007             layout.prop(world, "horizon_color", text="Color")
1008
1009
1010 class CyclesWorld_PT_volume(CyclesButtonsPanel, Panel):
1011     bl_label = "Volume"
1012     bl_context = "world"
1013     bl_options = {'DEFAULT_CLOSED'}
1014
1015     @classmethod
1016     def poll(cls, context):
1017         world = context.world
1018         return world and world.node_tree and CyclesButtonsPanel.poll(context)
1019
1020     def draw(self, context):
1021         layout = self.layout
1022
1023         world = context.world
1024         panel_node_draw(layout, world, 'OUTPUT_WORLD', 'Volume')
1025
1026
1027 class CyclesWorld_PT_ambient_occlusion(CyclesButtonsPanel, Panel):
1028     bl_label = "Ambient Occlusion"
1029     bl_context = "world"
1030
1031     @classmethod
1032     def poll(cls, context):
1033         return context.world and CyclesButtonsPanel.poll(context)
1034
1035     def draw_header(self, context):
1036         light = context.world.light_settings
1037         self.layout.prop(light, "use_ambient_occlusion", text="")
1038
1039     def draw(self, context):
1040         layout = self.layout
1041
1042         light = context.world.light_settings
1043
1044         row = layout.row()
1045         sub = row.row()
1046         sub.active = light.use_ambient_occlusion
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         col = split.column()
1229         col.label(text="Volume:")
1230         sub = col.column()
1231         sub.active = use_cpu(context)
1232         sub.prop(cmat, "volume_sampling", text="")
1233         sub.prop(cmat, "volume_interpolation", text="")
1234         col.prop(cmat, "homogeneous_volume", text="Homogeneous")
1235
1236         layout.separator()
1237         split = layout.split()
1238
1239         col = split.column(align=True)
1240         col.label("Viewport Color:")
1241         col.prop(mat, "diffuse_color", text="")
1242         col.prop(mat, "alpha")
1243
1244         col.separator()
1245         col.label("Viewport Alpha:")
1246         col.prop(mat.game_settings, "alpha_blend", text="")
1247
1248         col = split.column(align=True)
1249         col.label("Viewport Specular:")
1250         col.prop(mat, "specular_color", text="")
1251         col.prop(mat, "specular_hardness", text="Hardness")
1252
1253         col.separator()
1254         col.prop(mat, "pass_index")
1255
1256
1257 class CyclesTexture_PT_context(CyclesButtonsPanel, Panel):
1258     bl_label = ""
1259     bl_context = "texture"
1260     bl_options = {'HIDE_HEADER'}
1261     COMPAT_ENGINES = {'CYCLES'}
1262
1263     def draw(self, context):
1264         layout = self.layout
1265
1266         tex = context.texture
1267         space = context.space_data
1268         pin_id = space.pin_id
1269         use_pin_id = space.use_pin_id
1270         user = context.texture_user
1271
1272         space.use_limited_texture_context = False
1273
1274         if not (use_pin_id and isinstance(pin_id, bpy.types.Texture)):
1275             pin_id = None
1276
1277         if not pin_id:
1278             layout.template_texture_user()
1279
1280         if user or pin_id:
1281             layout.separator()
1282
1283             split = layout.split(percentage=0.65)
1284             col = split.column()
1285
1286             if pin_id:
1287                 col.template_ID(space, "pin_id")
1288             else:
1289                 propname = context.texture_user_property.identifier
1290                 col.template_ID(user, propname, new="texture.new")
1291
1292             if tex:
1293                 split = layout.split(percentage=0.2)
1294                 split.label(text="Type:")
1295                 split.prop(tex, "type", text="")
1296
1297
1298 class CyclesTexture_PT_node(CyclesButtonsPanel, Panel):
1299     bl_label = "Node"
1300     bl_context = "texture"
1301
1302     @classmethod
1303     def poll(cls, context):
1304         node = context.texture_node
1305         return node and CyclesButtonsPanel.poll(context)
1306
1307     def draw(self, context):
1308         layout = self.layout
1309
1310         node = context.texture_node
1311         ntree = node.id_data
1312         layout.template_node_view(ntree, node, None)
1313
1314
1315 class CyclesTexture_PT_mapping(CyclesButtonsPanel, Panel):
1316     bl_label = "Mapping"
1317     bl_context = "texture"
1318
1319     @classmethod
1320     def poll(cls, context):
1321         node = context.texture_node
1322         # TODO(sergey): perform a faster/nicer check?
1323         return node and hasattr(node, 'texture_mapping') and CyclesButtonsPanel.poll(context)
1324
1325     def draw(self, context):
1326         layout = self.layout
1327
1328         node = context.texture_node
1329
1330         mapping = node.texture_mapping
1331
1332         layout.prop(mapping, "vector_type", expand=True)
1333
1334         row = layout.row()
1335
1336         row.column().prop(mapping, "translation")
1337         row.column().prop(mapping, "rotation")
1338         row.column().prop(mapping, "scale")
1339
1340         layout.label(text="Projection:")
1341
1342         row = layout.row()
1343         row.prop(mapping, "mapping_x", text="")
1344         row.prop(mapping, "mapping_y", text="")
1345         row.prop(mapping, "mapping_z", text="")
1346
1347
1348 class CyclesTexture_PT_colors(CyclesButtonsPanel, Panel):
1349     bl_label = "Color"
1350     bl_context = "texture"
1351     bl_options = {'DEFAULT_CLOSED'}
1352
1353     @classmethod
1354     def poll(cls, context):
1355         # node = context.texture_node
1356         return False
1357         # return node and CyclesButtonsPanel.poll(context)
1358
1359     def draw(self, context):
1360         layout = self.layout
1361
1362         node = context.texture_node
1363
1364         mapping = node.color_mapping
1365
1366         split = layout.split()
1367
1368         col = split.column()
1369         col.label(text="Blend:")
1370         col.prop(mapping, "blend_type", text="")
1371         col.prop(mapping, "blend_factor", text="Factor")
1372         col.prop(mapping, "blend_color", text="")
1373
1374         col = split.column()
1375         col.label(text="Adjust:")
1376         col.prop(mapping, "brightness")
1377         col.prop(mapping, "contrast")
1378         col.prop(mapping, "saturation")
1379
1380         layout.separator()
1381
1382         layout.prop(mapping, "use_color_ramp", text="Ramp")
1383         if mapping.use_color_ramp:
1384             layout.template_color_ramp(mapping, "color_ramp", expand=True)
1385
1386
1387 class CyclesRender_PT_CurveRendering(CyclesButtonsPanel, Panel):
1388     bl_label = "Cycles Hair Rendering"
1389     bl_context = "particle"
1390
1391     @classmethod
1392     def poll(cls, context):
1393         psys = context.particle_system
1394         return CyclesButtonsPanel.poll(context) and psys and psys.settings.type == 'HAIR'
1395
1396     def draw_header(self, context):
1397         ccscene = context.scene.cycles_curves
1398         self.layout.prop(ccscene, "use_curves", text="")
1399
1400     def draw(self, context):
1401         layout = self.layout
1402
1403         scene = context.scene
1404         ccscene = scene.cycles_curves
1405
1406         layout.active = ccscene.use_curves
1407
1408         layout.prop(ccscene, "primitive", text="Primitive")
1409         layout.prop(ccscene, "shape", text="Shape")
1410
1411         if not (ccscene.primitive in {'CURVE_SEGMENTS', 'LINE_SEGMENTS'} and ccscene.shape == 'RIBBONS'):
1412             layout.prop(ccscene, "cull_backfacing", text="Cull back-faces")
1413
1414         if ccscene.primitive == 'TRIANGLES' and ccscene.shape == 'THICK':
1415             layout.prop(ccscene, "resolution", text="Resolution")
1416         elif ccscene.primitive == 'CURVE_SEGMENTS':
1417             layout.prop(ccscene, "subdivisions", text="Curve subdivisions")
1418
1419         row = layout.row()
1420         row.prop(ccscene, "minimum_width", text="Min Pixels")
1421         row.prop(ccscene, "maximum_width", text="Max Ext.")
1422
1423
1424 class CyclesRender_PT_bake(CyclesButtonsPanel, Panel):
1425     bl_label = "Bake"
1426     bl_context = "render"
1427     bl_options = {'DEFAULT_CLOSED'}
1428     COMPAT_ENGINES = {'CYCLES'}
1429
1430     def draw(self, context):
1431         layout = self.layout
1432
1433         scene = context.scene
1434         cscene = scene.cycles
1435         cbk = scene.render.bake
1436
1437         layout.operator("object.bake", icon='RENDER_STILL').type = cscene.bake_type
1438
1439         col = layout.column()
1440         col.prop(cscene, "bake_type")
1441
1442         col = layout.column()
1443
1444         if cscene.bake_type == 'NORMAL':
1445             col.prop(cbk, "normal_space", text="Space")
1446
1447             row = col.row(align=True)
1448             row.label(text="Swizzle:")
1449             row.prop(cbk, "normal_r", text="")
1450             row.prop(cbk, "normal_g", text="")
1451             row.prop(cbk, "normal_b", text="")
1452
1453         elif cscene.bake_type == 'COMBINED':
1454             row = col.row(align=True)
1455             row.prop(cbk, "use_pass_direct", toggle=True)
1456             row.prop(cbk, "use_pass_indirect", toggle=True)
1457
1458             split = col.split()
1459             split.active = cbk.use_pass_direct or cbk.use_pass_indirect
1460
1461             col = split.column()
1462             col.prop(cbk, "use_pass_diffuse")
1463             col.prop(cbk, "use_pass_glossy")
1464             col.prop(cbk, "use_pass_transmission")
1465
1466             col = split.column()
1467             col.prop(cbk, "use_pass_subsurface")
1468             col.prop(cbk, "use_pass_ambient_occlusion")
1469             col.prop(cbk, "use_pass_emit")
1470
1471         elif cscene.bake_type in {'DIFFUSE', 'GLOSSY', 'TRANSMISSION', 'SUBSURFACE'}:
1472             row = col.row(align=True)
1473             row.prop(cbk, "use_pass_direct", toggle=True)
1474             row.prop(cbk, "use_pass_indirect", toggle=True)
1475             row.prop(cbk, "use_pass_color", toggle=True)
1476
1477         layout.separator()
1478
1479         split = layout.split()
1480
1481         col = split.column()
1482         col.prop(cbk, "margin")
1483         col.prop(cbk, "use_clear")
1484
1485         col = split.column()
1486         col.prop(cbk, "use_selected_to_active")
1487         sub = col.column()
1488         sub.active = cbk.use_selected_to_active
1489         sub.prop(cbk, "use_cage", text="Cage")
1490         if cbk.use_cage:
1491             sub.prop(cbk, "cage_extrusion", text="Extrusion")
1492             sub.prop_search(cbk, "cage_object", scene, "objects", text="")
1493         else:
1494             sub.prop(cbk, "cage_extrusion", text="Ray Distance")
1495
1496
1497 class CyclesRender_PT_debug(CyclesButtonsPanel, Panel):
1498     bl_label = "Debug"
1499     bl_context = "render"
1500     bl_options = {'DEFAULT_CLOSED'}
1501     COMPAT_ENGINES = {'CYCLES'}
1502
1503     @classmethod
1504     def poll(cls, context):
1505         return CyclesButtonsPanel.poll(context) and bpy.app.debug_value == 256
1506
1507     def draw(self, context):
1508         layout = self.layout
1509
1510         scene = context.scene
1511         cscene = scene.cycles
1512
1513         col = layout.column()
1514
1515         col.label('CPU Flags:')
1516         row = col.row(align=True)
1517         row.prop(cscene, "debug_use_cpu_sse2", toggle=True)
1518         row.prop(cscene, "debug_use_cpu_sse3", toggle=True)
1519         row.prop(cscene, "debug_use_cpu_sse41", toggle=True)
1520         row.prop(cscene, "debug_use_cpu_avx", toggle=True)
1521         row.prop(cscene, "debug_use_cpu_avx2", toggle=True)
1522         col.prop(cscene, "debug_use_qbvh")
1523
1524         col = layout.column()
1525         col.label('CUDA Flags:')
1526         col.prop(cscene, "debug_use_cuda_adaptive_compile")
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_use_opencl_debug", text="Debug")
1533
1534
1535 class CyclesScene_PT_simplify(CyclesButtonsPanel, Panel):
1536     bl_label = "Simplify"
1537     bl_context = "scene"
1538     COMPAT_ENGINES = {'CYCLES'}
1539
1540     def draw_header(self, context):
1541         rd = context.scene.render
1542         self.layout.prop(rd, "use_simplify", text="")
1543
1544     def draw(self, context):
1545         layout = self.layout
1546
1547         scene = context.scene
1548         rd = scene.render
1549         cscene = scene.cycles
1550
1551         layout.active = rd.use_simplify
1552         split = layout.split()
1553
1554         col = split.column()
1555         col.label(text="Viewport:")
1556         col.prop(rd, "simplify_subdivision", text="Subdivision")
1557
1558         col = split.column()
1559         col.label(text="Render:")
1560         col.prop(rd, "simplify_subdivision_render", text="Subdivision")
1561
1562         col = layout.column()
1563         col.prop(cscene, "use_camera_cull")
1564         subsub = col.column()
1565         subsub.active = cscene.use_camera_cull
1566         subsub.prop(cscene, "camera_cull_margin")
1567
1568
1569 def draw_device(self, context):
1570     scene = context.scene
1571     layout = self.layout
1572
1573     if scene.render.engine == 'CYCLES':
1574         from . import engine
1575         cscene = scene.cycles
1576
1577         layout.prop(cscene, "feature_set")
1578
1579         device_type = context.user_preferences.system.compute_device_type
1580         if device_type in {'CUDA', 'OPENCL', 'NETWORK'}:
1581             layout.prop(cscene, "device")
1582
1583         if engine.with_osl() and use_cpu(context):
1584             layout.prop(cscene, "shading_system")
1585
1586
1587 def draw_pause(self, context):
1588     layout = self.layout
1589     scene = context.scene
1590
1591     if scene.render.engine == "CYCLES":
1592         view = context.space_data
1593
1594         if view.viewport_shade == 'RENDERED':
1595             cscene = scene.cycles
1596             layername = scene.render.layers.active.name
1597             layout.prop(cscene, "preview_pause", icon="PAUSE", text="")
1598             layout.prop(cscene, "preview_active_layer", icon="RENDERLAYERS", text=layername)
1599
1600
1601 def get_panels():
1602     types = bpy.types
1603     panels = [
1604         "RENDER_PT_render",
1605         "RENDER_PT_output",
1606         "RENDER_PT_encoding",
1607         "RENDER_PT_dimensions",
1608         "RENDER_PT_stamp",
1609         "RENDER_PT_freestyle",
1610         "RENDERLAYER_PT_layers",
1611         "RENDERLAYER_PT_freestyle",
1612         "RENDERLAYER_PT_freestyle_lineset",
1613         "RENDERLAYER_PT_freestyle_linestyle",
1614         "SCENE_PT_scene",
1615         "SCENE_PT_color_management",
1616         "SCENE_PT_custom_props",
1617         "SCENE_PT_audio",
1618         "SCENE_PT_unit",
1619         "SCENE_PT_keying_sets",
1620         "SCENE_PT_keying_set_paths",
1621         "SCENE_PT_physics",
1622         "WORLD_PT_context_world",
1623         "WORLD_PT_custom_props",
1624         "DATA_PT_context_mesh",
1625         "DATA_PT_context_camera",
1626         "DATA_PT_context_lamp",
1627         "DATA_PT_context_speaker",
1628         "DATA_PT_normals",
1629         "DATA_PT_texture_space",
1630         "DATA_PT_curve_texture_space",
1631         "DATA_PT_mball_texture_space",
1632         "DATA_PT_vertex_groups",
1633         "DATA_PT_shape_keys",
1634         "DATA_PT_uv_texture",
1635         "DATA_PT_vertex_colors",
1636         "DATA_PT_camera",
1637         "DATA_PT_camera_display",
1638         "DATA_PT_camera_stereoscopy",
1639         "DATA_PT_camera_safe_areas",
1640         "DATA_PT_lens",
1641         "DATA_PT_speaker",
1642         "DATA_PT_distance",
1643         "DATA_PT_cone",
1644         "DATA_PT_customdata",
1645         "DATA_PT_custom_props_mesh",
1646         "DATA_PT_custom_props_camera",
1647         "DATA_PT_custom_props_lamp",
1648         "DATA_PT_custom_props_speaker",
1649         "DATA_PT_custom_props_arm",
1650         "DATA_PT_custom_props_curve",
1651         "DATA_PT_custom_props_lattice",
1652         "DATA_PT_custom_props_metaball",
1653         "TEXTURE_PT_preview",
1654         "TEXTURE_PT_custom_props",
1655         "TEXTURE_PT_clouds",
1656         "TEXTURE_PT_wood",
1657         "TEXTURE_PT_marble",
1658         "TEXTURE_PT_magic",
1659         "TEXTURE_PT_blend",
1660         "TEXTURE_PT_stucci",
1661         "TEXTURE_PT_image",
1662         "TEXTURE_PT_image_sampling",
1663         "TEXTURE_PT_image_mapping",
1664         "TEXTURE_PT_musgrave",
1665         "TEXTURE_PT_voronoi",
1666         "TEXTURE_PT_distortednoise",
1667         "TEXTURE_PT_voxeldata",
1668         "TEXTURE_PT_pointdensity",
1669         "TEXTURE_PT_pointdensity_turbulence",
1670         "TEXTURE_PT_mapping",
1671         "TEXTURE_PT_ocean",
1672         "TEXTURE_PT_influence",
1673         "TEXTURE_PT_colors",
1674         "SCENE_PT_rigid_body_world",
1675         "SCENE_PT_rigid_body_cache",
1676         "SCENE_PT_rigid_body_field_weights",
1677         "MATERIAL_PT_custom_props",
1678         "MATERIAL_PT_freestyle_line",
1679         "BONE_PT_custom_props",
1680         "OBJECT_PT_custom_props",
1681         ]
1682
1683     return [getattr(types, p) for p in panels if hasattr(types, p)]
1684
1685
1686 def register():
1687     bpy.types.RENDER_PT_render.append(draw_device)
1688     bpy.types.VIEW3D_HT_header.append(draw_pause)
1689
1690     for panel in get_panels():
1691         panel.COMPAT_ENGINES.add('CYCLES')
1692
1693
1694 def unregister():
1695     bpy.types.RENDER_PT_render.remove(draw_device)
1696     bpy.types.VIEW3D_HT_header.remove(draw_pause)
1697
1698     for panel in get_panels():
1699         panel.COMPAT_ENGINES.remove('CYCLES')