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