minor cycles edits
[blender.git] / intern / cycles / blender / addon / ui.py
1 #
2 # Copyright 2011, Blender Foundation.
3 #
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 # GNU General Public License for more details.
13 #
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software Foundation,
16 # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 #
18
19 # <pep8 compliant>
20
21 import bpy
22
23 from bpy.types import Panel, Menu
24
25 from . import enums, engine
26
27
28 class CYCLES_MT_integrator_presets(Menu):
29     bl_label = "Integrator Presets"
30     preset_subdir = "cycles/integrator"
31     preset_operator = "script.execute_preset"
32     COMPAT_ENGINES = {'CYCLES'}
33     draw = Menu.draw_preset
34
35
36 class CyclesButtonsPanel():
37     bl_space_type = "PROPERTIES"
38     bl_region_type = "WINDOW"
39     bl_context = "render"
40
41     @classmethod
42     def poll(cls, context):
43         rd = context.scene.render
44         return rd.engine == 'CYCLES'
45
46
47 class CyclesRender_PT_integrator(CyclesButtonsPanel, Panel):
48     bl_label = "Integrator"
49     bl_options = {'DEFAULT_CLOSED'}
50
51     def draw(self, context):
52         layout = self.layout
53
54         scene = context.scene
55         cscene = scene.cycles
56
57         row = layout.row(align=True)
58         row.menu("CYCLES_MT_integrator_presets", text=bpy.types.CYCLES_MT_integrator_presets.bl_label)
59         row.operator("render.cycles_integrator_preset_add", text="", icon="ZOOMIN")
60         row.operator("render.cycles_integrator_preset_add", text="", icon="ZOOMOUT").remove_active = True
61
62         split = layout.split()
63
64         col = split.column()
65         sub = col.column(align=True)
66         sub.label(text="Samples:")
67         sub.prop(cscene, "samples", text="Render")
68         sub.prop(cscene, "preview_samples", text="Preview")
69         sub.prop(cscene, "seed")
70
71         sub = col.column(align=True)
72         sub.label("Transparency:")
73         sub.prop(cscene, "transparent_max_bounces", text="Max")
74         sub.prop(cscene, "transparent_min_bounces", text="Min")
75         sub.prop(cscene, "use_transparent_shadows", text="Shadows")
76
77         col = split.column()
78
79         sub = col.column(align=True)
80         sub.label(text="Bounces:")
81         sub.prop(cscene, "max_bounces", text="Max")
82         sub.prop(cscene, "min_bounces", text="Min")
83
84         sub = col.column(align=True)
85         sub.label(text="Light Paths:")
86         sub.prop(cscene, "diffuse_bounces", text="Diffuse")
87         sub.prop(cscene, "glossy_bounces", text="Glossy")
88         sub.prop(cscene, "transmission_bounces", text="Transmission")
89         sub.prop(cscene, "no_caustics")
90
91         #row = col.row()
92         #row.prop(cscene, "blur_caustics")
93         #row.active = not cscene.no_caustics
94
95
96 class CyclesRender_PT_film(CyclesButtonsPanel, Panel):
97     bl_label = "Film"
98
99     def draw(self, context):
100         layout = self.layout
101
102         scene = context.scene
103         cscene = scene.cycles
104
105         split = layout.split()
106
107         col = split.column()
108         col.prop(cscene, "film_exposure")
109         col.prop(cscene, "film_transparent")
110
111         col = split.column()
112         sub = col.column(align=True)
113         sub.prop(cscene, "filter_type", text="")
114         if cscene.filter_type != 'BOX':
115             sub.prop(cscene, "filter_width", text="Width")
116
117
118 class CyclesRender_PT_performance(CyclesButtonsPanel, Panel):
119     bl_label = "Performance"
120     bl_options = {'DEFAULT_CLOSED'}
121
122     def draw(self, context):
123         layout = self.layout
124
125         scene = context.scene
126         rd = scene.render
127         cscene = scene.cycles
128
129         split = layout.split()
130
131         col = split.column(align=True)
132
133         col.label(text="Threads:")
134         col.row().prop(rd, "threads_mode", expand=True)
135         sub = col.column()
136         sub.enabled = rd.threads_mode == 'FIXED'
137         sub.prop(rd, "threads")
138
139         sub = col.column(align=True)
140         sub.label(text="Tiles:")
141         sub.prop(cscene, "debug_tile_size")
142         sub.prop(cscene, "debug_min_size")
143
144         col = split.column()
145
146         sub = col.column(align=True)
147         sub.label(text="Acceleration structure:")
148         sub.prop(cscene, "debug_bvh_type", text="")
149         sub.prop(cscene, "debug_use_spatial_splits")
150
151
152 class CyclesRender_PT_layers(CyclesButtonsPanel, Panel):
153     bl_label = "Layers"
154     bl_options = {'DEFAULT_CLOSED'}
155     COMPAT_ENGINES = {'BLENDER_RENDER'}
156
157     def draw(self, context):
158         layout = self.layout
159
160         scene = context.scene
161         rd = scene.render
162
163         # row = layout.row()
164         # row.template_list(rd, "layers", rd.layers, "active_index", rows=2)
165
166         # col = row.column(align=True)
167         # col.operator("scene.render_layer_add", icon='ZOOMIN', text="")
168         # col.operator("scene.render_layer_remove", icon='ZOOMOUT', text="")
169
170         row = layout.row()
171         # rl = rd.layers.active
172         rl = rd.layers[0]
173         row.prop(rl, "name")
174         #row.prop(rd, "use_single_layer", text="", icon_only=True)
175
176         split = layout.split()
177
178         col = split.column()
179         col.prop(scene, "layers", text="Scene")
180
181         col = split.column()
182         col.prop(rl, "layers", text="Layer")
183
184         layout.separator()
185
186         layout.prop(rl, "material_override", text="Material")
187
188
189 class Cycles_PT_post_processing(CyclesButtonsPanel, Panel):
190     bl_label = "Post Processing"
191     bl_options = {'DEFAULT_CLOSED'}
192
193     def draw(self, context):
194         layout = self.layout
195
196         rd = context.scene.render
197
198         split = layout.split()
199
200         col = split.column()
201         col.prop(rd, "use_compositing")
202         col.prop(rd, "use_sequencer")
203
204         col = split.column()
205         col.prop(rd, "dither_intensity", text="Dither", slider=True)
206
207
208 class CyclesCamera_PT_dof(CyclesButtonsPanel, Panel):
209     bl_label = "Depth of Field"
210     bl_context = "data"
211
212     @classmethod
213     def poll(cls, context):
214         return context.camera and CyclesButtonsPanel.poll(context)
215
216     def draw(self, context):
217         layout = self.layout
218
219         cam = context.camera
220         ccam = cam.cycles
221
222         split = layout.split()
223
224         col = split.column()
225         col.label("Focus:")
226         col.prop(cam, "dof_object", text="")
227
228         sub = col.row()
229         sub.active = cam.dof_object is None
230         sub.prop(cam, "dof_distance", text="Distance")
231
232         col = split.column()
233
234         col.label("Aperture:")
235         col.prop(ccam, "aperture_size", text="Size")
236
237         sub = col.column(align=True)
238         sub.prop(ccam, "aperture_blades", text="Blades")
239         sub.prop(ccam, "aperture_rotation", text="Rotation")
240
241
242 class Cycles_PT_context_material(CyclesButtonsPanel, Panel):
243     bl_label = "Surface"
244     bl_context = "material"
245     bl_options = {'HIDE_HEADER'}
246
247     @classmethod
248     def poll(cls, context):
249         return (context.material or context.object) and CyclesButtonsPanel.poll(context)
250
251     def draw(self, context):
252         layout = self.layout
253
254         mat = context.material
255         ob = context.object
256         slot = context.material_slot
257         space = context.space_data
258
259         if ob:
260             row = layout.row()
261
262             row.template_list(ob, "material_slots", ob, "active_material_index", rows=2)
263
264             col = row.column(align=True)
265             col.operator("object.material_slot_add", icon='ZOOMIN', text="")
266             col.operator("object.material_slot_remove", icon='ZOOMOUT', text="")
267
268             col.menu("MATERIAL_MT_specials", icon='DOWNARROW_HLT', text="")
269
270             if ob.mode == 'EDIT':
271                 row = layout.row(align=True)
272                 row.operator("object.material_slot_assign", text="Assign")
273                 row.operator("object.material_slot_select", text="Select")
274                 row.operator("object.material_slot_deselect", text="Deselect")
275
276         split = layout.split(percentage=0.65)
277
278         if ob:
279             split.template_ID(ob, "active_material", new="material.new")
280             row = split.row()
281
282             if slot:
283                 row.prop(slot, "link", text="")
284             else:
285                 row.label()
286         elif mat:
287             split.template_ID(space, "pin_id")
288             split.separator()
289
290
291 class Cycles_PT_mesh_displacement(CyclesButtonsPanel, Panel):
292     bl_label = "Displacement"
293     bl_context = "data"
294
295     @classmethod
296     def poll(cls, context):
297         return CyclesButtonsPanel.poll(context) and (context.mesh or context.curve or context.meta_ball)
298
299     def draw(self, context):
300         layout = self.layout
301
302         mesh = context.mesh
303         curve = context.curve
304         mball = context.meta_ball
305
306         if mesh:
307             cdata = mesh.cycles
308         elif curve:
309             cdata = curve.cycles
310         elif mball:
311             cdata = mball.cycles
312
313         layout.prop(cdata, "displacement_method", text="Method")
314         layout.prop(cdata, "use_subdivision")
315         layout.prop(cdata, "dicing_rate")
316
317
318 class CyclesObject_PT_ray_visibility(CyclesButtonsPanel, Panel):
319     bl_label = "Ray Visibility"
320     bl_context = "object"
321     bl_options = {'DEFAULT_CLOSED'}
322
323     @classmethod
324     def poll(cls, context):
325         ob = context.object
326         return CyclesButtonsPanel.poll(context) and ob and ob.type in {'MESH', 'CURVE', 'CURVE', 'SURFACE', 'FONT', 'META'}  # todo: 'LAMP'
327
328     def draw(self, context):
329         layout = self.layout
330
331         ob = context.object
332         visibility = ob.cycles_visibility
333
334         split = layout.split()
335
336         col = split.column()
337         col.prop(visibility, "camera")
338         col.prop(visibility, "diffuse")
339         col.prop(visibility, "glossy")
340
341         col = split.column()
342         col.prop(visibility, "transmission")
343         col.prop(visibility, "shadow")
344
345
346 def find_node(material, nodetype):
347     if material and material.node_tree:
348         ntree = material.node_tree
349
350         for node in ntree.nodes:
351             if getattr(node, "type", None) == nodetype:
352                 return node
353
354     return None
355
356
357 def find_node_input(node, name):
358     for input in node.inputs:
359         if input.name == name:
360             return input
361
362     return None
363
364
365 def panel_node_draw(layout, id_data, output_type, input_name):
366     if not id_data.node_tree:
367         layout.prop(id_data, "use_nodes", icon='NODETREE')
368         return False
369
370     ntree = id_data.node_tree
371
372     node = find_node(id_data, output_type)
373     if not node:
374         layout.label(text="No output node.")
375     else:
376         input = find_node_input(node, input_name)
377         layout.template_node_view(ntree, node, input)
378
379     return True
380
381
382 class CyclesLamp_PT_lamp(CyclesButtonsPanel, Panel):
383     bl_label = "Lamp"
384     bl_context = "data"
385
386     @classmethod
387     def poll(cls, context):
388         return context.lamp and CyclesButtonsPanel.poll(context)
389
390     def draw(self, context):
391         layout = self.layout
392
393         lamp = context.lamp
394         clamp = lamp.cycles
395
396         layout.prop(lamp, "type", expand=True)
397
398         split = layout.split()
399         col = split.column(align=True)
400
401         if lamp.type in {'POINT', 'SUN', 'SPOT'}:
402             col.prop(lamp, "shadow_soft_size", text="Size")
403         elif lamp.type == 'AREA':
404             col.prop(lamp, "shape", text="")
405             sub = col.column(align=True)
406
407             if lamp.shape == 'SQUARE':
408                 sub.prop(lamp, "size")
409             elif lamp.shape == 'RECTANGLE':
410                 sub.prop(lamp, "size", text="Size X")
411                 sub.prop(lamp, "size_y", text="Size Y")
412
413         col = split.column()
414         col.prop(clamp, "cast_shadow")
415
416         if lamp.type == 'SPOT':
417             layout.label(text="Not supported, interpreted as point lamp.")
418         elif lamp.type == 'HEMI':
419             layout.label(text="Not supported, interpreted as sun lamp.")
420
421
422 class CyclesLamp_PT_nodes(CyclesButtonsPanel, Panel):
423     bl_label = "Nodes"
424     bl_context = "data"
425
426     @classmethod
427     def poll(cls, context):
428         return context.lamp and CyclesButtonsPanel.poll(context)
429
430     def draw(self, context):
431         layout = self.layout
432
433         lamp = context.lamp
434         if not panel_node_draw(layout, lamp, 'OUTPUT_LAMP', 'Surface'):
435             layout.prop(lamp, "color")
436
437
438 class CyclesWorld_PT_surface(CyclesButtonsPanel, Panel):
439     bl_label = "Surface"
440     bl_context = "world"
441
442     @classmethod
443     def poll(cls, context):
444         return context.world and CyclesButtonsPanel.poll(context)
445
446     def draw(self, context):
447         layout = self.layout
448
449         world = context.world
450         if not panel_node_draw(layout, world, 'OUTPUT_WORLD', 'Surface'):
451             layout.prop(world, "horizon_color", text="Color")
452
453
454 class CyclesWorld_PT_volume(CyclesButtonsPanel, Panel):
455     bl_label = "Volume"
456     bl_context = "world"
457     bl_options = {'DEFAULT_CLOSED'}
458
459     @classmethod
460     def poll(cls, context):
461         # world = context.world
462         # world and world.node_tree and CyclesButtonsPanel.poll(context)
463         return False
464
465     def draw(self, context):
466         layout = self.layout
467         layout.active = False
468
469         world = context.world
470         panel_node_draw(layout, world, 'OUTPUT_WORLD', 'Volume')
471
472
473 class CyclesMaterial_PT_surface(CyclesButtonsPanel, Panel):
474     bl_label = "Surface"
475     bl_context = "material"
476
477     @classmethod
478     def poll(cls, context):
479         return context.material and CyclesButtonsPanel.poll(context)
480
481     def draw(self, context):
482         layout = self.layout
483
484         mat = context.material
485         if not panel_node_draw(layout, mat, 'OUTPUT_MATERIAL', 'Surface'):
486             layout.prop(mat, "diffuse_color")
487
488
489 class CyclesMaterial_PT_volume(CyclesButtonsPanel, Panel):
490     bl_label = "Volume"
491     bl_context = "material"
492     bl_options = {'DEFAULT_CLOSED'}
493
494     @classmethod
495     def poll(cls, context):
496         # mat = context.material
497         # mat and mat.node_tree and CyclesButtonsPanel.poll(context)
498         return False
499
500     def draw(self, context):
501         layout = self.layout
502         layout.active = False
503
504         mat = context.material
505         cmat = mat.cycles
506
507         panel_node_draw(layout, mat, 'OUTPUT_MATERIAL', 'Volume')
508
509         layout.prop(cmat, "homogeneous_volume")
510
511
512 class CyclesMaterial_PT_displacement(CyclesButtonsPanel, Panel):
513     bl_label = "Displacement"
514     bl_context = "material"
515
516     @classmethod
517     def poll(cls, context):
518         mat = context.material
519         return mat and mat.node_tree and CyclesButtonsPanel.poll(context)
520
521     def draw(self, context):
522         layout = self.layout
523
524         mat = context.material
525         panel_node_draw(layout, mat, 'OUTPUT_MATERIAL', 'Displacement')
526
527
528 class CyclesMaterial_PT_settings(CyclesButtonsPanel, Panel):
529     bl_label = "Settings"
530     bl_context = "material"
531     bl_options = {'DEFAULT_CLOSED'}
532
533     @classmethod
534     def poll(cls, context):
535         return context.material and CyclesButtonsPanel.poll(context)
536
537     def draw(self, context):
538         layout = self.layout
539
540         mat = context.material
541         cmat = mat.cycles
542
543         split = layout.split()
544
545         col = split.column()
546         col.prop(mat, "diffuse_color", text="Viewport Color")
547
548         col = split.column()
549         col.prop(cmat, "sample_as_light")
550
551
552 class CyclesTexture_PT_context(CyclesButtonsPanel, Panel):
553     bl_label = ""
554     bl_context = "texture"
555     bl_options = {'HIDE_HEADER'}
556     COMPAT_ENGINES = {'CYCLES'}
557
558     def draw(self, context):
559         layout = self.layout
560
561         tex = context.texture
562         space = context.space_data
563         pin_id = space.pin_id
564         use_pin_id = space.use_pin_id
565         user = context.texture_user
566         # node = context.texture_node
567
568         if not use_pin_id or not isinstance(pin_id, bpy.types.Texture):
569             pin_id = None
570
571         if not pin_id:
572             layout.template_texture_user()
573
574         if user:
575             layout.separator()
576
577             split = layout.split(percentage=0.65)
578             col = split.column()
579
580             if pin_id:
581                 col.template_ID(space, "pin_id")
582             elif user:
583                 col.template_ID(user, "texture", new="texture.new")
584
585             if tex:
586                 row = split.row()
587                 row.prop(tex, "use_nodes", icon="NODETREE", text="")
588                 row.label()
589
590                 if not tex.use_nodes:
591                     split = layout.split(percentage=0.2)
592                     split.label(text="Type:")
593                     split.prop(tex, "type", text="")
594
595
596 class CyclesTexture_PT_nodes(CyclesButtonsPanel, Panel):
597     bl_label = "Nodes"
598     bl_context = "texture"
599
600     @classmethod
601     def poll(cls, context):
602         tex = context.texture
603         return (tex and tex.use_nodes) and CyclesButtonsPanel.poll(context)
604
605     def draw(self, context):
606         layout = self.layout
607
608         tex = context.texture
609         panel_node_draw(layout, tex, 'OUTPUT_TEXTURE', 'Color')
610
611
612 class CyclesTexture_PT_node(CyclesButtonsPanel, Panel):
613     bl_label = "Node"
614     bl_context = "texture"
615
616     @classmethod
617     def poll(cls, context):
618         node = context.texture_node
619         return node and CyclesButtonsPanel.poll(context)
620
621     def draw(self, context):
622         layout = self.layout
623
624         node = context.texture_node
625         ntree = node.id_data
626         layout.template_node_view(ntree, node, None)
627
628
629 class CyclesTexture_PT_mapping(CyclesButtonsPanel, Panel):
630     bl_label = "Mapping"
631     bl_context = "texture"
632
633     @classmethod
634     def poll(cls, context):
635         tex = context.texture
636         node = context.texture_node
637         return (node or (tex and tex.use_nodes)) and CyclesButtonsPanel.poll(context)
638
639     def draw(self, context):
640         layout = self.layout
641
642         # tex = context.texture
643         node = context.texture_node
644
645         mapping = node.texture_mapping
646
647         row = layout.row()
648
649         row.column().prop(mapping, "location")
650         row.column().prop(mapping, "rotation")
651         row.column().prop(mapping, "scale")
652
653         layout.label(text="Projection:")
654
655         row = layout.row()
656         row.prop(mapping, "mapping_x", text="")
657         row.prop(mapping, "mapping_y", text="")
658         row.prop(mapping, "mapping_z", text="")
659
660
661 class CyclesTexture_PT_colors(CyclesButtonsPanel, Panel):
662     bl_label = "Color"
663     bl_context = "texture"
664     bl_options = {'DEFAULT_CLOSED'}
665
666     @classmethod
667     def poll(cls, context):
668         # tex = context.texture
669         # node = context.texture_node
670         return False
671         #return (node or (tex and tex.use_nodes)) and CyclesButtonsPanel.poll(context)
672
673     def draw(self, context):
674         layout = self.layout
675
676         # tex = context.texture
677         node = context.texture_node
678
679         mapping = node.color_mapping
680
681         split = layout.split()
682
683         col = split.column()
684         col.label(text="Blend:")
685         col.prop(mapping, "blend_type", text="")
686         col.prop(mapping, "blend_factor", text="Factor")
687         col.prop(mapping, "blend_color", text="")
688
689         col = split.column()
690         col.label(text="Adjust:")
691         col.prop(mapping, "brightness")
692         col.prop(mapping, "contrast")
693         col.prop(mapping, "saturation")
694
695         layout.separator()
696
697         layout.prop(mapping, "use_color_ramp", text="Ramp")
698         if mapping.use_color_ramp:
699             layout.template_color_ramp(mapping, "color_ramp", expand=True)
700
701
702 def draw_device(self, context):
703     scene = context.scene
704     layout = self.layout
705
706     if scene.render.engine == "CYCLES":
707         cscene = scene.cycles
708
709         available_devices = engine.available_devices()
710         available_cuda = 'cuda' in available_devices
711         available_opencl = 'opencl' in available_devices
712
713         if available_cuda or available_opencl:
714             layout.prop(cscene, "device")
715             if cscene.device == 'GPU' and available_cuda and available_opencl:
716                 layout.prop(cscene, "gpu_type")
717         if cscene.device == 'CPU' and engine.with_osl():
718             layout.prop(cscene, "shading_system")
719
720
721 def draw_pause(self, context):
722     layout = self.layout
723     scene = context.scene
724
725     if scene.render.engine == "CYCLES":
726         view = context.space_data
727
728         if view.viewport_shade == "RENDERED":
729             cscene = scene.cycles
730             layout.prop(cscene, "preview_pause", icon="PAUSE", text="")
731
732
733 def get_panels():
734     return (
735         bpy.types.RENDER_PT_render,
736         bpy.types.RENDER_PT_output,
737         bpy.types.RENDER_PT_encoding,
738         bpy.types.RENDER_PT_dimensions,
739         bpy.types.RENDER_PT_stamp,
740         bpy.types.WORLD_PT_context_world,
741         bpy.types.DATA_PT_context_mesh,
742         bpy.types.DATA_PT_context_camera,
743         bpy.types.DATA_PT_context_lamp,
744         bpy.types.DATA_PT_texture_space,
745         bpy.types.DATA_PT_curve_texture_space,
746         bpy.types.DATA_PT_mball_texture_space,
747         bpy.types.DATA_PT_vertex_groups,
748         bpy.types.DATA_PT_shape_keys,
749         bpy.types.DATA_PT_uv_texture,
750         bpy.types.DATA_PT_vertex_colors,
751         bpy.types.DATA_PT_camera,
752         bpy.types.DATA_PT_camera_display,
753         bpy.types.DATA_PT_lens,
754         bpy.types.DATA_PT_custom_props_mesh,
755         bpy.types.DATA_PT_custom_props_camera,
756         bpy.types.DATA_PT_custom_props_lamp,
757         bpy.types.TEXTURE_PT_clouds,
758         bpy.types.TEXTURE_PT_wood,
759         bpy.types.TEXTURE_PT_marble,
760         bpy.types.TEXTURE_PT_magic,
761         bpy.types.TEXTURE_PT_blend,
762         bpy.types.TEXTURE_PT_stucci,
763         bpy.types.TEXTURE_PT_image,
764         bpy.types.TEXTURE_PT_image_sampling,
765         bpy.types.TEXTURE_PT_image_mapping,
766         bpy.types.TEXTURE_PT_musgrave,
767         bpy.types.TEXTURE_PT_voronoi,
768         bpy.types.TEXTURE_PT_distortednoise,
769         bpy.types.TEXTURE_PT_voxeldata,
770         bpy.types.TEXTURE_PT_pointdensity,
771         bpy.types.TEXTURE_PT_pointdensity_turbulence,
772         bpy.types.PARTICLE_PT_context_particles,
773         bpy.types.PARTICLE_PT_emission,
774         bpy.types.PARTICLE_PT_hair_dynamics,
775         bpy.types.PARTICLE_PT_cache,
776         bpy.types.PARTICLE_PT_velocity,
777         bpy.types.PARTICLE_PT_rotation,
778         bpy.types.PARTICLE_PT_physics,
779         bpy.types.PARTICLE_PT_boidbrain,
780         bpy.types.PARTICLE_PT_render,
781         bpy.types.PARTICLE_PT_draw,
782         bpy.types.PARTICLE_PT_children,
783         bpy.types.PARTICLE_PT_field_weights,
784         bpy.types.PARTICLE_PT_force_fields,
785         bpy.types.PARTICLE_PT_vertexgroups,
786         bpy.types.PARTICLE_PT_custom_props,
787         )
788
789
790 def register():
791     bpy.types.RENDER_PT_render.append(draw_device)
792     bpy.types.VIEW3D_HT_header.append(draw_pause)
793
794     for panel in get_panels():
795         panel.COMPAT_ENGINES.add('CYCLES')
796
797
798 def unregister():
799     bpy.types.RENDER_PT_render.remove(draw_device)
800     bpy.types.VIEW3D_HT_header.remove(draw_pause)
801
802     for panel in get_panels():
803         panel.COMPAT_ENGINES.remove('CYCLES')