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