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