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