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