Patch by oenvoyage - olivier amrein, thanks a lot!
[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             col = layout.column()
251             col.active = (not mat.use_shadeless)
252             col.separator()
253             col.template_color_ramp(mat, "diffuse_ramp", expand=True)
254             col.separator()
255
256             row = col.row()
257             row.prop(mat, "diffuse_ramp_input", text="Input")
258             row.prop(mat, "diffuse_ramp_blend", text="Blend")
259
260             col.prop(mat, "diffuse_ramp_factor", text="Factor")
261
262
263 class MATERIAL_PT_specular(MaterialButtonsPanel, bpy.types.Panel):
264     bl_label = "Specular"
265     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
266
267     @classmethod
268     def poll(cls, context):
269         mat = context.material
270         engine = context.scene.render.engine
271         return check_material(mat) and (mat.type in {'SURFACE', 'WIRE'}) and (engine in cls.COMPAT_ENGINES)
272
273     def draw(self, context):
274         layout = self.layout
275
276         mat = active_node_mat(context.material)
277
278         layout.active = (not mat.use_shadeless)
279
280         split = layout.split()
281
282         col = split.column()
283         col.prop(mat, "specular_color", text="")
284         col.prop(mat, "specular_intensity", text="Intensity")
285
286         col = split.column()
287         col.prop(mat, "specular_shader", text="")
288         col.prop(mat, "use_specular_ramp", text="Ramp")
289
290         col = layout.column()
291         if mat.specular_shader in {'COOKTORR', 'PHONG'}:
292             col.prop(mat, "specular_hardness", text="Hardness")
293         elif mat.specular_shader == 'BLINN':
294             row = col.row()
295             row.prop(mat, "specular_hardness", text="Hardness")
296             row.prop(mat, "specular_ior", text="IOR")
297         elif mat.specular_shader == 'WARDISO':
298             col.prop(mat, "specular_slope", text="Slope")
299         elif mat.specular_shader == 'TOON':
300             row = col.row()
301             row.prop(mat, "specular_toon_size", text="Size")
302             row.prop(mat, "specular_toon_smooth", text="Smooth")
303
304         if mat.use_specular_ramp:
305             layout.separator()
306             layout.template_color_ramp(mat, "specular_ramp", expand=True)
307             layout.separator()
308
309             row = layout.row()
310             row.prop(mat, "specular_ramp_input", text="Input")
311             row.prop(mat, "specular_ramp_blend", text="Blend")
312
313             layout.prop(mat, "specular_ramp_factor", text="Factor")
314
315
316 class MATERIAL_PT_shading(MaterialButtonsPanel, bpy.types.Panel):
317     bl_label = "Shading"
318     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
319
320     @classmethod
321     def poll(cls, context):
322         mat = context.material
323         engine = context.scene.render.engine
324         return check_material(mat) and (mat.type in {'SURFACE', 'WIRE'}) and (engine in cls.COMPAT_ENGINES)
325
326     def draw(self, context):
327         layout = self.layout
328
329         mat = active_node_mat(context.material)
330
331         if mat.type in {'SURFACE', 'WIRE'}:
332             split = layout.split()
333
334             col = split.column()
335             sub = col.column()
336             sub.active = not mat.use_shadeless
337             sub.prop(mat, "emit")
338             sub.prop(mat, "ambient")
339             sub = col.column()
340             sub.prop(mat, "translucency")
341
342             col = split.column()
343             col.prop(mat, "use_shadeless")
344             sub = col.column()
345             sub.active = not mat.use_shadeless
346             sub.prop(mat, "use_tangent_shading")
347             sub.prop(mat, "use_cubic")
348
349
350 class MATERIAL_PT_transp(MaterialButtonsPanel, bpy.types.Panel):
351     bl_label = "Transparency"
352     # bl_options = {'DEFAULT_CLOSED'}
353     COMPAT_ENGINES = {'BLENDER_RENDER'}
354
355     @classmethod
356     def poll(cls, context):
357         mat = context.material
358         engine = context.scene.render.engine
359         return check_material(mat) and (mat.type in {'SURFACE', 'WIRE'}) and (engine in cls.COMPAT_ENGINES)
360
361     def draw_header(self, context):
362         mat = context.material
363
364         if simple_material(mat):
365             self.layout.prop(mat, "use_transparency", text="")
366
367     def draw(self, context):
368         layout = self.layout
369
370         base_mat = context.material
371         mat = active_node_mat(context.material)
372         rayt = mat.raytrace_transparency
373
374         if simple_material(base_mat):
375             row = layout.row()
376             row.active = mat.use_transparency
377             row.prop(mat, "transparency_method", expand=True)
378
379         split = layout.split()
380         split.active = base_mat.use_transparency
381
382         col = split.column()
383         col.prop(mat, "alpha")
384         row = col.row()
385         row.active = (base_mat.transparency_method != 'MASK') and (not mat.use_shadeless)
386         row.prop(mat, "specular_alpha", text="Specular")
387
388         col = split.column()
389         col.active = (not mat.use_shadeless)
390         col.prop(rayt, "fresnel")
391         sub = col.column()
392         sub.active = rayt.fresnel > 0
393         sub.prop(rayt, "fresnel_factor", text="Blend")
394
395         if base_mat.transparency_method == 'RAYTRACE':
396             layout.separator()
397             split = layout.split()
398             split.active = base_mat.use_transparency
399
400             col = split.column()
401             col.prop(rayt, "ior")
402             col.prop(rayt, "filter")
403             col.prop(rayt, "falloff")
404             col.prop(rayt, "depth_max")
405             col.prop(rayt, "depth")
406
407             col = split.column()
408             col.label(text="Gloss:")
409             col.prop(rayt, "gloss_factor", text="Amount")
410             sub = col.column()
411             sub.active = rayt.gloss_factor < 1.0
412             sub.prop(rayt, "gloss_threshold", text="Threshold")
413             sub.prop(rayt, "gloss_samples", text="Samples")
414
415
416 class MATERIAL_PT_mirror(MaterialButtonsPanel, bpy.types.Panel):
417     bl_label = "Mirror"
418     bl_options = {'DEFAULT_CLOSED'}
419     COMPAT_ENGINES = {'BLENDER_RENDER'}
420
421     @classmethod
422     def poll(cls, context):
423         mat = context.material
424         engine = context.scene.render.engine
425         return check_material(mat) and (mat.type in {'SURFACE', 'WIRE'}) and (engine in cls.COMPAT_ENGINES)
426
427     def draw_header(self, context):
428         raym = active_node_mat(context.material).raytrace_mirror
429
430         self.layout.prop(raym, "use", text="")
431
432     def draw(self, context):
433         layout = self.layout
434
435         mat = active_node_mat(context.material)
436         raym = mat.raytrace_mirror
437
438         layout.active = raym.use
439
440         split = layout.split()
441
442         col = split.column()
443         col.prop(raym, "reflect_factor")
444         col.prop(mat, "mirror_color", text="")
445
446         col = split.column()
447         col.prop(raym, "fresnel")
448         sub = col.column()
449         sub.active = raym.fresnel > 0
450         sub.prop(raym, "fresnel_factor", text="Blend")
451
452         split = layout.split()
453
454         col = split.column()
455         col.separator()
456         col.prop(raym, "depth")
457         col.prop(raym, "distance", text="Max Dist")
458         col.separator()
459         sub = col.split(percentage=0.4)
460         sub.active = raym.distance > 0.0
461         sub.label(text="Fade To:")
462         sub.prop(raym, "fade_to", text="")
463
464         col = split.column()
465         col.label(text="Gloss:")
466         col.prop(raym, "gloss_factor", text="Amount")
467         sub = col.column()
468         sub.active = raym.gloss_factor < 1.0
469         sub.prop(raym, "gloss_threshold", text="Threshold")
470         sub.prop(raym, "gloss_samples", text="Samples")
471         sub.prop(raym, "gloss_anisotropic", text="Anisotropic")
472
473
474 class MATERIAL_PT_sss(MaterialButtonsPanel, bpy.types.Panel):
475     bl_label = "Subsurface Scattering"
476     bl_options = {'DEFAULT_CLOSED'}
477     COMPAT_ENGINES = {'BLENDER_RENDER'}
478
479     @classmethod
480     def poll(cls, context):
481         mat = context.material
482         engine = context.scene.render.engine
483         return check_material(mat) and (mat.type in {'SURFACE', 'WIRE'}) and (engine in cls.COMPAT_ENGINES)
484
485     def draw_header(self, context):
486         mat = active_node_mat(context.material)
487         sss = mat.subsurface_scattering
488
489         self.layout.active = (not mat.use_shadeless)
490         self.layout.prop(sss, "use", text="")
491
492     def draw(self, context):
493         layout = self.layout
494
495         mat = active_node_mat(context.material)
496         sss = mat.subsurface_scattering
497
498         layout.active = (sss.use) and (not mat.use_shadeless)
499
500         row = layout.row().split()
501         sub = row.row(align=True).split(percentage=0.75)
502         sub.menu("MATERIAL_MT_sss_presets", text=bpy.types.MATERIAL_MT_sss_presets.bl_label)
503         sub.operator("material.sss_preset_add", text="", icon="ZOOMIN")
504         sub.operator("material.sss_preset_add", text="", icon="ZOOMOUT").remove_active = True
505
506         split = layout.split()
507
508         col = split.column()
509         col.prop(sss, "ior")
510         col.prop(sss, "scale")
511         col.prop(sss, "color", text="")
512         col.prop(sss, "radius", text="RGB Radius", expand=True)
513
514         col = split.column()
515         sub = col.column(align=True)
516         sub.label(text="Blend:")
517         sub.prop(sss, "color_factor", text="Color")
518         sub.prop(sss, "texture_factor", text="Texture")
519         sub.label(text="Scattering Weight:")
520         sub.prop(sss, "front")
521         sub.prop(sss, "back")
522         col.separator()
523         col.prop(sss, "error_threshold", text="Error")
524
525
526 class MATERIAL_PT_halo(MaterialButtonsPanel, bpy.types.Panel):
527     bl_label = "Halo"
528     COMPAT_ENGINES = {'BLENDER_RENDER'}
529
530     @classmethod
531     def poll(cls, context):
532         mat = context.material
533         engine = context.scene.render.engine
534         return mat and (mat.type == 'HALO') and (engine in cls.COMPAT_ENGINES)
535
536     def draw(self, context):
537         layout = self.layout
538
539         mat = context.material  # dont use node material
540         halo = mat.halo
541
542         def number_but(layout, toggle, number, name, color):
543             row = layout.row(align=True)
544             row.prop(halo, toggle, text="")
545             sub = row.column()
546             sub.active = getattr(halo, toggle)
547             sub.prop(halo, number, text=name)
548             if not color == "":
549                 sub.prop(mat, color, text="")
550
551         split = layout.split()
552
553         col = split.column()
554         col.prop(mat, "alpha")
555         col.prop(mat, "diffuse_color", text="")
556         col.prop(halo, "seed")
557
558         col = split.column()
559         col.prop(halo, "size")
560         col.prop(halo, "hardness")
561         col.prop(halo, "add")
562
563         layout.label(text="Options:")
564
565         split = layout.split()
566         col = split.column()
567         col.prop(halo, "use_texture")
568         col.prop(halo, "use_vertex_normal")
569         col.prop(halo, "use_extreme_alpha")
570         col.prop(halo, "use_shaded")
571         col.prop(halo, "use_soft")
572
573         col = split.column()
574         number_but(col, "use_ring", "ring_count", "Rings", "mirror_color")
575         number_but(col, "use_lines", "line_count", "Lines", "specular_color")
576         number_but(col, "use_star", "star_tip_count", "Star tips", "")
577
578
579 class MATERIAL_PT_flare(MaterialButtonsPanel, bpy.types.Panel):
580     bl_label = "Flare"
581     COMPAT_ENGINES = {'BLENDER_RENDER'}
582
583     @classmethod
584     def poll(cls, context):
585         mat = context.material
586         engine = context.scene.render.engine
587         return mat and (mat.type == 'HALO') and (engine in cls.COMPAT_ENGINES)
588
589     def draw_header(self, context):
590         halo = context.material.halo
591
592         self.layout.prop(halo, "use_flare_mode", text="")
593
594     def draw(self, context):
595         layout = self.layout
596
597         mat = context.material  # dont use node material
598         halo = mat.halo
599
600         layout.active = halo.use_flare_mode
601
602         split = layout.split()
603
604         col = split.column()
605         col.prop(halo, "flare_size", text="Size")
606         col.prop(halo, "flare_boost", text="Boost")
607         col.prop(halo, "flare_seed", text="Seed")
608
609         col = split.column()
610         col.prop(halo, "flare_subflare_count", text="Subflares")
611         col.prop(halo, "flare_subflare_size", text="Subsize")
612
613
614 class MATERIAL_PT_physics(MaterialButtonsPanel, bpy.types.Panel):
615     bl_label = "Physics"
616     COMPAT_ENGINES = {'BLENDER_GAME'}
617
618     @classmethod
619     def poll(cls, context):
620         return context.material and (context.scene.render.engine in cls.COMPAT_ENGINES)
621
622     def draw(self, context):
623         layout = self.layout
624
625         phys = context.material.physics  # dont use node material
626
627         split = layout.split()
628         row = split.row()
629         row.prop(phys, "friction")
630         row.prop(phys, "elasticity", slider=True)
631
632         row = layout.row()
633         row.label(text="Force Field:")
634
635         row = layout.row()
636         row.prop(phys, "fh_force")
637         row.prop(phys, "fh_damping", slider=True)
638
639         row = layout.row()
640         row.prop(phys, "fh_distance")
641         row.prop(phys, "use_fh_normal")
642
643
644 class MATERIAL_PT_strand(MaterialButtonsPanel, bpy.types.Panel):
645     bl_label = "Strand"
646     bl_options = {'DEFAULT_CLOSED'}
647     COMPAT_ENGINES = {'BLENDER_RENDER'}
648
649     @classmethod
650     def poll(cls, context):
651         mat = context.material
652         engine = context.scene.render.engine
653         return mat and (mat.type in {'SURFACE', 'WIRE', 'HALO'}) and (engine in cls.COMPAT_ENGINES)
654
655     def draw(self, context):
656         layout = self.layout
657
658         mat = context.material  # dont use node material
659         tan = mat.strand
660
661         split = layout.split()
662
663         col = split.column()
664         sub = col.column(align=True)
665         sub.label(text="Size:")
666         sub.prop(tan, "root_size", text="Root")
667         sub.prop(tan, "tip_size", text="Tip")
668         sub.prop(tan, "size_min", text="Minimum")
669         sub.prop(tan, "use_blender_units")
670         sub = col.column()
671         sub.active = (not mat.use_shadeless)
672         sub.prop(tan, "use_tangent_shading")
673         col.prop(tan, "shape")
674
675         col = split.column()
676         col.label(text="Shading:")
677         col.prop(tan, "width_fade")
678         ob = context.object
679         if ob and ob.type == 'MESH':
680             col.prop_search(tan, "uv_layer", ob.data, "uv_textures", text="")
681         else:
682             col.prop(tan, "uv_layer", text="")
683         col.separator()
684         sub = col.column()
685         sub.active = (not mat.use_shadeless)
686         sub.label("Surface diffuse:")
687         sub = col.column()
688         sub.prop(tan, "blend_distance", text="Distance")
689
690
691 class MATERIAL_PT_options(MaterialButtonsPanel, bpy.types.Panel):
692     bl_label = "Options"
693     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
694
695     @classmethod
696     def poll(cls, context):
697         mat = context.material
698         engine = context.scene.render.engine
699         return check_material(mat) and (mat.type in {'SURFACE', 'WIRE'}) and (engine in cls.COMPAT_ENGINES)
700
701     def draw(self, context):
702         layout = self.layout
703
704         base_mat = context.material
705         mat = active_node_mat(base_mat)
706
707         split = layout.split()
708
709         col = split.column()
710         if simple_material(base_mat):
711             col.prop(mat, "use_raytrace")
712             col.prop(mat, "use_full_oversampling")
713             col.prop(mat, "use_sky")
714         col.prop(mat, "use_mist")
715         if simple_material(base_mat):
716             col.prop(mat, "invert_z")
717             sub = col.row()
718             sub.prop(mat, "offset_z")
719             sub.active = mat.use_transparency and mat.transparency_method == 'Z_TRANSPARENCY'
720         sub = col.column(align=True)
721         sub.label(text="Light Group:")
722         sub.prop(mat, "light_group", text="")
723         row = sub.row()
724         row.active = bool(mat.light_group)
725         row.prop(mat, "use_light_group_exclusive", text="Exclusive")
726
727         col = split.column()
728         col.prop(mat, "use_face_texture")
729         sub = col.column()
730         sub.active = mat.use_face_texture
731         sub.prop(mat, "use_face_texture_alpha")
732         col.separator()
733         col.prop(mat, "use_vertex_color_paint")
734         col.prop(mat, "use_vertex_color_light")
735         col.prop(mat, "use_object_color")
736         if simple_material(base_mat):
737             col.prop(mat, "pass_index")
738
739
740 class MATERIAL_PT_shadow(MaterialButtonsPanel, bpy.types.Panel):
741     bl_label = "Shadow"
742     bl_options = {'DEFAULT_CLOSED'}
743     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
744
745     @classmethod
746     def poll(cls, context):
747         mat = context.material
748         engine = context.scene.render.engine
749         return check_material(mat) and (mat.type in {'SURFACE', 'WIRE'}) and (engine in cls.COMPAT_ENGINES)
750
751     def draw(self, context):
752         layout = self.layout
753
754         base_mat = context.material
755         mat = active_node_mat(base_mat)
756
757         split = layout.split()
758
759         col = split.column()
760         col.prop(mat, "use_shadows", text="Receive")
761         col.prop(mat, "use_transparent_shadows", text="Receive Transparent")
762         if simple_material(base_mat):
763             col.prop(mat, "use_cast_shadows_only", text="Cast Only")
764             col.prop(mat, "shadow_cast_alpha", text="Casting Alpha")
765         col.prop(mat, "use_only_shadow", text="Shadows Only")
766         sub = col.column()
767         sub.active = mat.use_only_shadow
768         sub.prop(mat, "shadow_only_type", text="")
769
770         col = split.column()
771         if simple_material(base_mat):
772             col.prop(mat, "use_cast_buffer_shadows")
773         sub = col.column()
774         sub.active = mat.use_cast_buffer_shadows
775         sub.prop(mat, "shadow_buffer_bias", text="Buffer Bias")
776         col.prop(mat, "use_ray_shadow_bias", text="Auto Ray Bias")
777         sub = col.column()
778         sub.active = (not mat.use_ray_shadow_bias)
779         sub.prop(mat, "shadow_ray_bias", text="Ray Bias")
780         if simple_material(base_mat):
781             col.prop(mat, "use_cast_approximate")
782
783
784 class MATERIAL_PT_transp_game(MaterialButtonsPanel, bpy.types.Panel):
785     bl_label = "Transparency"
786     bl_options = {'DEFAULT_CLOSED'}
787     COMPAT_ENGINES = {'BLENDER_GAME'}
788
789     @classmethod
790     def poll(cls, context):
791         mat = context.material
792         engine = context.scene.render.engine
793         return check_material(mat) and (engine in cls.COMPAT_ENGINES)
794
795     def draw_header(self, context):
796         mat = context.material
797
798         if simple_material(mat):
799             self.layout.prop(mat, "use_transparency", text="")
800
801     def draw(self, context):
802         layout = self.layout
803         base_mat = context.material
804         mat = active_node_mat(base_mat)
805
806         if simple_material(base_mat):
807             row = layout.row()
808             row.active = mat.use_transparency
809             row.prop(mat, "transparency_method", expand=True)
810
811         layout.prop(mat, "alpha")
812
813
814 class VolumeButtonsPanel():
815     bl_space_type = 'PROPERTIES'
816     bl_region_type = 'WINDOW'
817     bl_context = "material"
818     COMPAT_ENGINES = {'BLENDER_RENDER'}
819
820     @classmethod
821     def poll(cls, context):
822         mat = context.material
823         engine = context.scene.render.engine
824         return mat and (mat.type == 'VOLUME') and (engine in cls.COMPAT_ENGINES)
825
826
827 class MATERIAL_PT_volume_density(VolumeButtonsPanel, bpy.types.Panel):
828     bl_label = "Density"
829     COMPAT_ENGINES = {'BLENDER_RENDER'}
830
831     def draw(self, context):
832         layout = self.layout
833
834         vol = context.material.volume  # dont use node material
835
836         row = layout.row()
837         row.prop(vol, "density")
838         row.prop(vol, "density_scale")
839
840
841 class MATERIAL_PT_volume_shading(VolumeButtonsPanel, bpy.types.Panel):
842     bl_label = "Shading"
843     COMPAT_ENGINES = {'BLENDER_RENDER'}
844
845     def draw(self, context):
846         layout = self.layout
847
848         vol = context.material.volume  # dont use node material
849
850         split = layout.split()
851
852         col = split.column()
853         col.prop(vol, "scattering")
854         col.prop(vol, "asymmetry")
855         col.prop(vol, "transmission_color")
856
857         col = split.column()
858         sub = col.column(align=True)
859         sub.prop(vol, "emission")
860         sub.prop(vol, "emission_color", text="")
861         sub = col.column(align=True)
862         sub.prop(vol, "reflection")
863         sub.prop(vol, "reflection_color", text="")
864
865
866 class MATERIAL_PT_volume_lighting(VolumeButtonsPanel, bpy.types.Panel):
867     bl_label = "Lighting"
868     COMPAT_ENGINES = {'BLENDER_RENDER'}
869
870     def draw(self, context):
871         layout = self.layout
872
873         vol = context.material.volume  # dont use node material
874
875         split = layout.split()
876
877         col = split.column()
878         col.prop(vol, "light_method", text="")
879
880         col = split.column()
881
882         if vol.light_method == 'SHADED':
883             col.prop(vol, "use_external_shadows")
884             col.prop(vol, "use_light_cache")
885             sub = col.column()
886             sub.active = vol.use_light_cache
887             sub.prop(vol, "cache_resolution")
888         elif vol.light_method in {'MULTIPLE_SCATTERING', 'SHADED_PLUS_MULTIPLE_SCATTERING'}:
889             sub = col.column()
890             sub.enabled = True
891             sub.active = False
892             sub.label("Light Cache Enabled")
893             col.prop(vol, "cache_resolution")
894
895             sub = col.column(align=True)
896             sub.prop(vol, "ms_diffusion")
897             sub.prop(vol, "ms_spread")
898             sub.prop(vol, "ms_intensity")
899
900
901 class MATERIAL_PT_volume_transp(VolumeButtonsPanel, bpy.types.Panel):
902     bl_label = "Transparency"
903     COMPAT_ENGINES = {'BLENDER_RENDER'}
904
905     @classmethod
906     def poll(cls, context):
907         mat = context.material
908         engine = context.scene.render.engine
909         return mat and simple_material(mat) and (mat.type == 'VOLUME') and (engine in cls.COMPAT_ENGINES)
910
911     def draw(self, context):
912         layout = self.layout
913
914         mat = context.material  # dont use node material
915
916         layout.prop(mat, "transparency_method", expand=True)
917
918
919 class MATERIAL_PT_volume_integration(VolumeButtonsPanel, bpy.types.Panel):
920     bl_label = "Integration"
921     COMPAT_ENGINES = {'BLENDER_RENDER'}
922
923     def draw(self, context):
924         layout = self.layout
925
926         vol = context.material.volume  # dont use node material
927
928         split = layout.split()
929
930         col = split.column()
931         col.label(text="Step Calculation:")
932         col.prop(vol, "step_method", text="")
933         col = col.column(align=True)
934         col.prop(vol, "step_size")
935
936         col = split.column()
937         col.label()
938         col.prop(vol, "depth_threshold")
939
940
941 class MATERIAL_PT_volume_options(VolumeButtonsPanel, bpy.types.Panel):
942     bl_label = "Options"
943     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
944     bl_options = {'DEFAULT_CLOSED'}
945
946     @classmethod
947     def poll(cls, context):
948         mat = context.material
949         engine = context.scene.render.engine
950         return check_material(mat) and (mat.type == 'VOLUME') and (engine in cls.COMPAT_ENGINES)
951
952     def draw(self, context):
953         layout = self.layout
954
955         mat = active_node_mat(context.material)
956
957         split = layout.split()
958
959         col = split.column()
960         if simple_material(context.material):
961             col.prop(mat, "use_raytrace")
962             col.prop(mat, "use_full_oversampling")
963         col.prop(mat, "use_mist")
964
965         col = split.column()
966         col.label(text="Light Group:")
967         col.prop(mat, "light_group", text="")
968         row = col.row()
969         row.active = bool(mat.light_group)
970         row.prop(mat, "use_light_group_exclusive", text="Exclusive")
971
972
973 class MATERIAL_PT_custom_props(MaterialButtonsPanel, PropertyPanel, bpy.types.Panel):
974     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
975     _context_path = "material"
976     _property_type = bpy.types.Material
977
978 if __name__ == "__main__":  # only for live edit.
979     bpy.utils.register_module(__name__)