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