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