Slightly generalized the crash fix in revision 54111.
[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
26 class CYCLES_MT_integrator_presets(Menu):
27     bl_label = "Integrator Presets"
28     preset_subdir = "cycles/integrator"
29     preset_operator = "script.execute_preset"
30     COMPAT_ENGINES = {'CYCLES'}
31     draw = Menu.draw_preset
32
33
34 class CyclesButtonsPanel():
35     bl_space_type = "PROPERTIES"
36     bl_region_type = "WINDOW"
37     bl_context = "render"
38
39     @classmethod
40     def poll(cls, context):
41         rd = context.scene.render
42         return rd.engine == 'CYCLES'
43
44
45 class CyclesRender_PT_sampling(CyclesButtonsPanel, Panel):
46     bl_label = "Sampling"
47     bl_options = {'DEFAULT_CLOSED'}
48
49     def draw(self, context):
50         layout = self.layout
51
52         scene = context.scene
53         cscene = scene.cycles
54         device_type = context.user_preferences.system.compute_device_type
55
56         split = layout.split()
57
58         col = split.column()
59         sub = col.column()
60         sub.active = (device_type == 'NONE' or cscene.device == 'CPU')
61         sub.prop(cscene, "progressive")
62
63         sub = col.column(align=True)
64         sub.prop(cscene, "seed")
65         sub.prop(cscene, "sample_clamp")
66
67         if cscene.progressive or (device_type != 'NONE' and cscene.device == 'GPU'):
68             col = split.column()
69             col.label(text="Samples:")
70             sub = col.column(align=True)
71             sub.prop(cscene, "samples", text="Render")
72             sub.prop(cscene, "preview_samples", text="Preview")
73         else:
74             sub.label(text="AA Samples:")
75             sub.prop(cscene, "aa_samples", text="Render")
76             sub.prop(cscene, "preview_aa_samples", text="Preview")
77
78             col = split.column()
79             col.label(text="Samples:")
80             sub = col.column(align=True)
81             sub.prop(cscene, "diffuse_samples", text="Diffuse")
82             sub.prop(cscene, "glossy_samples", text="Glossy")
83             sub.prop(cscene, "transmission_samples", text="Transmission")
84             sub.prop(cscene, "ao_samples", text="AO")
85             sub.prop(cscene, "mesh_light_samples", text="Mesh Light")
86
87
88 class CyclesRender_PT_light_paths(CyclesButtonsPanel, Panel):
89     bl_label = "Light Paths"
90     bl_options = {'DEFAULT_CLOSED'}
91
92     def draw(self, context):
93         layout = self.layout
94
95         scene = context.scene
96         cscene = scene.cycles
97
98         row = layout.row(align=True)
99         row.menu("CYCLES_MT_integrator_presets", text=bpy.types.CYCLES_MT_integrator_presets.bl_label)
100         row.operator("render.cycles_integrator_preset_add", text="", icon="ZOOMIN")
101         row.operator("render.cycles_integrator_preset_add", text="", icon="ZOOMOUT").remove_active = True
102
103         split = layout.split()
104
105         col = split.column()
106
107         sub = col.column(align=True)
108         sub.label("Transparency:")
109         sub.prop(cscene, "transparent_max_bounces", text="Max")
110         sub.prop(cscene, "transparent_min_bounces", text="Min")
111         sub.prop(cscene, "use_transparent_shadows", text="Shadows")
112
113         col.separator()
114
115         col.prop(cscene, "no_caustics")
116         col.prop(cscene, "blur_glossy")
117
118         col = split.column()
119
120         sub = col.column(align=True)
121         sub.label(text="Bounces:")
122         sub.prop(cscene, "max_bounces", text="Max")
123         sub.prop(cscene, "min_bounces", text="Min")
124
125         sub = col.column(align=True)
126         sub.prop(cscene, "diffuse_bounces", text="Diffuse")
127         sub.prop(cscene, "glossy_bounces", text="Glossy")
128         sub.prop(cscene, "transmission_bounces", text="Transmission")
129
130
131 class CyclesRender_PT_motion_blur(CyclesButtonsPanel, Panel):
132     bl_label = "Motion Blur"
133     bl_options = {'DEFAULT_CLOSED'}
134
135     def draw_header(self, context):
136         rd = context.scene.render
137
138         self.layout.prop(rd, "use_motion_blur", text="")
139
140     def draw(self, context):
141         layout = self.layout
142
143         rd = context.scene.render
144         layout.active = rd.use_motion_blur
145
146         row = layout.row()
147         row.prop(rd, "motion_blur_shutter")
148
149
150 class CyclesRender_PT_film(CyclesButtonsPanel, Panel):
151     bl_label = "Film"
152
153     def draw(self, context):
154         layout = self.layout
155
156         scene = context.scene
157         cscene = scene.cycles
158
159         split = layout.split()
160
161         col = split.column()
162         col.prop(cscene, "film_exposure")
163         col.prop(cscene, "film_transparent")
164
165         col = split.column()
166         sub = col.column(align=True)
167         sub.prop(cscene, "filter_type", text="")
168         if cscene.filter_type != 'BOX':
169             sub.prop(cscene, "filter_width", text="Width")
170
171
172 class CyclesRender_PT_performance(CyclesButtonsPanel, Panel):
173     bl_label = "Performance"
174     bl_options = {'DEFAULT_CLOSED'}
175
176     def draw(self, context):
177         layout = self.layout
178
179         scene = context.scene
180         rd = scene.render
181         cscene = scene.cycles
182
183         split = layout.split()
184
185         col = split.column(align=True)
186
187         col.label(text="Threads:")
188         col.row().prop(rd, "threads_mode", expand=True)
189         sub = col.column()
190         sub.enabled = rd.threads_mode == 'FIXED'
191         sub.prop(rd, "threads")
192
193         sub = col.column(align=True)
194         sub.label(text="Tiles:")
195         sub.prop(cscene, "tile_order", text="")
196
197         sub.prop(rd, "tile_x", text="X")
198         sub.prop(rd, "tile_y", text="Y")
199
200         sub.prop(cscene, "use_progressive_refine")
201
202         subsub = sub.column()
203         subsub.enabled = not rd.use_border
204         subsub.prop(rd, "use_save_buffers")
205
206         col = split.column()
207
208         sub = col.column(align=True)
209         sub.label(text="Acceleration structure:")
210         sub.prop(cscene, "debug_bvh_type", text="")
211         sub.prop(cscene, "debug_use_spatial_splits")
212         sub.prop(cscene, "use_cache")
213
214         sub = col.column(align=True)
215         sub.label(text="Viewport:")
216         sub.prop(cscene, "preview_start_resolution")
217
218         sub = col.column(align=True)
219         sub.label(text="Final Render:")
220         sub.prop(rd, "use_persistent_data", text="Persistent Images")
221
222
223 class Cycles_PT_post_processing(CyclesButtonsPanel, Panel):
224     bl_label = "Post Processing"
225     bl_options = {'DEFAULT_CLOSED'}
226
227     def draw(self, context):
228         layout = self.layout
229
230         rd = context.scene.render
231
232         split = layout.split()
233
234         col = split.column()
235         col.prop(rd, "use_compositing")
236         col.prop(rd, "use_sequencer")
237
238         col = split.column()
239         col.prop(rd, "dither_intensity", text="Dither", slider=True)
240
241
242 class CyclesCamera_PT_dof(CyclesButtonsPanel, Panel):
243     bl_label = "Depth of Field"
244     bl_context = "data"
245
246     @classmethod
247     def poll(cls, context):
248         return context.camera and CyclesButtonsPanel.poll(context)
249
250     def draw(self, context):
251         layout = self.layout
252
253         cam = context.camera
254         ccam = cam.cycles
255
256         split = layout.split()
257
258         col = split.column()
259         col.label("Focus:")
260         col.prop(cam, "dof_object", text="")
261
262         sub = col.row()
263         sub.active = cam.dof_object is None
264         sub.prop(cam, "dof_distance", text="Distance")
265
266         col = split.column()
267
268         col.label("Aperture:")
269         sub = col.column(align=True)
270         sub.prop(ccam, "aperture_type", text="")
271         if ccam.aperture_type == 'RADIUS':
272             sub.prop(ccam, "aperture_size", text="Size")
273         elif ccam.aperture_type == 'FSTOP':
274             sub.prop(ccam, "aperture_fstop", text="Number")
275
276         sub = col.column(align=True)
277         sub.prop(ccam, "aperture_blades", text="Blades")
278         sub.prop(ccam, "aperture_rotation", text="Rotation")
279
280
281 class CyclesRender_PT_layers(CyclesButtonsPanel, Panel):
282     bl_label = "Layers"
283     bl_options = {'HIDE_HEADER'}
284     bl_context = "render_layer"
285     COMPAT_ENGINES = {'CYCLES'}
286
287     def draw(self, context):
288         layout = self.layout
289
290         scene = context.scene
291         rd = scene.render
292
293         row = layout.row()
294         row.template_list("RENDER_UL_renderlayers", "", rd, "layers", rd.layers, "active_index", rows=2)
295
296         col = row.column(align=True)
297         col.operator("scene.render_layer_add", icon='ZOOMIN', text="")
298         col.operator("scene.render_layer_remove", icon='ZOOMOUT', text="")
299
300         row = layout.row()
301         rl = rd.layers.active
302         if rl:
303             row.prop(rl, "name")
304         row.prop(rd, "use_single_layer", text="", icon_only=True)
305
306
307 class CyclesRender_PT_layer_options(CyclesButtonsPanel, Panel):
308     bl_label = "Layer"
309     bl_options = {'DEFAULT_CLOSED'}
310     bl_context = "render_layer"
311     COMPAT_ENGINES = {'CYCLES'}
312
313     def draw(self, context):
314         layout = self.layout
315
316         scene = context.scene
317         rd = scene.render
318         rl = rd.layers.active
319
320         split = layout.split()
321
322         col = split.column()
323         col.prop(scene, "layers", text="Scene")
324         col.prop(rl, "layers_exclude", text="Exclude")
325
326         col = split.column()
327         col.prop(rl, "layers", text="Layer")
328         col.label(text="Mask Layers:")
329         col.prop(rl, "layers_zmask", text="")
330
331         split = layout.split()
332
333         col = split.column()
334         col.label(text="Material:")
335         col.prop(rl, "material_override", text="")
336
337         col = split.column()
338         col.prop(rl, "samples")
339         col.prop(rl, "use_sky", "Use Environment")
340
341
342 class CyclesRender_PT_layer_passes(CyclesButtonsPanel, Panel):
343     bl_label = "Layer"
344     bl_options = {'DEFAULT_CLOSED'}
345     bl_context = "render_layer"
346     COMPAT_ENGINES = {'CYCLES'}
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.label(text="Passes:")
359         col.prop(rl, "use_pass_combined")
360         col.prop(rl, "use_pass_z")
361         col.prop(rl, "use_pass_normal")
362         col.prop(rl, "use_pass_vector")
363         col.prop(rl, "use_pass_uv")
364         col.prop(rl, "use_pass_object_index")
365         col.prop(rl, "use_pass_material_index")
366         col.prop(rl, "use_pass_ambient_occlusion")
367         col.prop(rl, "use_pass_shadow")
368
369         col = split.column()
370         col.label()
371         col.label(text="Diffuse:")
372         row = col.row(align=True)
373         row.prop(rl, "use_pass_diffuse_direct", text="Direct", toggle=True)
374         row.prop(rl, "use_pass_diffuse_indirect", text="Indirect", toggle=True)
375         row.prop(rl, "use_pass_diffuse_color", text="Color", toggle=True)
376         col.label(text="Glossy:")
377         row = col.row(align=True)
378         row.prop(rl, "use_pass_glossy_direct", text="Direct", toggle=True)
379         row.prop(rl, "use_pass_glossy_indirect", text="Indirect", toggle=True)
380         row.prop(rl, "use_pass_glossy_color", text="Color", toggle=True)
381         col.label(text="Transmission:")
382         row = col.row(align=True)
383         row.prop(rl, "use_pass_transmission_direct", text="Direct", toggle=True)
384         row.prop(rl, "use_pass_transmission_indirect", text="Indirect", toggle=True)
385         row.prop(rl, "use_pass_transmission_color", text="Color", toggle=True)
386
387         col.prop(rl, "use_pass_emit", text="Emission")
388         col.prop(rl, "use_pass_environment")
389
390
391 class Cycles_PT_context_material(CyclesButtonsPanel, Panel):
392     bl_label = ""
393     bl_context = "material"
394     bl_options = {'HIDE_HEADER'}
395
396     @classmethod
397     def poll(cls, context):
398         return (context.material or context.object) and CyclesButtonsPanel.poll(context)
399
400     def draw(self, context):
401         layout = self.layout
402
403         mat = context.material
404         ob = context.object
405         slot = context.material_slot
406         space = context.space_data
407
408         if ob:
409             row = layout.row()
410
411             row.template_list("MATERIAL_UL_matslots", "", ob, "material_slots", ob, "active_material_index", rows=2)
412
413             col = row.column(align=True)
414             col.operator("object.material_slot_add", icon='ZOOMIN', text="")
415             col.operator("object.material_slot_remove", icon='ZOOMOUT', text="")
416
417             col.menu("MATERIAL_MT_specials", icon='DOWNARROW_HLT', text="")
418
419             if ob.mode == 'EDIT':
420                 row = layout.row(align=True)
421                 row.operator("object.material_slot_assign", text="Assign")
422                 row.operator("object.material_slot_select", text="Select")
423                 row.operator("object.material_slot_deselect", text="Deselect")
424
425         split = layout.split(percentage=0.65)
426
427         if ob:
428             split.template_ID(ob, "active_material", new="material.new")
429             row = split.row()
430
431             if slot:
432                 row.prop(slot, "link", text="")
433             else:
434                 row.label()
435         elif mat:
436             split.template_ID(space, "pin_id")
437             split.separator()
438
439
440 class Cycles_PT_mesh_displacement(CyclesButtonsPanel, Panel):
441     bl_label = "Displacement"
442     bl_context = "data"
443
444     @classmethod
445     def poll(cls, context):
446         if CyclesButtonsPanel.poll(context):
447             if context.mesh or context.curve or context.meta_ball:
448                 if context.scene.cycles.feature_set == 'EXPERIMENTAL':
449                     return True
450
451         return False
452
453     def draw(self, context):
454         layout = self.layout
455
456         mesh = context.mesh
457         curve = context.curve
458         mball = context.meta_ball
459
460         if mesh:
461             cdata = mesh.cycles
462         elif curve:
463             cdata = curve.cycles
464         elif mball:
465             cdata = mball.cycles
466
467         layout.prop(cdata, "displacement_method", text="Method")
468         layout.prop(cdata, "use_subdivision")
469         layout.prop(cdata, "dicing_rate")
470
471
472 class Cycles_PT_mesh_normals(CyclesButtonsPanel, Panel):
473     bl_label = "Normals"
474     bl_context = "data"
475
476     @classmethod
477     def poll(cls, context):
478         return CyclesButtonsPanel.poll(context) and context.mesh
479
480     def draw(self, context):
481         layout = self.layout
482
483         mesh = context.mesh
484
485         split = layout.split()
486
487         col = split.column()
488         col.prop(mesh, "show_double_sided")
489
490         col = split.column()
491         col.label()
492
493
494 class CyclesObject_PT_ray_visibility(CyclesButtonsPanel, Panel):
495     bl_label = "Ray Visibility"
496     bl_context = "object"
497     bl_options = {'DEFAULT_CLOSED'}
498
499     @classmethod
500     def poll(cls, context):
501         ob = context.object
502         return CyclesButtonsPanel.poll(context) and ob and ob.type in {'MESH', 'CURVE', 'CURVE', 'SURFACE', 'FONT', 'META'}  # todo: 'LAMP'
503
504     def draw(self, context):
505         layout = self.layout
506
507         ob = context.object
508         visibility = ob.cycles_visibility
509
510         flow = layout.column_flow()
511
512         flow.prop(visibility, "camera")
513         flow.prop(visibility, "diffuse")
514         flow.prop(visibility, "glossy")
515         flow.prop(visibility, "transmission")
516         flow.prop(visibility, "shadow")
517
518
519 def find_node(material, nodetype):
520     if material and material.node_tree:
521         ntree = material.node_tree
522
523         for node in ntree.nodes:
524             if getattr(node, "type", None) == nodetype:
525                 return node
526
527     return None
528
529
530 def find_node_input(node, name):
531     for input in node.inputs:
532         if input.name == name:
533             return input
534
535     return None
536
537
538 def panel_node_draw(layout, id_data, output_type, input_name):
539     if not id_data.use_nodes:
540         layout.prop(id_data, "use_nodes", icon='NODETREE')
541         return False
542
543     ntree = id_data.node_tree
544
545     node = find_node(id_data, output_type)
546     if not node:
547         layout.label(text="No output node.")
548     else:
549         input = find_node_input(node, input_name)
550         layout.template_node_view(ntree, node, input)
551
552     return True
553
554
555 class CyclesLamp_PT_lamp(CyclesButtonsPanel, Panel):
556     bl_label = "Lamp"
557     bl_context = "data"
558
559     @classmethod
560     def poll(cls, context):
561         return context.lamp and CyclesButtonsPanel.poll(context)
562
563     def draw(self, context):
564         layout = self.layout
565
566         lamp = context.lamp
567         clamp = lamp.cycles
568         cscene = context.scene.cycles
569         device_type = context.user_preferences.system.compute_device_type
570
571         layout.prop(lamp, "type", expand=True)
572
573         split = layout.split()
574         col = split.column(align=True)
575
576         if lamp.type in {'POINT', 'SUN', 'SPOT'}:
577             col.prop(lamp, "shadow_soft_size", text="Size")
578         elif lamp.type == 'AREA':
579             col.prop(lamp, "shape", text="")
580             sub = col.column(align=True)
581
582             if lamp.shape == 'SQUARE':
583                 sub.prop(lamp, "size")
584             elif lamp.shape == 'RECTANGLE':
585                 sub.prop(lamp, "size", text="Size X")
586                 sub.prop(lamp, "size_y", text="Size Y")
587
588         if not cscene.progressive and (device_type == 'NONE' or cscene.device == 'CPU'):
589             col.prop(clamp, "samples")
590
591         col = split.column()
592         col.prop(clamp, "cast_shadow")
593
594         if lamp.type == 'HEMI':
595             layout.label(text="Not supported, interpreted as sun lamp.")
596
597
598 class CyclesLamp_PT_nodes(CyclesButtonsPanel, Panel):
599     bl_label = "Nodes"
600     bl_context = "data"
601
602     @classmethod
603     def poll(cls, context):
604         return context.lamp and CyclesButtonsPanel.poll(context)
605
606     def draw(self, context):
607         layout = self.layout
608
609         lamp = context.lamp
610         if not panel_node_draw(layout, lamp, 'OUTPUT_LAMP', 'Surface'):
611             layout.prop(lamp, "color")
612
613
614 class CyclesLamp_PT_spot(CyclesButtonsPanel, Panel):
615     bl_label = "Spot Shape"
616     bl_context = "data"
617
618     @classmethod
619     def poll(cls, context):
620         lamp = context.lamp
621         return (lamp and lamp.type == 'SPOT') and CyclesButtonsPanel.poll(context)
622
623     def draw(self, context):
624         layout = self.layout
625
626         lamp = context.lamp
627
628         split = layout.split()
629
630         col = split.column()
631         sub = col.column()
632         sub.prop(lamp, "spot_size", text="Size")
633         sub.prop(lamp, "spot_blend", text="Blend", slider=True)
634
635         col = split.column()
636         col.prop(lamp, "show_cone")
637
638
639 class CyclesWorld_PT_surface(CyclesButtonsPanel, Panel):
640     bl_label = "Surface"
641     bl_context = "world"
642
643     @classmethod
644     def poll(cls, context):
645         return context.world and CyclesButtonsPanel.poll(context)
646
647     def draw(self, context):
648         layout = self.layout
649
650         world = context.world
651
652         if not panel_node_draw(layout, world, 'OUTPUT_WORLD', 'Surface'):
653             layout.prop(world, "horizon_color", text="Color")
654
655
656 class CyclesWorld_PT_volume(CyclesButtonsPanel, Panel):
657     bl_label = "Volume"
658     bl_context = "world"
659     bl_options = {'DEFAULT_CLOSED'}
660
661     @classmethod
662     def poll(cls, context):
663         # world = context.world
664         # world and world.node_tree and CyclesButtonsPanel.poll(context)
665         return False
666
667     def draw(self, context):
668         layout = self.layout
669         layout.active = False
670
671         world = context.world
672         panel_node_draw(layout, world, 'OUTPUT_WORLD', 'Volume')
673
674
675 class CyclesWorld_PT_ambient_occlusion(CyclesButtonsPanel, Panel):
676     bl_label = "Ambient Occlusion"
677     bl_context = "world"
678
679     @classmethod
680     def poll(cls, context):
681         return context.world and CyclesButtonsPanel.poll(context)
682
683     def draw_header(self, context):
684         light = context.world.light_settings
685         self.layout.prop(light, "use_ambient_occlusion", text="")
686
687     def draw(self, context):
688         layout = self.layout
689         light = context.world.light_settings
690
691         layout.active = light.use_ambient_occlusion
692
693         row = layout.row()
694         row.prop(light, "ao_factor", text="Factor")
695         row.prop(light, "distance", text="Distance")
696
697
698 class CyclesWorld_PT_settings(CyclesButtonsPanel, Panel):
699     bl_label = "Settings"
700     bl_context = "world"
701     bl_options = {'DEFAULT_CLOSED'}
702
703     @classmethod
704     def poll(cls, context):
705         return context.world and CyclesButtonsPanel.poll(context)
706
707     def draw(self, context):
708         layout = self.layout
709
710         world = context.world
711         cworld = world.cycles
712         cscene = context.scene.cycles
713         device_type = context.user_preferences.system.compute_device_type
714
715         col = layout.column()
716
717         col.prop(cworld, "sample_as_light")
718         sub = col.row(align=True)
719         sub.active = cworld.sample_as_light
720         sub.prop(cworld, "sample_map_resolution")
721         if not cscene.progressive and (device_type == 'NONE' or cscene.device == 'CPU'):
722             sub.prop(cworld, "samples")
723
724
725 class CyclesMaterial_PT_surface(CyclesButtonsPanel, Panel):
726     bl_label = "Surface"
727     bl_context = "material"
728
729     @classmethod
730     def poll(cls, context):
731         return context.material and CyclesButtonsPanel.poll(context)
732
733     def draw(self, context):
734         layout = self.layout
735
736         mat = context.material
737         if not panel_node_draw(layout, mat, 'OUTPUT_MATERIAL', 'Surface'):
738             layout.prop(mat, "diffuse_color")
739
740
741 class CyclesMaterial_PT_volume(CyclesButtonsPanel, Panel):
742     bl_label = "Volume"
743     bl_context = "material"
744     bl_options = {'DEFAULT_CLOSED'}
745
746     @classmethod
747     def poll(cls, context):
748         # mat = context.material
749         # mat and mat.node_tree and CyclesButtonsPanel.poll(context)
750         return False
751
752     def draw(self, context):
753         layout = self.layout
754         layout.active = False
755
756         mat = context.material
757         cmat = mat.cycles
758
759         panel_node_draw(layout, mat, 'OUTPUT_MATERIAL', 'Volume')
760
761         layout.prop(cmat, "homogeneous_volume")
762
763
764 class CyclesMaterial_PT_displacement(CyclesButtonsPanel, Panel):
765     bl_label = "Displacement"
766     bl_context = "material"
767
768     @classmethod
769     def poll(cls, context):
770         mat = context.material
771         return mat and mat.node_tree and CyclesButtonsPanel.poll(context)
772
773     def draw(self, context):
774         layout = self.layout
775
776         mat = context.material
777         panel_node_draw(layout, mat, 'OUTPUT_MATERIAL', 'Displacement')
778
779
780 class CyclesMaterial_PT_settings(CyclesButtonsPanel, Panel):
781     bl_label = "Settings"
782     bl_context = "material"
783     bl_options = {'DEFAULT_CLOSED'}
784
785     @classmethod
786     def poll(cls, context):
787         return context.material and CyclesButtonsPanel.poll(context)
788
789     def draw(self, context):
790         layout = self.layout
791
792         mat = context.material
793         cmat = mat.cycles
794
795         split = layout.split()
796
797         col = split.column()
798         col.prop(mat, "diffuse_color", text="Viewport Color")
799
800         col = split.column()
801         col.prop(cmat, "sample_as_light")
802         col.prop(mat, "pass_index")
803
804
805 class CyclesTexture_PT_context(CyclesButtonsPanel, Panel):
806     bl_label = ""
807     bl_context = "texture"
808     bl_options = {'HIDE_HEADER'}
809     COMPAT_ENGINES = {'CYCLES'}
810
811     def draw(self, context):
812         layout = self.layout
813
814         tex = context.texture
815         space = context.space_data
816         pin_id = space.pin_id
817         use_pin_id = space.use_pin_id
818         user = context.texture_user
819
820         if not use_pin_id or not isinstance(pin_id, bpy.types.Texture):
821             pin_id = None
822
823         if not pin_id:
824             layout.template_texture_user()
825
826         if user:
827             layout.separator()
828
829             split = layout.split(percentage=0.65)
830             col = split.column()
831
832             if pin_id:
833                 col.template_ID(space, "pin_id")
834             elif user:
835                 col.template_ID(user, "texture", new="texture.new")
836
837             if tex:
838                 split = layout.split(percentage=0.2)
839                 split.label(text="Type:")
840                 split.prop(tex, "type", text="")
841
842
843 class CyclesTexture_PT_nodes(CyclesButtonsPanel, Panel):
844     bl_label = "Nodes"
845     bl_context = "texture"
846
847     @classmethod
848     def poll(cls, context):
849         tex = context.texture
850         return (tex and tex.use_nodes) and CyclesButtonsPanel.poll(context)
851
852     def draw(self, context):
853         layout = self.layout
854
855         tex = context.texture
856         panel_node_draw(layout, tex, 'OUTPUT_TEXTURE', 'Color')
857
858
859 class CyclesTexture_PT_node(CyclesButtonsPanel, Panel):
860     bl_label = "Node"
861     bl_context = "texture"
862
863     @classmethod
864     def poll(cls, context):
865         node = context.texture_node
866         return node and CyclesButtonsPanel.poll(context)
867
868     def draw(self, context):
869         layout = self.layout
870
871         node = context.texture_node
872         ntree = node.id_data
873         layout.template_node_view(ntree, node, None)
874
875
876 class CyclesTexture_PT_mapping(CyclesButtonsPanel, Panel):
877     bl_label = "Mapping"
878     bl_context = "texture"
879
880     @classmethod
881     def poll(cls, context):
882         tex = context.texture
883         node = context.texture_node
884         return (node or (tex and tex.use_nodes)) and CyclesButtonsPanel.poll(context)
885
886     def draw(self, context):
887         layout = self.layout
888
889         # tex = context.texture
890         node = context.texture_node
891
892         mapping = node.texture_mapping
893
894         row = layout.row()
895
896         row.column().prop(mapping, "translation")
897         row.column().prop(mapping, "rotation")
898         row.column().prop(mapping, "scale")
899
900         layout.label(text="Projection:")
901
902         row = layout.row()
903         row.prop(mapping, "mapping_x", text="")
904         row.prop(mapping, "mapping_y", text="")
905         row.prop(mapping, "mapping_z", text="")
906
907
908 class CyclesTexture_PT_colors(CyclesButtonsPanel, Panel):
909     bl_label = "Color"
910     bl_context = "texture"
911     bl_options = {'DEFAULT_CLOSED'}
912
913     @classmethod
914     def poll(cls, context):
915         # tex = context.texture
916         # node = context.texture_node
917         return False
918         #return (node or (tex and tex.use_nodes)) and CyclesButtonsPanel.poll(context)
919
920     def draw(self, context):
921         layout = self.layout
922
923         # tex = context.texture
924         node = context.texture_node
925
926         mapping = node.color_mapping
927
928         split = layout.split()
929
930         col = split.column()
931         col.label(text="Blend:")
932         col.prop(mapping, "blend_type", text="")
933         col.prop(mapping, "blend_factor", text="Factor")
934         col.prop(mapping, "blend_color", text="")
935
936         col = split.column()
937         col.label(text="Adjust:")
938         col.prop(mapping, "brightness")
939         col.prop(mapping, "contrast")
940         col.prop(mapping, "saturation")
941
942         layout.separator()
943
944         layout.prop(mapping, "use_color_ramp", text="Ramp")
945         if mapping.use_color_ramp:
946             layout.template_color_ramp(mapping, "color_ramp", expand=True)
947
948
949 class CyclesParticle_PT_textures(CyclesButtonsPanel, Panel):
950     bl_label = "Textures"
951     bl_context = "particle"
952     bl_options = {'DEFAULT_CLOSED'}
953
954     @classmethod
955     def poll(cls, context):
956         psys = context.particle_system
957         return psys and CyclesButtonsPanel.poll(context)
958
959     def draw(self, context):
960         layout = self.layout
961
962         psys = context.particle_system
963         part = psys.settings
964
965         row = layout.row()
966         row.template_list("TEXTURE_UL_texslots", "", part, "texture_slots", part, "active_texture_index", rows=2)
967
968         col = row.column(align=True)
969         col.operator("texture.slot_move", text="", icon='TRIA_UP').type = 'UP'
970         col.operator("texture.slot_move", text="", icon='TRIA_DOWN').type = 'DOWN'
971         col.menu("TEXTURE_MT_specials", icon='DOWNARROW_HLT', text="")
972
973         if not part.active_texture:
974             layout.template_ID(part, "active_texture", new="texture.new")
975         else:
976             slot = part.texture_slots[part.active_texture_index]
977             layout.template_ID(slot, "texture", new="texture.new")
978
979 class CyclesRender_PT_CurveRendering(CyclesButtonsPanel, Panel):
980     bl_label = "Cycles Hair Rendering"
981     bl_context = "particle"
982     
983     @classmethod
984     def poll(cls, context):
985         psys = context.particle_system
986         device_type = context.user_preferences.system.compute_device_type
987         experimental = context.scene.cycles.feature_set == 'EXPERIMENTAL' and (context.scene.cycles.device == 'CPU' or device_type == 'NONE')
988         return CyclesButtonsPanel.poll(context) and experimental and psys
989         
990     def draw_header(self, context):
991         cscene = context.scene.cycles_curves
992         self.layout.prop(cscene, "use_curves", text="")
993     
994     def draw(self, context):
995         layout = self.layout
996         
997         scene = context.scene
998         cscene = scene.cycles_curves
999         
1000         layout.active = cscene.use_curves
1001         
1002         layout.prop(cscene, "preset", text="Mode")
1003         
1004         if cscene.preset == 'CUSTOM':
1005             layout.prop(cscene, "primitive", text="Primitive")
1006         
1007             if cscene.primitive == 'TRIANGLES':
1008                 layout.prop(cscene, "triangle_method", text="Method")
1009                 if cscene.triangle_method == 'TESSELLATED':
1010                     layout.prop(cscene, "resolution", text="Resolution")
1011                 layout.prop(cscene, "use_smooth", text="Smooth")
1012             elif cscene.primitive == 'LINE_SEGMENTS':
1013                 layout.prop(cscene, "use_backfacing", text="Check back-faces")
1014                 
1015                 row = layout.row()
1016                 row.prop(cscene, "use_encasing", text="Exclude encasing")
1017                 sub = row.row()
1018                 sub.active = cscene.use_encasing
1019                 sub.prop(cscene, "encasing_ratio", text="Ratio for encasing")
1020                 
1021                 layout.prop(cscene, "line_method", text="Method")
1022                 layout.prop(cscene, "use_tangent_normal", text="Use tangent normal as default")
1023                 layout.prop(cscene, "use_tangent_normal_geometry", text="Use tangent normal geometry")
1024                 layout.prop(cscene, "use_tangent_normal_correction", text="Correct tangent normal for slope")
1025                 layout.prop(cscene, "interpolation", text="Interpolation")
1026                 
1027                 row = layout.row()
1028                 row.prop(cscene, "segments", text="Segments")
1029                 row.prop(cscene, "normalmix", text="Ray Mix")
1030             
1031             row = layout.row()
1032             row.prop(cscene, "use_cache", text="Export cache with children")
1033             if cscene.use_cache:
1034                 row.prop(cscene, "use_parents", text="Include parents")  
1035             
1036 class CyclesParticle_PT_CurveSettings(CyclesButtonsPanel, Panel):
1037     bl_label = "Cycles Hair Settings"
1038     bl_context = "particle"
1039     
1040     @classmethod
1041     def poll(cls, context):
1042         use_curves = context.scene.cycles_curves.use_curves and context.particle_system
1043         device_type = context.user_preferences.system.compute_device_type
1044         experimental = context.scene.cycles.feature_set == 'EXPERIMENTAL' and (context.scene.cycles.device == 'CPU' or device_type == 'NONE')
1045         return CyclesButtonsPanel.poll(context) and experimental and use_curves
1046
1047     def draw(self, context):
1048         layout = self.layout
1049         
1050         psys = context.particle_settings
1051         cpsys = psys.cycles
1052         
1053         row = layout.row()
1054         row.prop(cpsys, "shape", text="Shape")
1055         row.prop(cpsys, "use_closetip", text="Close tip")
1056         
1057         layout.label(text="Width multiplier:")
1058         row = layout.row()
1059         row.prop(cpsys, "root_width", text="Root")
1060         row.prop(cpsys, "tip_width", text="Tip")
1061
1062
1063 class CyclesScene_PT_simplify(CyclesButtonsPanel, Panel):
1064     bl_label = "Simplify"
1065     bl_context = "scene"
1066     COMPAT_ENGINES = {'CYCLES'}
1067
1068     def draw_header(self, context):
1069         rd = context.scene.render
1070         self.layout.prop(rd, "use_simplify", text="")
1071
1072     def draw(self, context):
1073         layout = self.layout
1074
1075         rd = context.scene.render
1076
1077         layout.active = rd.use_simplify
1078
1079         split = layout.split()
1080
1081         col = split.column()
1082         col.prop(rd, "simplify_subdivision", text="Subdivision")
1083
1084         col = split.column()
1085         col.prop(rd, "simplify_child_particles", text="Child Particles")
1086
1087
1088 def draw_device(self, context):
1089     scene = context.scene
1090     layout = self.layout
1091
1092     if scene.render.engine == 'CYCLES':
1093         from . import engine
1094         cscene = scene.cycles
1095
1096         layout.prop(cscene, "feature_set")
1097
1098         device_type = context.user_preferences.system.compute_device_type
1099         if device_type == 'CUDA':
1100             layout.prop(cscene, "device")
1101         elif device_type == 'OPENCL' and cscene.feature_set == 'EXPERIMENTAL':
1102             layout.prop(cscene, "device")
1103
1104         if engine.with_osl() and (cscene.device == 'CPU' or device_type == 'NONE'):
1105             layout.prop(cscene, "shading_system")
1106
1107
1108 def draw_pause(self, context):
1109     layout = self.layout
1110     scene = context.scene
1111
1112     if scene.render.engine == "CYCLES":
1113         view = context.space_data
1114
1115         if view.viewport_shade == 'RENDERED':
1116             cscene = scene.cycles
1117             layername = scene.render.layers.active.name
1118             layout.prop(cscene, "preview_pause", icon="PAUSE", text="")
1119             layout.prop(cscene, "preview_active_layer", icon="RENDERLAYERS", text=layername)
1120
1121
1122 def get_panels():
1123     return (
1124         bpy.types.RENDER_PT_render,
1125         bpy.types.RENDER_PT_output,
1126         bpy.types.RENDER_PT_encoding,
1127         bpy.types.RENDER_PT_dimensions,
1128         bpy.types.RENDER_PT_stamp,
1129         bpy.types.SCENE_PT_scene,
1130         bpy.types.SCENE_PT_audio,
1131         bpy.types.SCENE_PT_unit,
1132         bpy.types.SCENE_PT_keying_sets,
1133         bpy.types.SCENE_PT_keying_set_paths,
1134         bpy.types.SCENE_PT_physics,
1135         bpy.types.WORLD_PT_context_world,
1136         bpy.types.DATA_PT_context_mesh,
1137         bpy.types.DATA_PT_context_camera,
1138         bpy.types.DATA_PT_context_lamp,
1139         bpy.types.DATA_PT_context_speaker,
1140         bpy.types.DATA_PT_texture_space,
1141         bpy.types.DATA_PT_curve_texture_space,
1142         bpy.types.DATA_PT_mball_texture_space,
1143         bpy.types.DATA_PT_vertex_groups,
1144         bpy.types.DATA_PT_shape_keys,
1145         bpy.types.DATA_PT_uv_texture,
1146         bpy.types.DATA_PT_vertex_colors,
1147         bpy.types.DATA_PT_camera,
1148         bpy.types.DATA_PT_camera_display,
1149         bpy.types.DATA_PT_lens,
1150         bpy.types.DATA_PT_speaker,
1151         bpy.types.DATA_PT_distance,
1152         bpy.types.DATA_PT_cone,
1153         bpy.types.DATA_PT_customdata,
1154         bpy.types.DATA_PT_custom_props_mesh,
1155         bpy.types.DATA_PT_custom_props_camera,
1156         bpy.types.DATA_PT_custom_props_lamp,
1157         bpy.types.DATA_PT_custom_props_speaker,
1158         bpy.types.TEXTURE_PT_clouds,
1159         bpy.types.TEXTURE_PT_wood,
1160         bpy.types.TEXTURE_PT_marble,
1161         bpy.types.TEXTURE_PT_magic,
1162         bpy.types.TEXTURE_PT_blend,
1163         bpy.types.TEXTURE_PT_stucci,
1164         bpy.types.TEXTURE_PT_image,
1165         bpy.types.TEXTURE_PT_image_sampling,
1166         bpy.types.TEXTURE_PT_image_mapping,
1167         bpy.types.TEXTURE_PT_musgrave,
1168         bpy.types.TEXTURE_PT_voronoi,
1169         bpy.types.TEXTURE_PT_distortednoise,
1170         bpy.types.TEXTURE_PT_voxeldata,
1171         bpy.types.TEXTURE_PT_pointdensity,
1172         bpy.types.TEXTURE_PT_pointdensity_turbulence,
1173         bpy.types.TEXTURE_PT_mapping,
1174         bpy.types.TEXTURE_PT_influence,
1175         bpy.types.TEXTURE_PT_colors,
1176         bpy.types.PARTICLE_PT_context_particles,
1177         bpy.types.PARTICLE_PT_emission,
1178         bpy.types.PARTICLE_PT_hair_dynamics,
1179         bpy.types.PARTICLE_PT_cache,
1180         bpy.types.PARTICLE_PT_velocity,
1181         bpy.types.PARTICLE_PT_rotation,
1182         bpy.types.PARTICLE_PT_physics,
1183         bpy.types.PARTICLE_PT_boidbrain,
1184         bpy.types.PARTICLE_PT_render,
1185         bpy.types.PARTICLE_PT_draw,
1186         bpy.types.PARTICLE_PT_children,
1187         bpy.types.PARTICLE_PT_field_weights,
1188         bpy.types.PARTICLE_PT_force_fields,
1189         bpy.types.PARTICLE_PT_vertexgroups,
1190         bpy.types.PARTICLE_PT_custom_props,
1191         )
1192
1193
1194 def register():
1195     bpy.types.RENDER_PT_render.append(draw_device)
1196     bpy.types.VIEW3D_HT_header.append(draw_pause)
1197
1198     for panel in get_panels():
1199         panel.COMPAT_ENGINES.add('CYCLES')
1200
1201
1202 def unregister():
1203     bpy.types.RENDER_PT_render.remove(draw_device)
1204     bpy.types.VIEW3D_HT_header.remove(draw_pause)
1205
1206     for panel in get_panels():
1207         panel.COMPAT_ENGINES.remove('CYCLES')