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 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, "light", 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
1348 class CYCLES_WORLD_PT_settings_surface(CyclesButtonsPanel, Panel):
1349     bl_label = "Surface"
1350     bl_parent_id = "CYCLES_WORLD_PT_settings"
1351     bl_context = "world"
1352
1353     @classmethod
1354     def poll(cls, context):
1355         return context.world and CyclesButtonsPanel.poll(context)
1356
1357     def draw(self, context):
1358         layout = self.layout
1359         layout.use_property_split = True
1360
1361         world = context.world
1362         cworld = world.cycles
1363
1364         col = layout.column()
1365         col.prop(cworld, "sampling_method", text="Sampling")
1366
1367         sub = col.column()
1368         sub.active = cworld.sampling_method != 'NONE'
1369         subsub = sub.row(align=True)
1370         subsub.active = cworld.sampling_method == 'MANUAL'
1371         subsub.prop(cworld, "sample_map_resolution")
1372         if use_branched_path(context):
1373             subsub = sub.column(align=True)
1374             subsub.active = use_sample_all_lights(context)
1375             subsub.prop(cworld, "samples")
1376         sub.prop(cworld, "max_bounces")
1377
1378
1379 class CYCLES_WORLD_PT_settings_volume(CyclesButtonsPanel, Panel):
1380     bl_label = "Volume"
1381     bl_parent_id = "CYCLES_WORLD_PT_settings"
1382     bl_context = "world"
1383
1384     @classmethod
1385     def poll(cls, context):
1386         return context.world and CyclesButtonsPanel.poll(context)
1387
1388     def draw(self, context):
1389         layout = self.layout
1390         layout.use_property_split = True
1391
1392         world = context.world
1393         cworld = world.cycles
1394
1395         col = layout.column()
1396
1397         sub = col.column()
1398         sub.active = use_cpu(context)
1399         sub.prop(cworld, "volume_sampling", text="Sampling")
1400         col.prop(cworld, "volume_interpolation", text="Interpolation")
1401         col.prop(cworld, "homogeneous_volume", text="Homogeneous")
1402
1403
1404 class CYCLES_MATERIAL_PT_preview(CyclesButtonsPanel, Panel):
1405     bl_label = "Preview"
1406     bl_context = "material"
1407     bl_options = {'DEFAULT_CLOSED'}
1408
1409     @classmethod
1410     def poll(cls, context):
1411         return context.material and CyclesButtonsPanel.poll(context)
1412
1413     def draw(self, context):
1414         self.layout.template_preview(context.material)
1415
1416
1417 class CYCLES_MATERIAL_PT_surface(CyclesButtonsPanel, Panel):
1418     bl_label = "Surface"
1419     bl_context = "material"
1420
1421     @classmethod
1422     def poll(cls, context):
1423         return context.material and CyclesButtonsPanel.poll(context)
1424
1425     def draw(self, context):
1426         layout = self.layout
1427
1428         mat = context.material
1429         if not panel_node_draw(layout, mat, 'OUTPUT_MATERIAL', 'Surface'):
1430             layout.prop(mat, "diffuse_color")
1431
1432
1433 class CYCLES_MATERIAL_PT_volume(CyclesButtonsPanel, Panel):
1434     bl_label = "Volume"
1435     bl_context = "material"
1436     bl_options = {'DEFAULT_CLOSED'}
1437
1438     @classmethod
1439     def poll(cls, context):
1440         mat = context.material
1441         return mat and mat.node_tree and CyclesButtonsPanel.poll(context)
1442
1443     def draw(self, context):
1444         layout = self.layout
1445
1446         mat = context.material
1447         # cmat = mat.cycles
1448
1449         panel_node_draw(layout, mat, 'OUTPUT_MATERIAL', 'Volume')
1450
1451
1452 class CYCLES_MATERIAL_PT_displacement(CyclesButtonsPanel, Panel):
1453     bl_label = "Displacement"
1454     bl_context = "material"
1455
1456     @classmethod
1457     def poll(cls, context):
1458         mat = context.material
1459         return mat and mat.node_tree and CyclesButtonsPanel.poll(context)
1460
1461     def draw(self, context):
1462         layout = self.layout
1463
1464         mat = context.material
1465         panel_node_draw(layout, mat, 'OUTPUT_MATERIAL', 'Displacement')
1466
1467
1468 class CYCLES_MATERIAL_PT_settings(CyclesButtonsPanel, Panel):
1469     bl_label = "Settings"
1470     bl_context = "material"
1471
1472     @classmethod
1473     def poll(cls, context):
1474         return context.material and CyclesButtonsPanel.poll(context)
1475
1476     def draw(self, context):
1477         layout = self.layout
1478         layout.use_property_split = True
1479
1480         mat = context.material
1481         cmat = mat.cycles
1482
1483         layout.prop(mat, "pass_index")
1484
1485
1486 class CYCLES_MATERIAL_PT_settings_surface(CyclesButtonsPanel, Panel):
1487     bl_label = "Surface"
1488     bl_parent_id = "CYCLES_MATERIAL_PT_settings"
1489     bl_context = "material"
1490
1491     @classmethod
1492     def poll(cls, context):
1493         return context.material and CyclesButtonsPanel.poll(context)
1494
1495     def draw(self, context):
1496         layout = self.layout
1497         layout.use_property_split = True
1498
1499         mat = context.material
1500         cmat = mat.cycles
1501
1502         col = layout.column()
1503         col.prop(cmat, "sample_as_light", text="Multiple Importance")
1504         col.prop(cmat, "use_transparent_shadow")
1505         col.prop(cmat, "displacement_method", text="Displacement Method")
1506
1507
1508 class CYCLES_MATERIAL_PT_settings_volume(CyclesButtonsPanel, Panel):
1509     bl_label = "Volume"
1510     bl_parent_id = "CYCLES_MATERIAL_PT_settings"
1511     bl_context = "material"
1512
1513     @classmethod
1514     def poll(cls, context):
1515         return context.material and CyclesButtonsPanel.poll(context)
1516
1517     def draw(self, context):
1518         layout = self.layout
1519         layout.use_property_split = True
1520
1521         mat = context.material
1522         cmat = mat.cycles
1523
1524         col = layout.column()
1525         sub = col.column()
1526         sub.active = use_cpu(context)
1527         sub.prop(cmat, "volume_sampling", text="Sampling")
1528         col.prop(cmat, "volume_interpolation", text="Interpolation")
1529         col.prop(cmat, "homogeneous_volume", text="Homogeneous")
1530
1531
1532 class CYCLES_RENDER_PT_bake(CyclesButtonsPanel, Panel):
1533     bl_label = "Bake"
1534     bl_context = "render"
1535     bl_options = {'DEFAULT_CLOSED'}
1536     COMPAT_ENGINES = {'CYCLES'}
1537
1538     def draw(self, context):
1539         layout = self.layout
1540         layout.use_property_split = True
1541         layout.use_property_decorate = False  # No animation.
1542
1543         scene = context.scene
1544         cscene = scene.cycles
1545         cbk = scene.render.bake
1546         rd = scene.render
1547
1548         col = layout.column()
1549         col.prop(rd, "use_bake_multires")
1550         if rd.use_bake_multires:
1551             col.prop(rd, "bake_type")
1552
1553             col = layout.column()
1554             col.prop(rd, "bake_margin")
1555             col.prop(rd, "use_bake_clear")
1556
1557             if rd.bake_type == 'DISPLACEMENT':
1558                 col.prop(rd, "use_bake_lores_mesh")
1559
1560             col.operator("object.bake_image", icon='RENDER_STILL')
1561
1562         else:
1563             col.prop(cscene, "bake_type")
1564
1565             col = layout.column()
1566
1567             if cscene.bake_type == 'NORMAL':
1568                 col.prop(cbk, "normal_space", text="Space")
1569
1570                 sub = col.column(align=True)
1571                 sub.prop(cbk, "normal_r", text="Swizzle R")
1572                 sub.prop(cbk, "normal_g", text="G")
1573                 sub.prop(cbk, "normal_b", text="B")
1574
1575             elif cscene.bake_type == 'COMBINED':
1576                 row = col.row(align=True)
1577                 row.use_property_split = False
1578                 row.prop(cbk, "use_pass_direct", toggle=True)
1579                 row.prop(cbk, "use_pass_indirect", toggle=True)
1580
1581                 col = col.column()
1582                 col.active = cbk.use_pass_direct or cbk.use_pass_indirect
1583                 col.prop(cbk, "use_pass_diffuse")
1584                 col.prop(cbk, "use_pass_glossy")
1585                 col.prop(cbk, "use_pass_transmission")
1586                 col.prop(cbk, "use_pass_subsurface")
1587                 col.prop(cbk, "use_pass_ambient_occlusion")
1588                 col.prop(cbk, "use_pass_emit")
1589
1590             elif cscene.bake_type in {'DIFFUSE', 'GLOSSY', 'TRANSMISSION', 'SUBSURFACE'}:
1591                 row = col.row(align=True)
1592                 row.use_property_split = False
1593                 row.prop(cbk, "use_pass_direct", toggle=True)
1594                 row.prop(cbk, "use_pass_indirect", toggle=True)
1595                 row.prop(cbk, "use_pass_color", toggle=True)
1596
1597             layout.separator()
1598
1599             col = layout.column()
1600             col.prop(cbk, "margin")
1601             col.prop(cbk, "use_clear", text="Clear Image")
1602
1603             col.separator()
1604
1605             col.prop(cbk, "use_selected_to_active")
1606             sub = col.column()
1607             sub.active = cbk.use_selected_to_active
1608             sub.prop(cbk, "use_cage", text="Cage")
1609             if cbk.use_cage:
1610                 sub.prop(cbk, "cage_extrusion", text="Extrusion")
1611                 sub.prop_search(cbk, "cage_object", scene, "objects", text="Cage Object")
1612             else:
1613                 sub.prop(cbk, "cage_extrusion", text="Ray Distance")
1614
1615             layout.separator()
1616
1617             layout.operator("object.bake", icon='RENDER_STILL').type = cscene.bake_type
1618
1619
1620 class CYCLES_RENDER_PT_debug(CyclesButtonsPanel, Panel):
1621     bl_label = "Debug"
1622     bl_context = "render"
1623     bl_options = {'DEFAULT_CLOSED'}
1624     COMPAT_ENGINES = {'CYCLES'}
1625
1626     @classmethod
1627     def poll(cls, context):
1628         return CyclesButtonsPanel.poll(context) and bpy.app.debug_value == 256
1629
1630     def draw(self, context):
1631         layout = self.layout
1632
1633         scene = context.scene
1634         cscene = scene.cycles
1635
1636         col = layout.column()
1637
1638         col.label('CPU Flags:')
1639         row = col.row(align=True)
1640         row.prop(cscene, "debug_use_cpu_sse2", toggle=True)
1641         row.prop(cscene, "debug_use_cpu_sse3", toggle=True)
1642         row.prop(cscene, "debug_use_cpu_sse41", toggle=True)
1643         row.prop(cscene, "debug_use_cpu_avx", toggle=True)
1644         row.prop(cscene, "debug_use_cpu_avx2", toggle=True)
1645         col.prop(cscene, "debug_bvh_layout")
1646         col.prop(cscene, "debug_use_cpu_split_kernel")
1647
1648         col.separator()
1649
1650         col = layout.column()
1651         col.label('CUDA Flags:')
1652         col.prop(cscene, "debug_use_cuda_adaptive_compile")
1653         col.prop(cscene, "debug_use_cuda_split_kernel")
1654
1655         col.separator()
1656
1657         col = layout.column()
1658         col.label('OpenCL Flags:')
1659         col.prop(cscene, "debug_opencl_kernel_type", text="Kernel")
1660         col.prop(cscene, "debug_opencl_device_type", text="Device")
1661         col.prop(cscene, "debug_opencl_kernel_single_program", text="Single Program")
1662         col.prop(cscene, "debug_use_opencl_debug", text="Debug")
1663         col.prop(cscene, "debug_opencl_mem_limit")
1664
1665         col.separator()
1666
1667         col = layout.column()
1668         col.prop(cscene, "debug_bvh_type")
1669
1670
1671 class CYCLES_SCENE_PT_simplify(CyclesButtonsPanel, Panel):
1672     bl_label = "Simplify"
1673     bl_context = "scene"
1674     COMPAT_ENGINES = {'CYCLES'}
1675
1676     def draw_header(self, context):
1677         rd = context.scene.render
1678         self.layout.prop(rd, "use_simplify", text="")
1679
1680     def draw(self, context):
1681         pass
1682
1683
1684 class CYCLES_SCENE_PT_simplify_viewport(CyclesButtonsPanel, Panel):
1685     bl_label = "Viewport"
1686     bl_context = "scene"
1687     bl_parent_id = "CYCLES_SCENE_PT_simplify"
1688     COMPAT_ENGINES = {'CYCLES'}
1689
1690     def draw(self, context):
1691         layout = self.layout
1692         layout.use_property_split = True
1693
1694         scene = context.scene
1695         rd = scene.render
1696         cscene = scene.cycles
1697
1698         layout.active = rd.use_simplify
1699
1700         col = layout.column()
1701         col.prop(rd, "simplify_subdivision", text="Max Subdivision")
1702         col.prop(rd, "simplify_child_particles", text="Child Particles")
1703         col.prop(cscene, "texture_limit", text="Texture Limit")
1704         col.prop(cscene, "ao_bounces", text="AO Bounces")
1705
1706
1707 class CYCLES_SCENE_PT_simplify_render(CyclesButtonsPanel, Panel):
1708     bl_label = "Render"
1709     bl_context = "scene"
1710     bl_parent_id = "CYCLES_SCENE_PT_simplify"
1711     COMPAT_ENGINES = {'CYCLES'}
1712
1713     def draw(self, context):
1714         layout = self.layout
1715         layout.use_property_split = True
1716
1717         scene = context.scene
1718         rd = scene.render
1719         cscene = scene.cycles
1720
1721         layout.active = rd.use_simplify
1722
1723         col = layout.column()
1724
1725         col.prop(rd, "simplify_subdivision_render", text="Max Subdivision")
1726         col.prop(rd, "simplify_child_particles_render", text="Child Particles")
1727         col.prop(cscene, "texture_limit_render", text="Texture Limit")
1728         col.prop(cscene, "ao_bounces_render", text="AO Bounces")
1729
1730
1731 class CYCLES_SCENE_PT_simplify_culling(CyclesButtonsPanel, Panel):
1732     bl_label = "Culling"
1733     bl_context = "scene"
1734     bl_parent_id = "CYCLES_SCENE_PT_simplify"
1735     bl_options = {'DEFAULT_CLOSED'}
1736     COMPAT_ENGINES = {'CYCLES'}
1737
1738     def draw(self, context):
1739         layout = self.layout
1740         layout.use_property_split = True
1741
1742         scene = context.scene
1743         rd = scene.render
1744         cscene = scene.cycles
1745
1746         layout.active = rd.use_simplify
1747
1748         col = layout.column()
1749         col.prop(cscene, "use_camera_cull")
1750         sub = col.column()
1751         sub.active = cscene.use_camera_cull
1752         sub.prop(cscene, "camera_cull_margin")
1753
1754         col = layout.column()
1755         col.prop(cscene, "use_distance_cull")
1756         sub = col.column()
1757         sub.active = cscene.use_distance_cull
1758         sub.prop(cscene, "distance_cull_margin", text="Distance")
1759
1760
1761 def draw_device(self, context):
1762     scene = context.scene
1763     layout = self.layout
1764     layout.use_property_split = True
1765
1766     if context.engine == 'CYCLES':
1767         from . import engine
1768         cscene = scene.cycles
1769
1770         col = layout.column()
1771         col.prop(cscene, "feature_set")
1772
1773
1774 def draw_pause(self, context):
1775     layout = self.layout
1776     scene = context.scene
1777
1778     if context.engine == "CYCLES":
1779         view = context.space_data
1780
1781         if view.shading.type == 'RENDERED':
1782             cscene = scene.cycles
1783             layout.prop(cscene, "preview_pause", icon='PAUSE', text="")
1784
1785
1786 def get_panels():
1787     exclude_panels = {
1788         'DATA_PT_area',
1789         'DATA_PT_camera_dof',
1790         'DATA_PT_falloff_curve',
1791         'DATA_PT_light',
1792         'DATA_PT_preview',
1793         'DATA_PT_spot',
1794         'MATERIAL_PT_context_material',
1795         'MATERIAL_PT_preview',
1796         'VIEWLAYER_PT_filter',
1797         'VIEWLAYER_PT_layer_passes',
1798         'RENDER_PT_post_processing',
1799         'SCENE_PT_simplify',
1800     }
1801
1802     panels = []
1803     for panel in bpy.types.Panel.__subclasses__():
1804         if hasattr(panel, 'COMPAT_ENGINES') and 'BLENDER_RENDER' in panel.COMPAT_ENGINES:
1805             if panel.__name__ not in exclude_panels:
1806                 panels.append(panel)
1807
1808     return panels
1809
1810
1811 classes = (
1812     CYCLES_MT_sampling_presets,
1813     CYCLES_MT_integrator_presets,
1814     CYCLES_RENDER_PT_sampling,
1815     CYCLES_RENDER_PT_sampling_light,
1816     CYCLES_RENDER_PT_geometry,
1817     CYCLES_RENDER_PT_geometry_subdivision,
1818     CYCLES_RENDER_PT_geometry_volume,
1819     CYCLES_RENDER_PT_geometry_hair,
1820     CYCLES_RENDER_PT_light_paths,
1821     CYCLES_RENDER_PT_light_paths_max_bounces,
1822     CYCLES_RENDER_PT_light_paths_caustics,
1823     CYCLES_RENDER_PT_motion_blur,
1824     CYCLES_RENDER_PT_motion_blur_curve,
1825     CYCLES_RENDER_PT_film,
1826     CYCLES_RENDER_PT_film_transparency,
1827     CYCLES_RENDER_PT_film_pixel_filter,
1828     CYCLES_RENDER_PT_performance,
1829     CYCLES_RENDER_PT_performance_threads,
1830     CYCLES_RENDER_PT_performance_tiles,
1831     CYCLES_RENDER_PT_performance_acceleration_structure,
1832     CYCLES_RENDER_PT_performance_final_render,
1833     CYCLES_RENDER_PT_performance_viewport,
1834     CYCLES_RENDER_PT_filter,
1835     CYCLES_RENDER_PT_layer_passes,
1836     CYCLES_RENDER_PT_denoising,
1837     CYCLES_PT_post_processing,
1838     CYCLES_CAMERA_PT_dof,
1839     CYCLES_CAMERA_PT_dof_aperture,
1840     CYCLES_CAMERA_PT_dof_viewport,
1841     CYCLES_PT_context_material,
1842     CYCLES_OBJECT_PT_motion_blur,
1843     CYCLES_OBJECT_PT_cycles_settings,
1844     CYCLES_OT_use_shading_nodes,
1845     CYCLES_LIGHT_PT_preview,
1846     CYCLES_LIGHT_PT_light,
1847     CYCLES_LIGHT_PT_nodes,
1848     CYCLES_LIGHT_PT_spot,
1849     CYCLES_WORLD_PT_preview,
1850     CYCLES_WORLD_PT_surface,
1851     CYCLES_WORLD_PT_volume,
1852     CYCLES_WORLD_PT_ambient_occlusion,
1853     CYCLES_WORLD_PT_mist,
1854     CYCLES_WORLD_PT_ray_visibility,
1855     CYCLES_WORLD_PT_settings,
1856     CYCLES_WORLD_PT_settings_surface,
1857     CYCLES_WORLD_PT_settings_volume,
1858     CYCLES_MATERIAL_PT_preview,
1859     CYCLES_MATERIAL_PT_surface,
1860     CYCLES_MATERIAL_PT_volume,
1861     CYCLES_MATERIAL_PT_displacement,
1862     CYCLES_MATERIAL_PT_settings,
1863     CYCLES_MATERIAL_PT_settings_surface,
1864     CYCLES_MATERIAL_PT_settings_volume,
1865     CYCLES_RENDER_PT_bake,
1866     CYCLES_RENDER_PT_debug,
1867     CYCLES_SCENE_PT_simplify,
1868     CYCLES_SCENE_PT_simplify_viewport,
1869     CYCLES_SCENE_PT_simplify_render,
1870     CYCLES_SCENE_PT_simplify_culling,
1871 )
1872
1873
1874 def register():
1875     from bpy.utils import register_class
1876
1877     bpy.types.RENDER_PT_context.append(draw_device)
1878     bpy.types.VIEW3D_HT_header.append(draw_pause)
1879
1880     for panel in get_panels():
1881         panel.COMPAT_ENGINES.add('CYCLES')
1882
1883     for cls in classes:
1884         register_class(cls)
1885
1886
1887 def unregister():
1888     from bpy.utils import unregister_class
1889
1890     bpy.types.RENDER_PT_context.remove(draw_device)
1891     bpy.types.VIEW3D_HT_header.remove(draw_pause)
1892
1893     for panel in get_panels():
1894         if 'CYCLES' in panel.COMPAT_ENGINES:
1895             panel.COMPAT_ENGINES.remove('CYCLES')
1896
1897     for cls in classes:
1898         unregister_class(cls)