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