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