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