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