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