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 CyclesRender_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 CyclesRender_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 CyclesRender_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 CyclesRender_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 CyclesRender_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 CyclesRender_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         sub = col.column(align=True)
401         sub.label(text="Tiles:")
402         sub.prop(cscene, "tile_order", text="")
403
404         sub.prop(rd, "tile_x", text="X")
405         sub.prop(rd, "tile_y", text="Y")
406
407         sub.prop(cscene, "use_progressive_refine")
408
409         subsub = sub.column(align=True)
410         subsub.prop(rd, "use_save_buffers")
411
412         col = split.column(align=True)
413
414         col.label(text="Viewport:")
415         col.prop(cscene, "debug_bvh_type", text="")
416         col.separator()
417         col.prop(cscene, "preview_start_resolution")
418
419         col.separator()
420
421         col.label(text="Final Render:")
422         col.prop(rd, "use_persistent_data", text="Persistent Images")
423
424         col.separator()
425
426         col.label(text="Acceleration structure:")
427         col.prop(cscene, "debug_use_spatial_splits")
428         col.prop(cscene, "debug_use_hair_bvh")
429
430         row = col.row()
431         row.active = not cscene.debug_use_spatial_splits
432         row.prop(cscene, "debug_bvh_time_steps")
433
434
435 class CyclesRender_PT_layer_options(CyclesButtonsPanel, Panel):
436     bl_label = "Layer"
437     bl_context = "render_layer"
438
439     def draw(self, context):
440         layout = self.layout
441
442         scene = context.scene
443         rd = scene.render
444         rl = rd.layers.active
445
446         split = layout.split()
447
448         col = split.column()
449         col.prop(scene, "layers", text="Scene")
450         col.prop(rl, "layers_exclude", text="Exclude")
451
452         col = split.column()
453         col.prop(rl, "layers", text="Layer")
454         col.prop(rl, "layers_zmask", text="Mask Layer")
455
456         split = layout.split()
457
458         col = split.column()
459         col.label(text="Material:")
460         col.prop(rl, "material_override", text="")
461         col.separator()
462         col.prop(rl, "samples")
463
464         col = split.column()
465         col.prop(rl, "use_sky", "Use Environment")
466         col.prop(rl, "use_ao", "Use AO")
467         col.prop(rl, "use_solid", "Use Surfaces")
468         col.prop(rl, "use_strand", "Use Hair")
469
470
471 class CyclesRender_PT_layer_passes(CyclesButtonsPanel, Panel):
472     bl_label = "Passes"
473     bl_context = "render_layer"
474     bl_options = {'DEFAULT_CLOSED'}
475
476     def draw(self, context):
477         import _cycles
478
479         layout = self.layout
480
481         scene = context.scene
482         rd = scene.render
483         rl = rd.layers.active
484         crl = rl.cycles
485
486         split = layout.split()
487
488         col = split.column()
489         col.prop(rl, "use_pass_combined")
490         col.prop(rl, "use_pass_z")
491         col.prop(rl, "use_pass_mist")
492         col.prop(rl, "use_pass_normal")
493         row = col.row()
494         row.prop(rl, "use_pass_vector")
495         row.active = not rd.use_motion_blur
496         col.prop(rl, "use_pass_uv")
497         col.prop(rl, "use_pass_object_index")
498         col.prop(rl, "use_pass_material_index")
499         col.separator()
500         col.prop(rl, "use_pass_shadow")
501         col.prop(rl, "use_pass_ambient_occlusion")
502         col.separator()
503         col.prop(rl, "pass_alpha_threshold")
504
505         col = split.column()
506         col.label(text="Diffuse:")
507         row = col.row(align=True)
508         row.prop(rl, "use_pass_diffuse_direct", text="Direct", toggle=True)
509         row.prop(rl, "use_pass_diffuse_indirect", text="Indirect", toggle=True)
510         row.prop(rl, "use_pass_diffuse_color", text="Color", toggle=True)
511         col.label(text="Glossy:")
512         row = col.row(align=True)
513         row.prop(rl, "use_pass_glossy_direct", text="Direct", toggle=True)
514         row.prop(rl, "use_pass_glossy_indirect", text="Indirect", toggle=True)
515         row.prop(rl, "use_pass_glossy_color", text="Color", toggle=True)
516         col.label(text="Transmission:")
517         row = col.row(align=True)
518         row.prop(rl, "use_pass_transmission_direct", text="Direct", toggle=True)
519         row.prop(rl, "use_pass_transmission_indirect", text="Indirect", toggle=True)
520         row.prop(rl, "use_pass_transmission_color", text="Color", toggle=True)
521         col.label(text="Subsurface:")
522         row = col.row(align=True)
523         row.prop(rl, "use_pass_subsurface_direct", text="Direct", toggle=True)
524         row.prop(rl, "use_pass_subsurface_indirect", text="Indirect", toggle=True)
525         row.prop(rl, "use_pass_subsurface_color", text="Color", toggle=True)
526
527         col.separator()
528         col.prop(rl, "use_pass_emit", text="Emission")
529         col.prop(rl, "use_pass_environment")
530
531         if context.scene.cycles.feature_set == 'EXPERIMENTAL':
532             col.separator()
533             sub = col.column()
534             sub.active = crl.use_denoising
535             sub.prop(crl, "denoising_store_passes", text="Denoising")
536
537         if _cycles.with_cycles_debug:
538             col = layout.column()
539             col.prop(crl, "pass_debug_bvh_traversed_nodes")
540             col.prop(crl, "pass_debug_bvh_traversed_instances")
541             col.prop(crl, "pass_debug_bvh_intersections")
542             col.prop(crl, "pass_debug_ray_bounces")
543
544
545 class CyclesRender_PT_views(CyclesButtonsPanel, Panel):
546     bl_label = "Views"
547     bl_context = "render_layer"
548     bl_options = {'DEFAULT_CLOSED'}
549
550     def draw_header(self, context):
551         rd = context.scene.render
552         self.layout.prop(rd, "use_multiview", text="")
553
554     def draw(self, context):
555         layout = self.layout
556
557         scene = context.scene
558         rd = scene.render
559         rv = rd.views.active
560
561         layout.active = rd.use_multiview
562         basic_stereo = (rd.views_format == 'STEREO_3D')
563
564         row = layout.row()
565         row.prop(rd, "views_format", expand=True)
566
567         if basic_stereo:
568             row = layout.row()
569             row.template_list("RENDERLAYER_UL_renderviews", "name", rd, "stereo_views", rd.views, "active_index", rows=2)
570
571             row = layout.row()
572             row.label(text="File Suffix:")
573             row.prop(rv, "file_suffix", text="")
574
575         else:
576             row = layout.row()
577             row.template_list("RENDERLAYER_UL_renderviews", "name", rd, "views", rd.views, "active_index", rows=2)
578
579             col = row.column(align=True)
580             col.operator("scene.render_view_add", icon='ZOOMIN', text="")
581             col.operator("scene.render_view_remove", icon='ZOOMOUT', text="")
582
583             row = layout.row()
584             row.label(text="Camera Suffix:")
585             row.prop(rv, "camera_suffix", text="")
586
587
588 class CyclesRender_PT_denoising(CyclesButtonsPanel, Panel):
589     bl_label = "Denoising"
590     bl_context = "render_layer"
591     bl_options = {'DEFAULT_CLOSED'}
592
593     def draw_header(self, context):
594         rd = context.scene.render
595         rl = rd.layers.active
596         crl = rl.cycles
597         cscene = context.scene.cycles
598         layout = self.layout
599
600         layout.active = not cscene.use_progressive_refine
601         layout.prop(crl, "use_denoising", text="")
602
603     def draw(self, context):
604         layout = self.layout
605
606         scene = context.scene
607         cscene = scene.cycles
608         rd = scene.render
609         rl = rd.layers.active
610         crl = rl.cycles
611
612         layout.active = crl.use_denoising and not cscene.use_progressive_refine
613
614         split = layout.split()
615
616         col = split.column()
617         sub = col.column(align=True)
618         sub.prop(crl, "denoising_radius", text="Radius")
619         sub.prop(crl, "denoising_strength", slider=True, text="Strength")
620
621         col = split.column()
622         sub = col.column(align=True)
623         sub.prop(crl, "denoising_feature_strength", slider=True, text="Feature Strength")
624         sub.prop(crl, "denoising_relative_pca")
625
626         layout.separator()
627
628         row = layout.row()
629         row.label(text="Diffuse:")
630         sub = row.row(align=True)
631         sub.prop(crl, "denoising_diffuse_direct", text="Direct", toggle=True)
632         sub.prop(crl, "denoising_diffuse_indirect", text="Indirect", toggle=True)
633
634         row = layout.row()
635         row.label(text="Glossy:")
636         sub = row.row(align=True)
637         sub.prop(crl, "denoising_glossy_direct", text="Direct", toggle=True)
638         sub.prop(crl, "denoising_glossy_indirect", text="Indirect", toggle=True)
639
640         row = layout.row()
641         row.label(text="Transmission:")
642         sub = row.row(align=True)
643         sub.prop(crl, "denoising_transmission_direct", text="Direct", toggle=True)
644         sub.prop(crl, "denoising_transmission_indirect", text="Indirect", toggle=True)
645
646         row = layout.row()
647         row.label(text="Subsurface:")
648         sub = row.row(align=True)
649         sub.prop(crl, "denoising_subsurface_direct", text="Direct", toggle=True)
650         sub.prop(crl, "denoising_subsurface_indirect", text="Indirect", toggle=True)
651
652
653 class Cycles_PT_post_processing(CyclesButtonsPanel, Panel):
654     bl_label = "Post Processing"
655     bl_options = {'DEFAULT_CLOSED'}
656
657     def draw(self, context):
658         layout = self.layout
659
660         rd = context.scene.render
661
662         split = layout.split()
663
664         col = split.column()
665         col.prop(rd, "use_compositing")
666         col.prop(rd, "use_sequencer")
667
668         col = split.column()
669         col.prop(rd, "dither_intensity", text="Dither", slider=True)
670
671
672 class CyclesCamera_PT_dof(CyclesButtonsPanel, Panel):
673     bl_label = "Depth of Field"
674     bl_context = "data"
675
676     @classmethod
677     def poll(cls, context):
678         return context.camera and CyclesButtonsPanel.poll(context)
679
680     def draw(self, context):
681         layout = self.layout
682
683         cam = context.camera
684         ccam = cam.cycles
685         dof_options = cam.gpu_dof
686
687         split = layout.split()
688
689         col = split.column()
690         col.label("Focus:")
691         col.prop(cam, "dof_object", text="")
692
693         sub = col.row()
694         sub.active = cam.dof_object is None
695         sub.prop(cam, "dof_distance", text="Distance")
696
697         hq_support = dof_options.is_hq_supported
698         sub = col.column(align=True)
699         sub.label("Viewport:")
700         subhq = sub.column()
701         subhq.active = hq_support
702         subhq.prop(dof_options, "use_high_quality")
703         sub.prop(dof_options, "fstop")
704         if dof_options.use_high_quality and hq_support:
705             sub.prop(dof_options, "blades")
706
707         col = split.column()
708
709         col.label("Aperture:")
710         sub = col.column(align=True)
711         sub.prop(ccam, "aperture_type", text="")
712         if ccam.aperture_type == 'RADIUS':
713             sub.prop(ccam, "aperture_size", text="Size")
714         elif ccam.aperture_type == 'FSTOP':
715             sub.prop(ccam, "aperture_fstop", text="Number")
716
717         sub = col.column(align=True)
718         sub.prop(ccam, "aperture_blades", text="Blades")
719         sub.prop(ccam, "aperture_rotation", text="Rotation")
720         sub.prop(ccam, "aperture_ratio", text="Ratio")
721
722
723 class Cycles_PT_context_material(CyclesButtonsPanel, Panel):
724     bl_label = ""
725     bl_context = "material"
726     bl_options = {'HIDE_HEADER'}
727
728     @classmethod
729     def poll(cls, context):
730         return (context.material or context.object) and CyclesButtonsPanel.poll(context)
731
732     def draw(self, context):
733         layout = self.layout
734
735         mat = context.material
736         ob = context.object
737         slot = context.material_slot
738         space = context.space_data
739
740         if ob:
741             is_sortable = len(ob.material_slots) > 1
742             rows = 1
743             if (is_sortable):
744                 rows = 4
745
746             row = layout.row()
747
748             row.template_list("MATERIAL_UL_matslots", "", ob, "material_slots", ob, "active_material_index", rows=rows)
749
750             col = row.column(align=True)
751             col.operator("object.material_slot_add", icon='ZOOMIN', text="")
752             col.operator("object.material_slot_remove", icon='ZOOMOUT', text="")
753
754             col.menu("MATERIAL_MT_specials", icon='DOWNARROW_HLT', text="")
755
756             if is_sortable:
757                 col.separator()
758
759                 col.operator("object.material_slot_move", icon='TRIA_UP', text="").direction = 'UP'
760                 col.operator("object.material_slot_move", icon='TRIA_DOWN', text="").direction = 'DOWN'
761
762             if ob.mode == 'EDIT':
763                 row = layout.row(align=True)
764                 row.operator("object.material_slot_assign", text="Assign")
765                 row.operator("object.material_slot_select", text="Select")
766                 row.operator("object.material_slot_deselect", text="Deselect")
767
768         split = layout.split(percentage=0.65)
769
770         if ob:
771             split.template_ID(ob, "active_material", new="material.new")
772             row = split.row()
773
774             if slot:
775                 row.prop(slot, "link", text="")
776             else:
777                 row.label()
778         elif mat:
779             split.template_ID(space, "pin_id")
780             split.separator()
781
782
783 class CyclesObject_PT_motion_blur(CyclesButtonsPanel, Panel):
784     bl_label = "Motion Blur"
785     bl_context = "object"
786     bl_options = {'DEFAULT_CLOSED'}
787
788     @classmethod
789     def poll(cls, context):
790         ob = context.object
791         if CyclesButtonsPanel.poll(context) and ob:
792             if ob.type in {'MESH', 'CURVE', 'CURVE', 'SURFACE', 'FONT', 'META'}:
793                 return True
794             if ob.dupli_type == 'GROUP' and ob.dupli_group:
795                 return True
796             # TODO(sergey): More duplicator types here?
797         return False
798
799     def draw_header(self, context):
800         layout = self.layout
801
802         rd = context.scene.render
803         # scene = context.scene
804
805         layout.active = rd.use_motion_blur
806
807         ob = context.object
808         cob = ob.cycles
809
810         layout.prop(cob, "use_motion_blur", text="")
811
812     def draw(self, context):
813         layout = self.layout
814
815         rd = context.scene.render
816         # scene = context.scene
817
818         ob = context.object
819         cob = ob.cycles
820
821         layout.active = (rd.use_motion_blur and cob.use_motion_blur)
822
823         row = layout.row()
824         row.prop(cob, "use_deform_motion", text="Deformation")
825
826         sub = row.row()
827         sub.active = cob.use_deform_motion
828         sub.prop(cob, "motion_steps", text="Steps")
829
830
831 class CyclesObject_PT_cycles_settings(CyclesButtonsPanel, Panel):
832     bl_label = "Cycles Settings"
833     bl_context = "object"
834     bl_options = {'DEFAULT_CLOSED'}
835
836     @classmethod
837     def poll(cls, context):
838         ob = context.object
839         return (CyclesButtonsPanel.poll(context) and
840                 ob and ((ob.type in {'MESH', 'CURVE', 'SURFACE', 'FONT', 'META', 'LAMP'}) or
841                         (ob.dupli_type == 'GROUP' and ob.dupli_group)))
842
843     def draw(self, context):
844         layout = self.layout
845
846         scene = context.scene
847         cscene = scene.cycles
848         ob = context.object
849         cob = ob.cycles
850         visibility = ob.cycles_visibility
851
852         layout.label(text="Ray Visibility:")
853         flow = layout.column_flow()
854
855         flow.prop(visibility, "camera")
856         flow.prop(visibility, "diffuse")
857         flow.prop(visibility, "glossy")
858         flow.prop(visibility, "transmission")
859         flow.prop(visibility, "scatter")
860
861         if ob.type != 'LAMP':
862             flow.prop(visibility, "shadow")
863
864         layout.prop(cob, "is_shadow_catcher")
865
866         col = layout.column()
867         col.label(text="Performance:")
868         row = col.row()
869         sub = row.row()
870         sub.active = scene.render.use_simplify and cscene.use_camera_cull
871         sub.prop(cob, "use_camera_cull")
872
873         sub = row.row()
874         sub.active = scene.render.use_simplify and cscene.use_distance_cull
875         sub.prop(cob, "use_distance_cull")
876
877
878 class CYCLES_OT_use_shading_nodes(Operator):
879     """Enable nodes on a material, world or lamp"""
880     bl_idname = "cycles.use_shading_nodes"
881     bl_label = "Use Nodes"
882
883     @classmethod
884     def poll(cls, context):
885         return (getattr(context, "material", False) or getattr(context, "world", False) or
886                 getattr(context, "lamp", False))
887
888     def execute(self, context):
889         if context.material:
890             context.material.use_nodes = True
891         elif context.world:
892             context.world.use_nodes = True
893         elif context.lamp:
894             context.lamp.use_nodes = True
895
896         return {'FINISHED'}
897
898
899 def panel_node_draw(layout, id_data, output_types, input_name):
900     if not id_data.use_nodes:
901         layout.operator("cycles.use_shading_nodes", icon='NODETREE')
902         return False
903
904     ntree = id_data.node_tree
905
906     node = find_output_node(ntree, output_types)
907     if node:
908         input = find_node_input(node, input_name)
909         if input:
910             layout.template_node_view(ntree, node, input)
911         else:
912             layout.label(text="Incompatible output node")
913     else:
914         layout.label(text="No output node")
915
916     return True
917
918
919 class CyclesLamp_PT_preview(CyclesButtonsPanel, Panel):
920     bl_label = "Preview"
921     bl_context = "data"
922     bl_options = {'DEFAULT_CLOSED'}
923
924     @classmethod
925     def poll(cls, context):
926         return context.lamp and \
927                not (context.lamp.type == 'AREA' and
928                     context.lamp.cycles.is_portal) \
929                and CyclesButtonsPanel.poll(context)
930
931     def draw(self, context):
932         self.layout.template_preview(context.lamp)
933
934
935 class CyclesLamp_PT_lamp(CyclesButtonsPanel, Panel):
936     bl_label = "Lamp"
937     bl_context = "data"
938
939     @classmethod
940     def poll(cls, context):
941         return context.lamp and CyclesButtonsPanel.poll(context)
942
943     def draw(self, context):
944         layout = self.layout
945
946         lamp = context.lamp
947         clamp = lamp.cycles
948         # cscene = context.scene.cycles
949
950         layout.prop(lamp, "type", expand=True)
951
952         split = layout.split()
953         col = split.column(align=True)
954
955         if lamp.type in {'POINT', 'SUN', 'SPOT'}:
956             col.prop(lamp, "shadow_soft_size", text="Size")
957         elif lamp.type == 'AREA':
958             col.prop(lamp, "shape", text="")
959             sub = col.column(align=True)
960
961             if lamp.shape == 'SQUARE':
962                 sub.prop(lamp, "size")
963             elif lamp.shape == 'RECTANGLE':
964                 sub.prop(lamp, "size", text="Size X")
965                 sub.prop(lamp, "size_y", text="Size Y")
966
967         if not (lamp.type == 'AREA' and clamp.is_portal):
968             sub = col.column(align=True)
969             if use_branched_path(context):
970                 subsub = sub.row(align=True)
971                 subsub.active = use_sample_all_lights(context)
972                 subsub.prop(clamp, "samples")
973             sub.prop(clamp, "max_bounces")
974
975         col = split.column()
976
977         sub = col.column(align=True)
978         sub.active = not (lamp.type == 'AREA' and clamp.is_portal)
979         sub.prop(clamp, "cast_shadow")
980         sub.prop(clamp, "use_multiple_importance_sampling", text="Multiple Importance")
981
982         if lamp.type == 'AREA':
983             col.prop(clamp, "is_portal", text="Portal")
984
985         if lamp.type == 'HEMI':
986             layout.label(text="Not supported, interpreted as sun lamp")
987
988
989 class CyclesLamp_PT_nodes(CyclesButtonsPanel, Panel):
990     bl_label = "Nodes"
991     bl_context = "data"
992
993     @classmethod
994     def poll(cls, context):
995         return context.lamp and not (context.lamp.type == 'AREA' and
996                                      context.lamp.cycles.is_portal) and \
997                CyclesButtonsPanel.poll(context)
998
999     def draw(self, context):
1000         layout = self.layout
1001
1002         lamp = context.lamp
1003         if not panel_node_draw(layout, lamp, ('OUTPUT_LAMP',), 'Surface'):
1004             layout.prop(lamp, "color")
1005
1006
1007 class CyclesLamp_PT_spot(CyclesButtonsPanel, Panel):
1008     bl_label = "Spot Shape"
1009     bl_context = "data"
1010
1011     @classmethod
1012     def poll(cls, context):
1013         lamp = context.lamp
1014         return (lamp and lamp.type == 'SPOT') and CyclesButtonsPanel.poll(context)
1015
1016     def draw(self, context):
1017         layout = self.layout
1018
1019         lamp = context.lamp
1020
1021         split = layout.split()
1022
1023         col = split.column()
1024         sub = col.column()
1025         sub.prop(lamp, "spot_size", text="Size")
1026         sub.prop(lamp, "spot_blend", text="Blend", slider=True)
1027
1028         col = split.column()
1029         col.prop(lamp, "show_cone")
1030
1031
1032 class CyclesWorld_PT_preview(CyclesButtonsPanel, Panel):
1033     bl_label = "Preview"
1034     bl_context = "world"
1035     bl_options = {'DEFAULT_CLOSED'}
1036
1037     @classmethod
1038     def poll(cls, context):
1039         return context.world and CyclesButtonsPanel.poll(context)
1040
1041     def draw(self, context):
1042         self.layout.template_preview(context.world)
1043
1044
1045 class CyclesWorld_PT_surface(CyclesButtonsPanel, Panel):
1046     bl_label = "Surface"
1047     bl_context = "world"
1048
1049     @classmethod
1050     def poll(cls, context):
1051         return context.world and CyclesButtonsPanel.poll(context)
1052
1053     def draw(self, context):
1054         layout = self.layout
1055
1056         world = context.world
1057
1058         if not panel_node_draw(layout, world, ('OUTPUT_WORLD',), 'Surface'):
1059             layout.prop(world, "horizon_color", text="Color")
1060
1061
1062 class CyclesWorld_PT_volume(CyclesButtonsPanel, Panel):
1063     bl_label = "Volume"
1064     bl_context = "world"
1065     bl_options = {'DEFAULT_CLOSED'}
1066
1067     @classmethod
1068     def poll(cls, context):
1069         world = context.world
1070         return world and world.node_tree and CyclesButtonsPanel.poll(context)
1071
1072     def draw(self, context):
1073         layout = self.layout
1074
1075         world = context.world
1076         panel_node_draw(layout, world, ('OUTPUT_WORLD',), 'Volume')
1077
1078
1079 class CyclesWorld_PT_ambient_occlusion(CyclesButtonsPanel, Panel):
1080     bl_label = "Ambient Occlusion"
1081     bl_context = "world"
1082
1083     @classmethod
1084     def poll(cls, context):
1085         return context.world and CyclesButtonsPanel.poll(context)
1086
1087     def draw_header(self, context):
1088         light = context.world.light_settings
1089         self.layout.prop(light, "use_ambient_occlusion", text="")
1090
1091     def draw(self, context):
1092         layout = self.layout
1093
1094         light = context.world.light_settings
1095         scene = context.scene
1096
1097         row = layout.row()
1098         sub = row.row()
1099         sub.active = light.use_ambient_occlusion or scene.render.use_simplify
1100         sub.prop(light, "ao_factor", text="Factor")
1101         row.prop(light, "distance", text="Distance")
1102
1103
1104 class CyclesWorld_PT_mist(CyclesButtonsPanel, Panel):
1105     bl_label = "Mist Pass"
1106     bl_context = "world"
1107     bl_options = {'DEFAULT_CLOSED'}
1108
1109     @classmethod
1110     def poll(cls, context):
1111         if CyclesButtonsPanel.poll(context):
1112             if context.world:
1113                 for rl in context.scene.render.layers:
1114                     if rl.use_pass_mist:
1115                         return True
1116
1117         return False
1118
1119     def draw(self, context):
1120         layout = self.layout
1121
1122         world = context.world
1123
1124         split = layout.split(align=True)
1125         split.prop(world.mist_settings, "start")
1126         split.prop(world.mist_settings, "depth")
1127
1128         layout.prop(world.mist_settings, "falloff")
1129
1130
1131 class CyclesWorld_PT_ray_visibility(CyclesButtonsPanel, Panel):
1132     bl_label = "Ray Visibility"
1133     bl_context = "world"
1134     bl_options = {'DEFAULT_CLOSED'}
1135
1136     @classmethod
1137     def poll(cls, context):
1138         return CyclesButtonsPanel.poll(context) and context.world
1139
1140     def draw(self, context):
1141         layout = self.layout
1142
1143         world = context.world
1144         visibility = world.cycles_visibility
1145
1146         flow = layout.column_flow()
1147
1148         flow.prop(visibility, "camera")
1149         flow.prop(visibility, "diffuse")
1150         flow.prop(visibility, "glossy")
1151         flow.prop(visibility, "transmission")
1152         flow.prop(visibility, "scatter")
1153
1154
1155 class CyclesWorld_PT_settings(CyclesButtonsPanel, Panel):
1156     bl_label = "Settings"
1157     bl_context = "world"
1158     bl_options = {'DEFAULT_CLOSED'}
1159
1160     @classmethod
1161     def poll(cls, context):
1162         return context.world and CyclesButtonsPanel.poll(context)
1163
1164     def draw(self, context):
1165         layout = self.layout
1166
1167         world = context.world
1168         cworld = world.cycles
1169         # cscene = context.scene.cycles
1170
1171         split = layout.split()
1172
1173         col = split.column()
1174
1175         col.label(text="Surface:")
1176         col.prop(cworld, "sample_as_light", text="Multiple Importance")
1177
1178         sub = col.column(align=True)
1179         sub.active = cworld.sample_as_light
1180         sub.prop(cworld, "sample_map_resolution")
1181         if use_branched_path(context):
1182             subsub = sub.row(align=True)
1183             subsub.active = use_sample_all_lights(context)
1184             subsub.prop(cworld, "samples")
1185         sub.prop(cworld, "max_bounces")
1186
1187         col = split.column()
1188         col.label(text="Volume:")
1189         sub = col.column()
1190         sub.active = use_cpu(context)
1191         sub.prop(cworld, "volume_sampling", text="")
1192         sub.prop(cworld, "volume_interpolation", text="")
1193         col.prop(cworld, "homogeneous_volume", text="Homogeneous")
1194
1195
1196 class CyclesMaterial_PT_preview(CyclesButtonsPanel, Panel):
1197     bl_label = "Preview"
1198     bl_context = "material"
1199     bl_options = {'DEFAULT_CLOSED'}
1200
1201     @classmethod
1202     def poll(cls, context):
1203         return context.material and CyclesButtonsPanel.poll(context)
1204
1205     def draw(self, context):
1206         self.layout.template_preview(context.material)
1207
1208
1209 class CyclesMaterial_PT_surface(CyclesButtonsPanel, Panel):
1210     bl_label = "Surface"
1211     bl_context = "material"
1212
1213     @classmethod
1214     def poll(cls, context):
1215         return context.material and CyclesButtonsPanel.poll(context)
1216
1217     def draw(self, context):
1218         layout = self.layout
1219
1220         mat = context.material
1221         if not panel_node_draw(layout, mat, ('OUTPUT_MATERIAL', 'OUTPUT_EEVEE_MATERIAL'), 'Surface'):
1222             layout.prop(mat, "diffuse_color")
1223
1224
1225 class CyclesMaterial_PT_volume(CyclesButtonsPanel, Panel):
1226     bl_label = "Volume"
1227     bl_context = "material"
1228     bl_options = {'DEFAULT_CLOSED'}
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         # cmat = mat.cycles
1240
1241         panel_node_draw(layout, mat, ('OUTPUT_MATERIAL', 'OUTPUT_EEVEE_MATERIAL'), 'Volume')
1242
1243
1244 class CyclesMaterial_PT_displacement(CyclesButtonsPanel, Panel):
1245     bl_label = "Displacement"
1246     bl_context = "material"
1247
1248     @classmethod
1249     def poll(cls, context):
1250         mat = context.material
1251         return mat and mat.node_tree and CyclesButtonsPanel.poll(context)
1252
1253     def draw(self, context):
1254         layout = self.layout
1255
1256         mat = context.material
1257         panel_node_draw(layout, mat, ('OUTPUT_MATERIAL', 'OUTPUT_EEVEE_MATERIAL'), 'Displacement')
1258
1259
1260 class CyclesMaterial_PT_settings(CyclesButtonsPanel, Panel):
1261     bl_label = "Settings"
1262     bl_context = "material"
1263     bl_options = {'DEFAULT_CLOSED'}
1264
1265     @classmethod
1266     def poll(cls, context):
1267         return context.material and CyclesButtonsPanel.poll(context)
1268
1269     def draw(self, context):
1270         layout = self.layout
1271
1272         mat = context.material
1273         cmat = mat.cycles
1274
1275         split = layout.split()
1276         col = split.column()
1277         col.label(text="Surface:")
1278         col.prop(cmat, "sample_as_light", text="Multiple Importance")
1279         col.prop(cmat, "use_transparent_shadow")
1280
1281         if context.scene.cycles.feature_set == 'EXPERIMENTAL':
1282             col.separator()
1283             col.label(text="Displacement:")
1284             col.prop(cmat, "displacement_method", text="")
1285
1286         col = split.column()
1287         col.label(text="Volume:")
1288         sub = col.column()
1289         sub.active = use_cpu(context)
1290         sub.prop(cmat, "volume_sampling", text="")
1291         sub.prop(cmat, "volume_interpolation", text="")
1292         col.prop(cmat, "homogeneous_volume", text="Homogeneous")
1293
1294         layout.separator()
1295         split = layout.split()
1296
1297         col = split.column(align=True)
1298         col.label("Viewport Color:")
1299         col.prop(mat, "diffuse_color", text="")
1300         col.prop(mat, "alpha")
1301
1302         col.separator()
1303         col.label("Viewport Alpha:")
1304         col.prop(mat.game_settings, "alpha_blend", text="")
1305
1306         col = split.column(align=True)
1307         col.label("Viewport Specular:")
1308         col.prop(mat, "specular_color", text="")
1309         col.prop(mat, "specular_hardness", text="Hardness")
1310
1311         col.separator()
1312         col.prop(mat, "pass_index")
1313
1314
1315 class CyclesTexture_PT_context(CyclesButtonsPanel, Panel):
1316     bl_label = ""
1317     bl_context = "texture"
1318     bl_options = {'HIDE_HEADER'}
1319     COMPAT_ENGINES = {'CYCLES'}
1320
1321     def draw(self, context):
1322         layout = self.layout
1323
1324         tex = context.texture
1325         space = context.space_data
1326         pin_id = space.pin_id
1327         use_pin_id = space.use_pin_id
1328         user = context.texture_user
1329
1330         space.use_limited_texture_context = False
1331
1332         if not (use_pin_id and isinstance(pin_id, bpy.types.Texture)):
1333             pin_id = None
1334
1335         if not pin_id:
1336             layout.template_texture_user()
1337
1338         if user or pin_id:
1339             layout.separator()
1340
1341             split = layout.split(percentage=0.65)
1342             col = split.column()
1343
1344             if pin_id:
1345                 col.template_ID(space, "pin_id")
1346             else:
1347                 propname = context.texture_user_property.identifier
1348                 col.template_ID(user, propname, new="texture.new")
1349
1350             if tex:
1351                 split = layout.split(percentage=0.2)
1352                 split.label(text="Type:")
1353                 split.prop(tex, "type", text="")
1354
1355
1356 class CyclesTexture_PT_node(CyclesButtonsPanel, Panel):
1357     bl_label = "Node"
1358     bl_context = "texture"
1359
1360     @classmethod
1361     def poll(cls, context):
1362         node = context.texture_node
1363         return node and CyclesButtonsPanel.poll(context)
1364
1365     def draw(self, context):
1366         layout = self.layout
1367
1368         node = context.texture_node
1369         ntree = node.id_data
1370         layout.template_node_view(ntree, node, None)
1371
1372
1373 class CyclesTexture_PT_mapping(CyclesButtonsPanel, Panel):
1374     bl_label = "Mapping"
1375     bl_context = "texture"
1376
1377     @classmethod
1378     def poll(cls, context):
1379         node = context.texture_node
1380         # TODO(sergey): perform a faster/nicer check?
1381         return node and hasattr(node, 'texture_mapping') and CyclesButtonsPanel.poll(context)
1382
1383     def draw(self, context):
1384         layout = self.layout
1385
1386         node = context.texture_node
1387
1388         mapping = node.texture_mapping
1389
1390         layout.prop(mapping, "vector_type", expand=True)
1391
1392         row = layout.row()
1393
1394         row.column().prop(mapping, "translation")
1395         row.column().prop(mapping, "rotation")
1396         row.column().prop(mapping, "scale")
1397
1398         layout.label(text="Projection:")
1399
1400         row = layout.row()
1401         row.prop(mapping, "mapping_x", text="")
1402         row.prop(mapping, "mapping_y", text="")
1403         row.prop(mapping, "mapping_z", text="")
1404
1405
1406 class CyclesTexture_PT_colors(CyclesButtonsPanel, Panel):
1407     bl_label = "Color"
1408     bl_context = "texture"
1409     bl_options = {'DEFAULT_CLOSED'}
1410
1411     @classmethod
1412     def poll(cls, context):
1413         # node = context.texture_node
1414         return False
1415         # return node and CyclesButtonsPanel.poll(context)
1416
1417     def draw(self, context):
1418         layout = self.layout
1419
1420         node = context.texture_node
1421
1422         mapping = node.color_mapping
1423
1424         split = layout.split()
1425
1426         col = split.column()
1427         col.label(text="Blend:")
1428         col.prop(mapping, "blend_type", text="")
1429         col.prop(mapping, "blend_factor", text="Factor")
1430         col.prop(mapping, "blend_color", text="")
1431
1432         col = split.column()
1433         col.label(text="Adjust:")
1434         col.prop(mapping, "brightness")
1435         col.prop(mapping, "contrast")
1436         col.prop(mapping, "saturation")
1437
1438         layout.separator()
1439
1440         layout.prop(mapping, "use_color_ramp", text="Ramp")
1441         if mapping.use_color_ramp:
1442             layout.template_color_ramp(mapping, "color_ramp", expand=True)
1443
1444
1445 class CyclesParticle_PT_textures(CyclesButtonsPanel, Panel):
1446     bl_label = "Textures"
1447     bl_context = "particle"
1448     bl_options = {'DEFAULT_CLOSED'}
1449
1450     @classmethod
1451     def poll(cls, context):
1452         psys = context.particle_system
1453         return psys and CyclesButtonsPanel.poll(context)
1454
1455     def draw(self, context):
1456         layout = self.layout
1457
1458         psys = context.particle_system
1459         part = psys.settings
1460
1461         row = layout.row()
1462         row.template_list("TEXTURE_UL_texslots", "", part, "texture_slots", part, "active_texture_index", rows=2)
1463
1464         col = row.column(align=True)
1465         col.operator("texture.slot_move", text="", icon='TRIA_UP').type = 'UP'
1466         col.operator("texture.slot_move", text="", icon='TRIA_DOWN').type = 'DOWN'
1467         col.menu("TEXTURE_MT_specials", icon='DOWNARROW_HLT', text="")
1468
1469         if not part.active_texture:
1470             layout.template_ID(part, "active_texture", new="texture.new")
1471         else:
1472             slot = part.texture_slots[part.active_texture_index]
1473             layout.template_ID(slot, "texture", new="texture.new")
1474
1475
1476 class CyclesRender_PT_bake(CyclesButtonsPanel, Panel):
1477     bl_label = "Bake"
1478     bl_context = "render"
1479     bl_options = {'DEFAULT_CLOSED'}
1480     COMPAT_ENGINES = {'CYCLES'}
1481
1482     def draw(self, context):
1483         layout = self.layout
1484
1485         scene = context.scene
1486         cscene = scene.cycles
1487         cbk = scene.render.bake
1488
1489         layout.operator("object.bake", icon='RENDER_STILL').type = cscene.bake_type
1490
1491         col = layout.column()
1492         col.prop(cscene, "bake_type")
1493
1494         col = layout.column()
1495
1496         if cscene.bake_type == 'NORMAL':
1497             col.prop(cbk, "normal_space", text="Space")
1498
1499             row = col.row(align=True)
1500             row.label(text="Swizzle:")
1501             row.prop(cbk, "normal_r", text="")
1502             row.prop(cbk, "normal_g", text="")
1503             row.prop(cbk, "normal_b", text="")
1504
1505         elif cscene.bake_type == 'COMBINED':
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
1510             split = col.split()
1511             split.active = cbk.use_pass_direct or cbk.use_pass_indirect
1512
1513             col = split.column()
1514             col.prop(cbk, "use_pass_diffuse")
1515             col.prop(cbk, "use_pass_glossy")
1516             col.prop(cbk, "use_pass_transmission")
1517
1518             col = split.column()
1519             col.prop(cbk, "use_pass_subsurface")
1520             col.prop(cbk, "use_pass_ambient_occlusion")
1521             col.prop(cbk, "use_pass_emit")
1522
1523         elif cscene.bake_type in {'DIFFUSE', 'GLOSSY', 'TRANSMISSION', 'SUBSURFACE'}:
1524             row = col.row(align=True)
1525             row.prop(cbk, "use_pass_direct", toggle=True)
1526             row.prop(cbk, "use_pass_indirect", toggle=True)
1527             row.prop(cbk, "use_pass_color", toggle=True)
1528
1529         layout.separator()
1530
1531         split = layout.split()
1532
1533         col = split.column()
1534         col.prop(cbk, "margin")
1535         col.prop(cbk, "use_clear")
1536
1537         col = split.column()
1538         col.prop(cbk, "use_selected_to_active")
1539         sub = col.column()
1540         sub.active = cbk.use_selected_to_active
1541         sub.prop(cbk, "use_cage", text="Cage")
1542         if cbk.use_cage:
1543             sub.prop(cbk, "cage_extrusion", text="Extrusion")
1544             sub.prop_search(cbk, "cage_object", scene, "objects", text="")
1545         else:
1546             sub.prop(cbk, "cage_extrusion", text="Ray Distance")
1547
1548
1549 class CyclesRender_PT_debug(CyclesButtonsPanel, Panel):
1550     bl_label = "Debug"
1551     bl_context = "render"
1552     bl_options = {'DEFAULT_CLOSED'}
1553     COMPAT_ENGINES = {'CYCLES'}
1554
1555     @classmethod
1556     def poll(cls, context):
1557         return CyclesButtonsPanel.poll(context) and bpy.app.debug_value == 256
1558
1559     def draw(self, context):
1560         layout = self.layout
1561
1562         scene = context.scene
1563         cscene = scene.cycles
1564
1565         col = layout.column()
1566
1567         col.label('CPU Flags:')
1568         row = col.row(align=True)
1569         row.prop(cscene, "debug_use_cpu_sse2", toggle=True)
1570         row.prop(cscene, "debug_use_cpu_sse3", toggle=True)
1571         row.prop(cscene, "debug_use_cpu_sse41", toggle=True)
1572         row.prop(cscene, "debug_use_cpu_avx", toggle=True)
1573         row.prop(cscene, "debug_use_cpu_avx2", toggle=True)
1574         col.prop(cscene, "debug_use_qbvh")
1575         col.prop(cscene, "debug_use_cpu_split_kernel")
1576
1577         col = layout.column()
1578         col.label('CUDA Flags:')
1579         col.prop(cscene, "debug_use_cuda_adaptive_compile")
1580         col.prop(cscene, "debug_use_cuda_split_kernel")
1581
1582         col = layout.column()
1583         col.label('OpenCL Flags:')
1584         col.prop(cscene, "debug_opencl_kernel_type", text="Kernel")
1585         col.prop(cscene, "debug_opencl_device_type", text="Device")
1586         col.prop(cscene, "debug_opencl_kernel_single_program", text="Single Program")
1587         col.prop(cscene, "debug_use_opencl_debug", text="Debug")
1588         col.prop(cscene, "debug_opencl_mem_limit")
1589
1590
1591 class CyclesParticle_PT_CurveSettings(CyclesButtonsPanel, Panel):
1592     bl_label = "Cycles Hair Settings"
1593     bl_context = "particle"
1594
1595     @classmethod
1596     def poll(cls, context):
1597         scene = context.scene
1598         ccscene = scene.cycles_curves
1599         psys = context.particle_system
1600         use_curves = ccscene.use_curves and psys
1601         return CyclesButtonsPanel.poll(context) and use_curves and psys.settings.type == 'HAIR'
1602
1603     def draw(self, context):
1604         layout = self.layout
1605
1606         psys = context.particle_settings
1607         cpsys = psys.cycles
1608
1609         row = layout.row()
1610         row.prop(cpsys, "shape", text="Shape")
1611
1612         layout.label(text="Thickness:")
1613         row = layout.row()
1614         row.prop(cpsys, "root_width", text="Root")
1615         row.prop(cpsys, "tip_width", text="Tip")
1616
1617         row = layout.row()
1618         row.prop(cpsys, "radius_scale", text="Scaling")
1619         row.prop(cpsys, "use_closetip", text="Close tip")
1620
1621
1622 class CyclesScene_PT_simplify(CyclesButtonsPanel, Panel):
1623     bl_label = "Simplify"
1624     bl_context = "scene"
1625     COMPAT_ENGINES = {'CYCLES'}
1626
1627     def draw_header(self, context):
1628         rd = context.scene.render
1629         self.layout.prop(rd, "use_simplify", text="")
1630
1631     def draw(self, context):
1632         layout = self.layout
1633
1634         scene = context.scene
1635         rd = scene.render
1636         cscene = scene.cycles
1637
1638         layout.active = rd.use_simplify
1639
1640         col = layout.column(align=True)
1641         col.label(text="Subdivision")
1642         row = col.row(align=True)
1643         row.prop(rd, "simplify_subdivision", text="Viewport")
1644         row.prop(rd, "simplify_subdivision_render", text="Render")
1645
1646
1647         col = layout.column(align=True)
1648         col.label(text="Child Particles")
1649         row = col.row(align=True)
1650         row.prop(rd, "simplify_child_particles", text="Viewport")
1651         row.prop(rd, "simplify_child_particles_render", text="Render")
1652
1653         col = layout.column(align=True)
1654         split = col.split()
1655         sub = split.column()
1656         sub.label(text="Texture Limit Viewport")
1657         sub.prop(cscene, "texture_limit", text="")
1658         sub = split.column()
1659         sub.label(text="Texture Limit Render")
1660         sub.prop(cscene, "texture_limit_render", text="")
1661
1662         split = layout.split()
1663         col = split.column()
1664         col.prop(cscene, "use_camera_cull")
1665         row = col.row()
1666         row.active = cscene.use_camera_cull
1667         row.prop(cscene, "camera_cull_margin")
1668
1669         col = split.column()
1670         col.prop(cscene, "use_distance_cull")
1671         row = col.row()
1672         row.active = cscene.use_distance_cull
1673         row.prop(cscene, "distance_cull_margin", text="Distance")
1674
1675         split = layout.split()
1676         col = split.column()
1677         col.prop(cscene, "ao_bounces")
1678
1679         col = split.column()
1680         col.prop(cscene, "ao_bounces_render")
1681
1682 def draw_device(self, context):
1683     scene = context.scene
1684     layout = self.layout
1685
1686     if scene.render.engine == 'CYCLES':
1687         from . import engine
1688         cscene = scene.cycles
1689
1690         layout.prop(cscene, "feature_set")
1691
1692         split = layout.split(percentage=1 / 3)
1693         split.label("Device:")
1694         row = split.row()
1695         row.active = show_device_active(context)
1696         row.prop(cscene, "device", text="")
1697
1698         if engine.with_osl() and use_cpu(context):
1699             layout.prop(cscene, "shading_system")
1700
1701
1702 def draw_pause(self, context):
1703     layout = self.layout
1704     scene = context.scene
1705
1706     if scene.render.engine == "CYCLES":
1707         view = context.space_data
1708
1709         cscene = scene.cycles
1710         layout.prop(cscene, "preview_pause", icon="PAUSE", text="")
1711
1712
1713 def get_panels():
1714     exclude_panels = {
1715         'DATA_PT_area',
1716         'DATA_PT_camera_dof',
1717         'DATA_PT_falloff_curve',
1718         'DATA_PT_lamp',
1719         'DATA_PT_preview',
1720         'DATA_PT_shadow',
1721         'DATA_PT_spot',
1722         'DATA_PT_sunsky',
1723         'MATERIAL_PT_context_material',
1724         'MATERIAL_PT_diffuse',
1725         'MATERIAL_PT_flare',
1726         'MATERIAL_PT_halo',
1727         'MATERIAL_PT_mirror',
1728         'MATERIAL_PT_options',
1729         'MATERIAL_PT_pipeline',
1730         'MATERIAL_PT_preview',
1731         'MATERIAL_PT_shading',
1732         'MATERIAL_PT_shadow',
1733         'MATERIAL_PT_specular',
1734         'MATERIAL_PT_sss',
1735         'MATERIAL_PT_strand',
1736         'MATERIAL_PT_transp',
1737         'MATERIAL_PT_volume_density',
1738         'MATERIAL_PT_volume_integration',
1739         'MATERIAL_PT_volume_lighting',
1740         'MATERIAL_PT_volume_options',
1741         'MATERIAL_PT_volume_shading',
1742         'MATERIAL_PT_volume_transp',
1743         'RENDERLAYER_PT_layer_options',
1744         'RENDERLAYER_PT_layer_passes',
1745         'RENDERLAYER_PT_views',
1746         'RENDER_PT_antialiasing',
1747         'RENDER_PT_bake',
1748         'RENDER_PT_motion_blur',
1749         'RENDER_PT_performance',
1750         'RENDER_PT_post_processing',
1751         'RENDER_PT_shading',
1752         'SCENE_PT_simplify',
1753         'TEXTURE_PT_context_texture',
1754         'WORLD_PT_ambient_occlusion',
1755         'WORLD_PT_environment_lighting',
1756         'WORLD_PT_gather',
1757         'WORLD_PT_indirect_lighting',
1758         'WORLD_PT_mist',
1759         'WORLD_PT_preview',
1760         'WORLD_PT_world'
1761         }
1762
1763     panels = []
1764     for panel in bpy.types.Panel.__subclasses__():
1765         if hasattr(panel, 'COMPAT_ENGINES') and 'BLENDER_RENDER' in panel.COMPAT_ENGINES:
1766             if panel.__name__ not in exclude_panels:
1767                 panels.append(panel)
1768
1769     return panels
1770
1771
1772 classes = (
1773     CYCLES_MT_sampling_presets,
1774     CYCLES_MT_integrator_presets,
1775     CyclesRender_PT_sampling,
1776     CyclesRender_PT_geometry,
1777     CyclesRender_PT_light_paths,
1778     CyclesRender_PT_motion_blur,
1779     CyclesRender_PT_film,
1780     CyclesRender_PT_performance,
1781     CyclesRender_PT_layer_options,
1782     CyclesRender_PT_layer_passes,
1783     CyclesRender_PT_views,
1784     CyclesRender_PT_denoising,
1785     Cycles_PT_post_processing,
1786     CyclesCamera_PT_dof,
1787     Cycles_PT_context_material,
1788     CyclesObject_PT_motion_blur,
1789     CyclesObject_PT_cycles_settings,
1790     CYCLES_OT_use_shading_nodes,
1791     CyclesLamp_PT_preview,
1792     CyclesLamp_PT_lamp,
1793     CyclesLamp_PT_nodes,
1794     CyclesLamp_PT_spot,
1795     CyclesWorld_PT_preview,
1796     CyclesWorld_PT_surface,
1797     CyclesWorld_PT_volume,
1798     CyclesWorld_PT_ambient_occlusion,
1799     CyclesWorld_PT_mist,
1800     CyclesWorld_PT_ray_visibility,
1801     CyclesWorld_PT_settings,
1802     CyclesMaterial_PT_preview,
1803     CyclesMaterial_PT_surface,
1804     CyclesMaterial_PT_volume,
1805     CyclesMaterial_PT_displacement,
1806     CyclesMaterial_PT_settings,
1807     CyclesTexture_PT_context,
1808     CyclesTexture_PT_node,
1809     CyclesTexture_PT_mapping,
1810     CyclesTexture_PT_colors,
1811     CyclesParticle_PT_textures,
1812     CyclesRender_PT_bake,
1813     CyclesRender_PT_debug,
1814     CyclesParticle_PT_CurveSettings,
1815     CyclesScene_PT_simplify,
1816 )
1817
1818
1819 def register():
1820     from bpy.utils import register_class
1821
1822     bpy.types.RENDER_PT_render.append(draw_device)
1823     bpy.types.VIEW3D_HT_header.append(draw_pause)
1824
1825     for panel in get_panels():
1826         panel.COMPAT_ENGINES.add('CYCLES')
1827
1828     for cls in classes:
1829         register_class(cls)
1830
1831
1832 def unregister():
1833     from bpy.utils import unregister_class
1834
1835     bpy.types.RENDER_PT_render.remove(draw_device)
1836     bpy.types.VIEW3D_HT_header.remove(draw_pause)
1837
1838     for panel in get_panels():
1839         if 'CYCLES' in panel.COMPAT_ENGINES:
1840             panel.COMPAT_ENGINES.remove('CYCLES')
1841
1842     for cls in classes:
1843         unregister_class(cls)