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