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