fix for [#28012] Mat ID messy with shader nodes
[blender.git] / release / scripts / startup / bl_ui / properties_material.py
1 # ##### BEGIN GPL LICENSE BLOCK #####
2 #
3 #  This program is free software; you can redistribute it and/or
4 #  modify it under the terms of the GNU General Public License
5 #  as published by the Free Software Foundation; either version 2
6 #  of the License, or (at your option) any later version.
7 #
8 #  This program is distributed in the hope that it will be useful,
9 #  but WITHOUT ANY WARRANTY; without even the implied warranty of
10 #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 #  GNU General Public License for more details.
12 #
13 #  You should have received a copy of the GNU General Public License
14 #  along with this program; if not, write to the Free Software Foundation,
15 #  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 #
17 # ##### END GPL LICENSE BLOCK #####
18
19 # <pep8 compliant>
20 import bpy
21 from rna_prop_ui import PropertyPanel
22
23
24 def active_node_mat(mat):
25     # TODO, 2.4x has a pipeline section, for 2.5 we need to communicate
26     # which settings from node-materials are used
27     if mat is not None:
28         mat_node = mat.active_node_material
29         if mat_node:
30             return mat_node
31         else:
32             return mat
33
34     return None
35
36
37 def check_material(mat):
38     if mat is not None:
39         if mat.use_nodes:
40             if mat.active_node_material is not None:
41                 return True
42             return False
43         return True
44     return False
45
46
47 def simple_material(mat):
48     if (mat is not None) and (not mat.use_nodes):
49         return True
50     return False
51
52
53 class MATERIAL_MT_sss_presets(bpy.types.Menu):
54     bl_label = "SSS Presets"
55     preset_subdir = "sss"
56     preset_operator = "script.execute_preset"
57     draw = bpy.types.Menu.draw_preset
58
59
60 class MATERIAL_MT_specials(bpy.types.Menu):
61     bl_label = "Material Specials"
62
63     def draw(self, context):
64         layout = self.layout
65
66         layout.operator("object.material_slot_copy", icon='COPY_ID')
67         layout.operator("material.copy", icon='COPYDOWN')
68         layout.operator("material.paste", icon='PASTEDOWN')
69
70
71 class MaterialButtonsPanel():
72     bl_space_type = 'PROPERTIES'
73     bl_region_type = 'WINDOW'
74     bl_context = "material"
75     # COMPAT_ENGINES must be defined in each subclass, external engines can add themselves here
76
77     @classmethod
78     def poll(cls, context):
79         return context.material and (context.scene.render.engine in cls.COMPAT_ENGINES)
80
81
82 class MATERIAL_PT_context_material(MaterialButtonsPanel, bpy.types.Panel):
83     bl_label = ""
84     bl_options = {'HIDE_HEADER'}
85     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
86
87     @classmethod
88     def poll(cls, context):
89         # An exception, dont call the parent poll func because
90         # this manages materials for all engine types
91
92         engine = context.scene.render.engine
93         return (context.material or context.object) and (engine in cls.COMPAT_ENGINES)
94
95     def draw(self, context):
96         layout = self.layout
97
98         mat = context.material
99         ob = context.object
100         slot = context.material_slot
101         space = context.space_data
102
103         if ob:
104             row = layout.row()
105
106             row.template_list(ob, "material_slots", ob, "active_material_index", rows=2)
107
108             col = row.column(align=True)
109             col.operator("object.material_slot_add", icon='ZOOMIN', text="")
110             col.operator("object.material_slot_remove", icon='ZOOMOUT', text="")
111
112             col.menu("MATERIAL_MT_specials", icon='DOWNARROW_HLT', text="")
113
114             if ob.mode == 'EDIT':
115                 row = layout.row(align=True)
116                 row.operator("object.material_slot_assign", text="Assign")
117                 row.operator("object.material_slot_select", text="Select")
118                 row.operator("object.material_slot_deselect", text="Deselect")
119
120         split = layout.split(percentage=0.65)
121
122         if ob:
123             split.template_ID(ob, "active_material", new="material.new")
124             row = split.row()
125             if mat:
126                 row.prop(mat, "use_nodes", icon="NODETREE", text="")
127
128             if slot:
129                 row.prop(slot, "link", text="")
130             else:
131                 row.label()
132         elif mat:
133             split.template_ID(space, "pin_id")
134             split.separator()
135
136         if mat:
137             layout.prop(mat, "type", expand=True)
138             if mat.use_nodes:
139                 row = layout.row()
140                 row.label(text="", icon='NODETREE')
141                 if mat.active_node_material:
142                     row.prop(mat.active_node_material, "name", text="")
143                 else:
144                     row.label(text="No material node selected")
145
146
147 class MATERIAL_PT_preview(MaterialButtonsPanel, bpy.types.Panel):
148     bl_label = "Preview"
149     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
150
151     def draw(self, context):
152         self.layout.template_preview(context.material)
153
154
155 class MATERIAL_PT_pipeline(MaterialButtonsPanel, bpy.types.Panel):
156     bl_label = "Render Pipeline Options"
157     bl_options = {'DEFAULT_CLOSED'}
158     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
159
160     @classmethod
161     def poll(cls, context):
162         mat = context.material
163         engine = context.scene.render.engine
164         return mat and (not simple_material(mat)) and (mat.type in {'SURFACE', 'WIRE', 'VOLUME'}) and (engine in cls.COMPAT_ENGINES)
165
166     def draw(self, context):
167         layout = self. layout
168
169         mat = context.material
170         mat_type = mat.type in {'SURFACE', 'WIRE'}
171
172         row = layout.row()
173         row.active = mat_type
174         row.prop(mat, "use_transparency")
175         sub = row.column()
176         sub.prop(mat, "offset_z")
177
178         sub.active = mat_type and mat.use_transparency and mat.transparency_method == 'Z_TRANSPARENCY'
179
180         row = layout.row()
181         row.active = mat.use_transparency or not mat_type
182         row.prop(mat, "transparency_method", expand=True)
183
184         layout.separator()
185
186         split = layout.split()
187         col = split.column()
188
189         col.prop(mat, "use_raytrace")
190         col.prop(mat, "use_full_oversampling")
191         sub = col.column()
192         sub.active = mat_type
193         sub.prop(mat, "use_sky")
194         sub.prop(mat, "invert_z")
195
196         col = split.column()
197         col.active = mat_type
198
199         col.prop(mat, "use_cast_shadows_only", text="Cast Only")
200         col.prop(mat, "shadow_cast_alpha", text="Casting Alpha")
201         col.prop(mat, "use_cast_buffer_shadows")
202         col.prop(mat, "use_cast_approximate")
203         col.prop(mat, "pass_index")
204
205
206 class MATERIAL_PT_diffuse(MaterialButtonsPanel, bpy.types.Panel):
207     bl_label = "Diffuse"
208     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
209
210     @classmethod
211     def poll(cls, context):
212         mat = context.material
213         engine = context.scene.render.engine
214         return check_material(mat) and (mat.type in {'SURFACE', 'WIRE'}) and (engine in cls.COMPAT_ENGINES)
215
216     def draw(self, context):
217         layout = self.layout
218
219         mat = active_node_mat(context.material)
220
221         split = layout.split()
222
223         col = split.column()
224         col.prop(mat, "diffuse_color", text="")
225         sub = col.column()
226         sub.active = (not mat.use_shadeless)
227         sub.prop(mat, "diffuse_intensity", text="Intensity")
228
229         col = split.column()
230         col.active = (not mat.use_shadeless)
231         col.prop(mat, "diffuse_shader", text="")
232         col.prop(mat, "use_diffuse_ramp", text="Ramp")
233
234         col = layout.column()
235         col.active = (not mat.use_shadeless)
236         if mat.diffuse_shader == 'OREN_NAYAR':
237             col.prop(mat, "roughness")
238         elif mat.diffuse_shader == 'MINNAERT':
239             col.prop(mat, "darkness")
240         elif mat.diffuse_shader == 'TOON':
241             row = col.row()
242             row.prop(mat, "diffuse_toon_size", text="Size")
243             row.prop(mat, "diffuse_toon_smooth", text="Smooth")
244         elif mat.diffuse_shader == 'FRESNEL':
245             row = col.row()
246             row.prop(mat, "diffuse_fresnel", text="Fresnel")
247             row.prop(mat, "diffuse_fresnel_factor", text="Factor")
248
249         if mat.use_diffuse_ramp:
250             layout.separator()
251             layout.template_color_ramp(mat, "diffuse_ramp", expand=True)
252             layout.separator()
253
254             row = layout.row()
255             row.prop(mat, "diffuse_ramp_input", text="Input")
256             row.prop(mat, "diffuse_ramp_blend", text="Blend")
257
258             layout.prop(mat, "diffuse_ramp_factor", text="Factor")
259
260
261 class MATERIAL_PT_specular(MaterialButtonsPanel, bpy.types.Panel):
262     bl_label = "Specular"
263     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
264
265     @classmethod
266     def poll(cls, context):
267         mat = context.material
268         engine = context.scene.render.engine
269         return check_material(mat) and (mat.type in {'SURFACE', 'WIRE'}) and (engine in cls.COMPAT_ENGINES)
270
271     def draw(self, context):
272         layout = self.layout
273
274         mat = active_node_mat(context.material)
275
276         layout.active = (not mat.use_shadeless)
277
278         split = layout.split()
279
280         col = split.column()
281         col.prop(mat, "specular_color", text="")
282         col.prop(mat, "specular_intensity", text="Intensity")
283
284         col = split.column()
285         col.prop(mat, "specular_shader", text="")
286         col.prop(mat, "use_specular_ramp", text="Ramp")
287
288         col = layout.column()
289         if mat.specular_shader in {'COOKTORR', 'PHONG'}:
290             col.prop(mat, "specular_hardness", text="Hardness")
291         elif mat.specular_shader == 'BLINN':
292             row = col.row()
293             row.prop(mat, "specular_hardness", text="Hardness")
294             row.prop(mat, "specular_ior", text="IOR")
295         elif mat.specular_shader == 'WARDISO':
296             col.prop(mat, "specular_slope", text="Slope")
297         elif mat.specular_shader == 'TOON':
298             row = col.row()
299             row.prop(mat, "specular_toon_size", text="Size")
300             row.prop(mat, "specular_toon_smooth", text="Smooth")
301
302         if mat.use_specular_ramp:
303             layout.separator()
304             layout.template_color_ramp(mat, "specular_ramp", expand=True)
305             layout.separator()
306
307             row = layout.row()
308             row.prop(mat, "specular_ramp_input", text="Input")
309             row.prop(mat, "specular_ramp_blend", text="Blend")
310
311             layout.prop(mat, "specular_ramp_factor", text="Factor")
312
313
314 class MATERIAL_PT_shading(MaterialButtonsPanel, bpy.types.Panel):
315     bl_label = "Shading"
316     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
317
318     @classmethod
319     def poll(cls, context):
320         mat = context.material
321         engine = context.scene.render.engine
322         return check_material(mat) and (mat.type in {'SURFACE', 'WIRE'}) and (engine in cls.COMPAT_ENGINES)
323
324     def draw(self, context):
325         layout = self.layout
326
327         mat = active_node_mat(context.material)
328
329         if mat.type in {'SURFACE', 'WIRE'}:
330             split = layout.split()
331
332             col = split.column()
333             sub = col.column()
334             sub.active = not mat.use_shadeless
335             sub.prop(mat, "emit")
336             sub.prop(mat, "ambient")
337             sub = col.column()
338             sub.prop(mat, "translucency")
339
340             col = split.column()
341             col.prop(mat, "use_shadeless")
342             sub = col.column()
343             sub.active = not mat.use_shadeless
344             sub.prop(mat, "use_tangent_shading")
345             sub.prop(mat, "use_cubic")
346
347
348 class MATERIAL_PT_transp(MaterialButtonsPanel, bpy.types.Panel):
349     bl_label = "Transparency"
350     # bl_options = {'DEFAULT_CLOSED'}
351     COMPAT_ENGINES = {'BLENDER_RENDER'}
352
353     @classmethod
354     def poll(cls, context):
355         mat = context.material
356         engine = context.scene.render.engine
357         return check_material(mat) and (mat.type in {'SURFACE', 'WIRE'}) and (engine in cls.COMPAT_ENGINES)
358
359     def draw_header(self, context):
360         mat = context.material
361
362         if simple_material(mat):
363             self.layout.prop(mat, "use_transparency", text="")
364
365     def draw(self, context):
366         layout = self.layout
367
368         base_mat = context.material
369         mat = active_node_mat(context.material)
370         rayt = mat.raytrace_transparency
371
372         if simple_material(base_mat):
373             row = layout.row()
374             row.active = mat.use_transparency
375             row.prop(mat, "transparency_method", expand=True)
376
377         split = layout.split()
378         split.active = base_mat.use_transparency
379
380         col = split.column()
381         col.prop(mat, "alpha")
382         row = col.row()
383         row.active = (base_mat.transparency_method != 'MASK') and (not mat.use_shadeless)
384         row.prop(mat, "specular_alpha", text="Specular")
385
386         col = split.column()
387         col.active = (not mat.use_shadeless)
388         col.prop(rayt, "fresnel")
389         sub = col.column()
390         sub.active = rayt.fresnel > 0
391         sub.prop(rayt, "fresnel_factor", text="Blend")
392
393         if base_mat.transparency_method == 'RAYTRACE':
394             layout.separator()
395             split = layout.split()
396             split.active = base_mat.use_transparency
397
398             col = split.column()
399             col.prop(rayt, "ior")
400             col.prop(rayt, "filter")
401             col.prop(rayt, "falloff")
402             col.prop(rayt, "depth_max")
403             col.prop(rayt, "depth")
404
405             col = split.column()
406             col.label(text="Gloss:")
407             col.prop(rayt, "gloss_factor", text="Amount")
408             sub = col.column()
409             sub.active = rayt.gloss_factor < 1.0
410             sub.prop(rayt, "gloss_threshold", text="Threshold")
411             sub.prop(rayt, "gloss_samples", text="Samples")
412
413
414 class MATERIAL_PT_mirror(MaterialButtonsPanel, bpy.types.Panel):
415     bl_label = "Mirror"
416     bl_options = {'DEFAULT_CLOSED'}
417     COMPAT_ENGINES = {'BLENDER_RENDER'}
418
419     @classmethod
420     def poll(cls, context):
421         mat = context.material
422         engine = context.scene.render.engine
423         return check_material(mat) and (mat.type in {'SURFACE', 'WIRE'}) and (engine in cls.COMPAT_ENGINES)
424
425     def draw_header(self, context):
426         raym = active_node_mat(context.material).raytrace_mirror
427
428         self.layout.prop(raym, "use", text="")
429
430     def draw(self, context):
431         layout = self.layout
432
433         mat = active_node_mat(context.material)
434         raym = mat.raytrace_mirror
435
436         layout.active = raym.use
437
438         split = layout.split()
439
440         col = split.column()
441         col.prop(raym, "reflect_factor")
442         col.prop(mat, "mirror_color", text="")
443
444         col = split.column()
445         col.prop(raym, "fresnel")
446         sub = col.column()
447         sub.active = raym.fresnel > 0
448         sub.prop(raym, "fresnel_factor", text="Blend")
449
450         split = layout.split()
451
452         col = split.column()
453         col.separator()
454         col.prop(raym, "depth")
455         col.prop(raym, "distance", text="Max Dist")
456         col.separator()
457         sub = col.split(percentage=0.4)
458         sub.active = raym.distance > 0.0
459         sub.label(text="Fade To:")
460         sub.prop(raym, "fade_to", text="")
461
462         col = split.column()
463         col.label(text="Gloss:")
464         col.prop(raym, "gloss_factor", text="Amount")
465         sub = col.column()
466         sub.active = raym.gloss_factor < 1.0
467         sub.prop(raym, "gloss_threshold", text="Threshold")
468         sub.prop(raym, "gloss_samples", text="Samples")
469         sub.prop(raym, "gloss_anisotropic", text="Anisotropic")
470
471
472 class MATERIAL_PT_sss(MaterialButtonsPanel, bpy.types.Panel):
473     bl_label = "Subsurface Scattering"
474     bl_options = {'DEFAULT_CLOSED'}
475     COMPAT_ENGINES = {'BLENDER_RENDER'}
476
477     @classmethod
478     def poll(cls, context):
479         mat = context.material
480         engine = context.scene.render.engine
481         return check_material(mat) and (mat.type in {'SURFACE', 'WIRE'}) and (engine in cls.COMPAT_ENGINES)
482
483     def draw_header(self, context):
484         mat = active_node_mat(context.material)
485         sss = mat.subsurface_scattering
486
487         self.layout.active = (not mat.use_shadeless)
488         self.layout.prop(sss, "use", text="")
489
490     def draw(self, context):
491         layout = self.layout
492
493         mat = active_node_mat(context.material)
494         sss = mat.subsurface_scattering
495
496         layout.active = (sss.use) and (not mat.use_shadeless)
497
498         row = layout.row().split()
499         sub = row.row(align=True).split(percentage=0.75)
500         sub.menu("MATERIAL_MT_sss_presets", text=bpy.types.MATERIAL_MT_sss_presets.bl_label)
501         sub.operator("material.sss_preset_add", text="", icon="ZOOMIN")
502         sub.operator("material.sss_preset_add", text="", icon="ZOOMOUT").remove_active = True
503
504         split = layout.split()
505
506         col = split.column()
507         col.prop(sss, "ior")
508         col.prop(sss, "scale")
509         col.prop(sss, "color", text="")
510         col.prop(sss, "radius", text="RGB Radius", expand=True)
511
512         col = split.column()
513         sub = col.column(align=True)
514         sub.label(text="Blend:")
515         sub.prop(sss, "color_factor", text="Color")
516         sub.prop(sss, "texture_factor", text="Texture")
517         sub.label(text="Scattering Weight:")
518         sub.prop(sss, "front")
519         sub.prop(sss, "back")
520         col.separator()
521         col.prop(sss, "error_threshold", text="Error")
522
523
524 class MATERIAL_PT_halo(MaterialButtonsPanel, bpy.types.Panel):
525     bl_label = "Halo"
526     COMPAT_ENGINES = {'BLENDER_RENDER'}
527
528     @classmethod
529     def poll(cls, context):
530         mat = context.material
531         engine = context.scene.render.engine
532         return mat and (mat.type == 'HALO') and (engine in cls.COMPAT_ENGINES)
533
534     def draw(self, context):
535         layout = self.layout
536
537         mat = context.material  # dont use node material
538         halo = mat.halo
539
540         def number_but(layout, toggle, number, name, color):
541             row = layout.row(align=True)
542             row.prop(halo, toggle, text="")
543             sub = row.column()
544             sub.active = getattr(halo, toggle)
545             sub.prop(halo, number, text=name)
546             if not color == "":
547                 sub.prop(mat, color, text="")
548
549         split = layout.split()
550
551         col = split.column()
552         col.prop(mat, "alpha")
553         col.prop(mat, "diffuse_color", text="")
554         col.prop(halo, "seed")
555
556         col = split.column()
557         col.prop(halo, "size")
558         col.prop(halo, "hardness")
559         col.prop(halo, "add")
560
561         layout.label(text="Options:")
562
563         split = layout.split()
564         col = split.column()
565         col.prop(halo, "use_texture")
566         col.prop(halo, "use_vertex_normal")
567         col.prop(halo, "use_extreme_alpha")
568         col.prop(halo, "use_shaded")
569         col.prop(halo, "use_soft")
570
571         col = split.column()
572         number_but(col, "use_ring", "ring_count", "Rings", "mirror_color")
573         number_but(col, "use_lines", "line_count", "Lines", "specular_color")
574         number_but(col, "use_star", "star_tip_count", "Star tips", "")
575
576
577 class MATERIAL_PT_flare(MaterialButtonsPanel, bpy.types.Panel):
578     bl_label = "Flare"
579     COMPAT_ENGINES = {'BLENDER_RENDER'}
580
581     @classmethod
582     def poll(cls, context):
583         mat = context.material
584         engine = context.scene.render.engine
585         return mat and (mat.type == 'HALO') and (engine in cls.COMPAT_ENGINES)
586
587     def draw_header(self, context):
588         halo = context.material.halo
589
590         self.layout.prop(halo, "use_flare_mode", text="")
591
592     def draw(self, context):
593         layout = self.layout
594
595         mat = context.material  # dont use node material
596         halo = mat.halo
597
598         layout.active = halo.use_flare_mode
599
600         split = layout.split()
601
602         col = split.column()
603         col.prop(halo, "flare_size", text="Size")
604         col.prop(halo, "flare_boost", text="Boost")
605         col.prop(halo, "flare_seed", text="Seed")
606
607         col = split.column()
608         col.prop(halo, "flare_subflare_count", text="Subflares")
609         col.prop(halo, "flare_subflare_size", text="Subsize")
610
611
612 class MATERIAL_PT_physics(MaterialButtonsPanel, bpy.types.Panel):
613     bl_label = "Physics"
614     COMPAT_ENGINES = {'BLENDER_GAME'}
615
616     @classmethod
617     def poll(cls, context):
618         return context.material and (context.scene.render.engine in cls.COMPAT_ENGINES)
619
620     def draw(self, context):
621         layout = self.layout
622
623         phys = context.material.physics  # dont use node material
624
625         split = layout.split()
626         row = split.row()
627         row.prop(phys, "friction")
628         row.prop(phys, "elasticity", slider=True)
629
630         row = layout.row()
631         row.label(text="Force Field:")
632
633         row = layout.row()
634         row.prop(phys, "fh_force")
635         row.prop(phys, "fh_damping", slider=True)
636
637         row = layout.row()
638         row.prop(phys, "fh_distance")
639         row.prop(phys, "use_fh_normal")
640
641
642 class MATERIAL_PT_strand(MaterialButtonsPanel, bpy.types.Panel):
643     bl_label = "Strand"
644     bl_options = {'DEFAULT_CLOSED'}
645     COMPAT_ENGINES = {'BLENDER_RENDER'}
646
647     @classmethod
648     def poll(cls, context):
649         mat = context.material
650         engine = context.scene.render.engine
651         return mat and (mat.type in {'SURFACE', 'WIRE', 'HALO'}) and (engine in cls.COMPAT_ENGINES)
652
653     def draw(self, context):
654         layout = self.layout
655
656         mat = context.material  # dont use node material
657         tan = mat.strand
658
659         split = layout.split()
660
661         col = split.column()
662         sub = col.column(align=True)
663         sub.label(text="Size:")
664         sub.prop(tan, "root_size", text="Root")
665         sub.prop(tan, "tip_size", text="Tip")
666         sub.prop(tan, "size_min", text="Minimum")
667         sub.prop(tan, "use_blender_units")
668         sub = col.column()
669         sub.active = (not mat.use_shadeless)
670         sub.prop(tan, "use_tangent_shading")
671         col.prop(tan, "shape")
672
673         col = split.column()
674         col.label(text="Shading:")
675         col.prop(tan, "width_fade")
676         ob = context.object
677         if ob and ob.type == 'MESH':
678             col.prop_search(tan, "uv_layer", ob.data, "uv_textures", text="")
679         else:
680             col.prop(tan, "uv_layer", text="")
681         col.separator()
682         sub = col.column()
683         sub.active = (not mat.use_shadeless)
684         sub.label("Surface diffuse:")
685         sub = col.column()
686         sub.prop(tan, "blend_distance", text="Distance")
687
688
689 class MATERIAL_PT_options(MaterialButtonsPanel, bpy.types.Panel):
690     bl_label = "Options"
691     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
692
693     @classmethod
694     def poll(cls, context):
695         mat = context.material
696         engine = context.scene.render.engine
697         return check_material(mat) and (mat.type in {'SURFACE', 'WIRE'}) and (engine in cls.COMPAT_ENGINES)
698
699     def draw(self, context):
700         layout = self.layout
701
702         base_mat = context.material
703         mat = active_node_mat(base_mat)
704
705         split = layout.split()
706
707         col = split.column()
708         if simple_material(base_mat):
709             col.prop(mat, "use_raytrace")
710             col.prop(mat, "use_full_oversampling")
711             col.prop(mat, "use_sky")
712         col.prop(mat, "use_mist")
713         if simple_material(base_mat):
714             col.prop(mat, "invert_z")
715             sub = col.row()
716             sub.prop(mat, "offset_z")
717             sub.active = mat.use_transparency and mat.transparency_method == 'Z_TRANSPARENCY'
718         sub = col.column(align=True)
719         sub.label(text="Light Group:")
720         sub.prop(mat, "light_group", text="")
721         row = sub.row()
722         row.active = bool(mat.light_group)
723         row.prop(mat, "use_light_group_exclusive", text="Exclusive")
724
725         col = split.column()
726         col.prop(mat, "use_face_texture")
727         sub = col.column()
728         sub.active = mat.use_face_texture
729         sub.prop(mat, "use_face_texture_alpha")
730         col.separator()
731         col.prop(mat, "use_vertex_color_paint")
732         col.prop(mat, "use_vertex_color_light")
733         col.prop(mat, "use_object_color")
734         if simple_material(base_mat):
735             col.prop(mat, "pass_index")
736
737
738 class MATERIAL_PT_shadow(MaterialButtonsPanel, bpy.types.Panel):
739     bl_label = "Shadow"
740     bl_options = {'DEFAULT_CLOSED'}
741     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
742
743     @classmethod
744     def poll(cls, context):
745         mat = context.material
746         engine = context.scene.render.engine
747         return check_material(mat) and (mat.type in {'SURFACE', 'WIRE'}) and (engine in cls.COMPAT_ENGINES)
748
749     def draw(self, context):
750         layout = self.layout
751
752         base_mat = context.material
753         mat = active_node_mat(base_mat)
754
755         split = layout.split()
756
757         col = split.column()
758         col.prop(mat, "use_shadows", text="Receive")
759         col.prop(mat, "use_transparent_shadows", text="Receive Transparent")
760         if simple_material(base_mat):
761             col.prop(mat, "use_cast_shadows_only", text="Cast Only")
762             col.prop(mat, "shadow_cast_alpha", text="Casting Alpha")
763         col.prop(mat, "use_only_shadow", text="Shadows Only")
764         sub = col.column()
765         sub.active = mat.use_only_shadow
766         sub.prop(mat, "shadow_only_type", text="")
767
768         col = split.column()
769         if simple_material(base_mat):
770             col.prop(mat, "use_cast_buffer_shadows")
771         sub = col.column()
772         sub.active = mat.use_cast_buffer_shadows
773         sub.prop(mat, "shadow_buffer_bias", text="Buffer Bias")
774         col.prop(mat, "use_ray_shadow_bias", text="Auto Ray Bias")
775         sub = col.column()
776         sub.active = (not mat.use_ray_shadow_bias)
777         sub.prop(mat, "shadow_ray_bias", text="Ray Bias")
778         if simple_material(base_mat):
779             col.prop(mat, "use_cast_approximate")
780
781
782 class MATERIAL_PT_transp_game(MaterialButtonsPanel, bpy.types.Panel):
783     bl_label = "Transparency"
784     bl_options = {'DEFAULT_CLOSED'}
785     COMPAT_ENGINES = {'BLENDER_GAME'}
786
787     @classmethod
788     def poll(cls, context):
789         mat = context.material
790         engine = context.scene.render.engine
791         return check_material(mat) and (engine in cls.COMPAT_ENGINES)
792
793     def draw_header(self, context):
794         mat = context.material
795
796         if simple_material(mat):
797             self.layout.prop(mat, "use_transparency", text="")
798
799     def draw(self, context):
800         layout = self.layout
801         base_mat = context.material
802         mat = active_node_mat(base_mat)
803
804         if simple_material(base_mat):
805             row = layout.row()
806             row.active = mat.use_transparency
807             row.prop(mat, "transparency_method", expand=True)
808
809         layout.prop(mat, "alpha")
810
811
812 class VolumeButtonsPanel():
813     bl_space_type = 'PROPERTIES'
814     bl_region_type = 'WINDOW'
815     bl_context = "material"
816     COMPAT_ENGINES = {'BLENDER_RENDER'}
817
818     @classmethod
819     def poll(cls, context):
820         mat = context.material
821         engine = context.scene.render.engine
822         return mat and (mat.type == 'VOLUME') and (engine in cls.COMPAT_ENGINES)
823
824
825 class MATERIAL_PT_volume_density(VolumeButtonsPanel, bpy.types.Panel):
826     bl_label = "Density"
827     COMPAT_ENGINES = {'BLENDER_RENDER'}
828
829     def draw(self, context):
830         layout = self.layout
831
832         vol = context.material.volume  # dont use node material
833
834         row = layout.row()
835         row.prop(vol, "density")
836         row.prop(vol, "density_scale")
837
838
839 class MATERIAL_PT_volume_shading(VolumeButtonsPanel, bpy.types.Panel):
840     bl_label = "Shading"
841     COMPAT_ENGINES = {'BLENDER_RENDER'}
842
843     def draw(self, context):
844         layout = self.layout
845
846         vol = context.material.volume  # dont use node material
847
848         split = layout.split()
849
850         col = split.column()
851         col.prop(vol, "scattering")
852         col.prop(vol, "asymmetry")
853         col.prop(vol, "transmission_color")
854
855         col = split.column()
856         sub = col.column(align=True)
857         sub.prop(vol, "emission")
858         sub.prop(vol, "emission_color", text="")
859         sub = col.column(align=True)
860         sub.prop(vol, "reflection")
861         sub.prop(vol, "reflection_color", text="")
862
863
864 class MATERIAL_PT_volume_lighting(VolumeButtonsPanel, bpy.types.Panel):
865     bl_label = "Lighting"
866     COMPAT_ENGINES = {'BLENDER_RENDER'}
867
868     def draw(self, context):
869         layout = self.layout
870
871         vol = context.material.volume  # dont use node material
872
873         split = layout.split()
874
875         col = split.column()
876         col.prop(vol, "light_method", text="")
877
878         col = split.column()
879
880         if vol.light_method == 'SHADED':
881             col.prop(vol, "use_external_shadows")
882             col.prop(vol, "use_light_cache")
883             sub = col.column()
884             sub.active = vol.use_light_cache
885             sub.prop(vol, "cache_resolution")
886         elif vol.light_method in {'MULTIPLE_SCATTERING', 'SHADED_PLUS_MULTIPLE_SCATTERING'}:
887             sub = col.column()
888             sub.enabled = True
889             sub.active = False
890             sub.label("Light Cache Enabled")
891             col.prop(vol, "cache_resolution")
892
893             sub = col.column(align=True)
894             sub.prop(vol, "ms_diffusion")
895             sub.prop(vol, "ms_spread")
896             sub.prop(vol, "ms_intensity")
897
898
899 class MATERIAL_PT_volume_transp(VolumeButtonsPanel, bpy.types.Panel):
900     bl_label = "Transparency"
901     COMPAT_ENGINES = {'BLENDER_RENDER'}
902
903     @classmethod
904     def poll(cls, context):
905         mat = context.material
906         engine = context.scene.render.engine
907         return mat and simple_material(mat) and (mat.type == 'VOLUME') and (engine in cls.COMPAT_ENGINES)
908
909     def draw(self, context):
910         layout = self.layout
911
912         mat = context.material  # dont use node material
913
914         layout.prop(mat, "transparency_method", expand=True)
915
916
917 class MATERIAL_PT_volume_integration(VolumeButtonsPanel, bpy.types.Panel):
918     bl_label = "Integration"
919     COMPAT_ENGINES = {'BLENDER_RENDER'}
920
921     def draw(self, context):
922         layout = self.layout
923
924         vol = context.material.volume  # dont use node material
925
926         split = layout.split()
927
928         col = split.column()
929         col.label(text="Step Calculation:")
930         col.prop(vol, "step_method", text="")
931         col = col.column(align=True)
932         col.prop(vol, "step_size")
933
934         col = split.column()
935         col.label()
936         col.prop(vol, "depth_threshold")
937
938
939 class MATERIAL_PT_volume_options(VolumeButtonsPanel, bpy.types.Panel):
940     bl_label = "Options"
941     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
942     bl_options = {'DEFAULT_CLOSED'}
943
944     @classmethod
945     def poll(cls, context):
946         mat = context.material
947         engine = context.scene.render.engine
948         return check_material(mat) and (mat.type == 'VOLUME') and (engine in cls.COMPAT_ENGINES)
949
950     def draw(self, context):
951         layout = self.layout
952
953         mat = active_node_mat(context.material)
954
955         split = layout.split()
956
957         col = split.column()
958         if simple_material(context.material):
959             col.prop(mat, "use_raytrace")
960             col.prop(mat, "use_full_oversampling")
961         col.prop(mat, "use_mist")
962
963         col = split.column()
964         col.label(text="Light Group:")
965         col.prop(mat, "light_group", text="")
966         row = col.row()
967         row.active = bool(mat.light_group)
968         row.prop(mat, "use_light_group_exclusive", text="Exclusive")
969
970
971 class MATERIAL_PT_custom_props(MaterialButtonsPanel, PropertyPanel, bpy.types.Panel):
972     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
973     _context_path = "material"
974     _property_type = bpy.types.Material
975
976 if __name__ == "__main__":  # only for live edit.
977     bpy.utils.register_module(__name__)