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