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