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