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