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