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