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