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