change python scripts so modules which register with blender have a register() functi...
[blender.git] / release / scripts / ui / properties_material.py
1 # ##### BEGIN GPL LICENSE BLOCK #####
2 #
3 #  This program is free software; you can redistribute it and/or
4 #  modify it under the terms of the GNU General Public License
5 #  as published by the Free Software Foundation; either version 2
6 #  of the License, or (at your option) any later version.
7 #
8 #  This program is distributed in the hope that it will be useful,
9 #  but WITHOUT ANY WARRANTY; without even the implied warranty of
10 #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 #  GNU General Public License for more details.
12 #
13 #  You should have received a copy of the GNU General Public License
14 #  along with this program; if not, write to the Free Software Foundation,
15 #  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 #
17 # ##### END GPL LICENSE BLOCK #####
18
19 # <pep8 compliant>
20 import bpy
21 from rna_prop_ui import PropertyPanel
22
23 narrowui = 180
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:
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 class MATERIAL_MT_sss_presets(bpy.types.Menu):
40     bl_label = "SSS Presets"
41     preset_subdir = "sss"
42     preset_operator = "script.python_file_run"
43     draw = bpy.types.Menu.draw_preset
44
45
46 class MATERIAL_MT_specials(bpy.types.Menu):
47     bl_label = "Material Specials"
48
49     def draw(self, context):
50         layout = self.layout
51
52         layout.operator("object.material_slot_copy", icon='COPY_ID')
53         layout.operator("material.copy", icon='COPYDOWN')
54         layout.operator("material.paste", icon='PASTEDOWN')
55
56
57 class MaterialButtonsPanel(bpy.types.Panel):
58     bl_space_type = 'PROPERTIES'
59     bl_region_type = 'WINDOW'
60     bl_context = "material"
61     # COMPAT_ENGINES must be defined in each subclass, external engines can add themselves here
62
63     def poll(self, context):
64         mat = context.material
65         engine = context.scene.render_data.engine
66         return mat and (engine in self.COMPAT_ENGINES)
67
68
69 class MATERIAL_PT_preview(MaterialButtonsPanel):
70     bl_label = "Preview"
71     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
72
73     def draw(self, context):
74         self.layout.template_preview(context.material)
75
76
77 class MATERIAL_PT_context_material(MaterialButtonsPanel):
78     bl_label = ""
79     bl_show_header = False
80     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
81
82     def poll(self, context):
83         # An exception, dont call the parent poll func because
84         # this manages materials for all engine types
85
86         engine = context.scene.render_data.engine
87         return (context.material or context.object) and (engine in self.COMPAT_ENGINES)
88
89     def draw(self, context):
90         layout = self.layout
91
92         mat = context.material
93         ob = context.object
94         slot = context.material_slot
95         space = context.space_data
96         wide_ui = context.region.width > narrowui
97
98         if ob:
99             row = layout.row()
100
101             row.template_list(ob, "material_slots", ob, "active_material_index", rows=2)
102
103             col = row.column(align=True)
104             col.operator("object.material_slot_add", icon='ZOOMIN', text="")
105             col.operator("object.material_slot_remove", icon='ZOOMOUT', text="")
106
107             col.menu("MATERIAL_MT_specials", icon='DOWNARROW_HLT', text="")
108
109             if ob.mode == 'EDIT':
110                 row = layout.row(align=True)
111                 row.operator("object.material_slot_assign", text="Assign")
112                 row.operator("object.material_slot_select", text="Select")
113                 row.operator("object.material_slot_deselect", text="Deselect")
114
115         if wide_ui:
116             split = layout.split(percentage=0.65)
117
118             if ob:
119                 split.template_ID(ob, "active_material", new="material.new")
120                 row = split.row()
121                 if slot:
122                     row.prop(slot, "link", text="")
123                 else:
124                     row.label()
125             elif mat:
126                 split.template_ID(space, "pin_id")
127                 split.separator()
128         else:
129             if ob:
130                 layout.template_ID(ob, "active_material", new="material.new")
131             elif mat:
132                 layout.template_ID(space, "pin_id")
133
134         if mat:
135             if wide_ui:
136                 layout.prop(mat, "type", expand=True)
137             else:
138                 layout.prop(mat, "type", text="")
139
140
141 class MATERIAL_PT_custom_props(MaterialButtonsPanel, PropertyPanel):
142     COMPAT_ENGINES = {'BLENDER_RENDER'}
143     _context_path = "material"
144
145
146 class MATERIAL_PT_shading(MaterialButtonsPanel):
147     bl_label = "Shading"
148     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
149
150     def poll(self, context):
151         mat = active_node_mat(context.material)
152         engine = context.scene.render_data.engine
153         return mat and (mat.type in ('SURFACE', 'WIRE', 'HALO')) and (engine in self.COMPAT_ENGINES)
154
155     def draw(self, context):
156         layout = self.layout
157
158         mat = active_node_mat(context.material)
159         wide_ui = context.region.width > narrowui
160
161         if mat.type in ('SURFACE', 'WIRE'):
162             split = layout.split()
163
164             col = split.column()
165             sub = col.column()
166             sub.active = not mat.shadeless
167             sub.prop(mat, "emit")
168             sub.prop(mat, "ambient")
169             sub = col.column()
170             sub.prop(mat, "translucency")
171
172             if wide_ui:
173                 col = split.column()
174             col.prop(mat, "shadeless")
175             sub = col.column()
176             sub.active = not mat.shadeless
177             sub.prop(mat, "tangent_shading")
178             sub.prop(mat, "cubic")
179
180         elif mat.type == 'HALO':
181             layout.prop(mat, "alpha")
182
183
184 class MATERIAL_PT_strand(MaterialButtonsPanel):
185     bl_label = "Strand"
186     bl_default_closed = True
187     COMPAT_ENGINES = {'BLENDER_RENDER'}
188
189     def poll(self, context):
190         mat = context.material
191         engine = context.scene.render_data.engine
192         return mat and (mat.type in ('SURFACE', 'WIRE', 'HALO')) and (engine in self.COMPAT_ENGINES)
193
194     def draw(self, context):
195         layout = self.layout
196
197         mat = context.material # dont use node material
198         tan = mat.strand
199         wide_ui = context.region.width > narrowui
200
201         split = layout.split()
202
203         col = split.column()
204         sub = col.column(align=True)
205         sub.label(text="Size:")
206         sub.prop(tan, "root_size", text="Root")
207         sub.prop(tan, "tip_size", text="Tip")
208         sub.prop(tan, "min_size", text="Minimum")
209         sub.prop(tan, "blender_units")
210         sub = col.column()
211         sub.active = (not mat.shadeless)
212         sub.prop(tan, "tangent_shading")
213         col.prop(tan, "shape")
214
215         if wide_ui:
216             col = split.column()
217         col.label(text="Shading:")
218         col.prop(tan, "width_fade")
219         ob = context.object
220         if ob and ob.type == 'MESH':
221             col.prop_object(tan, "uv_layer", ob.data, "uv_textures", text="")
222         else:
223             col.prop(tan, "uv_layer", text="")
224         col.separator()
225         sub = col.column()
226         sub.active = (not mat.shadeless)
227         sub.prop(tan, "surface_diffuse")
228         sub = col.column()
229         sub.active = tan.surface_diffuse
230         sub.prop(tan, "blend_distance", text="Distance")
231
232
233 class MATERIAL_PT_physics(MaterialButtonsPanel):
234     bl_label = "Physics"
235     COMPAT_ENGINES = {'BLENDER_GAME'}
236
237     def draw(self, context):
238         layout = self.layout
239
240         phys = context.material.physics # dont use node material
241         wide_ui = context.region.width > narrowui
242
243         split = layout.split()
244
245         col = split.column()
246         col.prop(phys, "distance")
247         col.prop(phys, "friction")
248         col.prop(phys, "align_to_normal")
249
250         if wide_ui:
251             col = split.column()
252         col.prop(phys, "force", slider=True)
253         col.prop(phys, "elasticity", slider=True)
254         col.prop(phys, "damp", slider=True)
255
256
257 class MATERIAL_PT_options(MaterialButtonsPanel):
258     bl_label = "Options"
259     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
260
261     def poll(self, context):
262         mat = active_node_mat(context.material)
263         engine = context.scene.render_data.engine
264         return mat and (mat.type in ('SURFACE', 'WIRE', 'HALO')) and (engine in self.COMPAT_ENGINES)
265
266     def draw(self, context):
267         layout = self.layout
268
269         mat = active_node_mat(context.material)
270         wide_ui = context.region.width > narrowui
271
272         split = layout.split()
273
274         col = split.column()
275         col.prop(mat, "traceable")
276         col.prop(mat, "full_oversampling")
277         col.prop(mat, "use_sky")
278         col.prop(mat, "exclude_mist")
279         col.prop(mat, "invert_z")
280         sub = col.row()
281         sub.prop(mat, "z_offset")
282         sub.active = mat.transparency and mat.transparency_method == 'Z_TRANSPARENCY'
283         sub = col.column(align=True)
284         sub.label(text="Light Group:")
285         sub.prop(mat, "light_group", text="")
286         row = sub.row()
287         row.active = bool(mat.light_group)
288         row.prop(mat, "light_group_exclusive", text="Exclusive")
289
290         if wide_ui:
291             col = split.column()
292         col.prop(mat, "face_texture")
293         sub = col.column()
294         sub.active = mat.face_texture
295         sub.prop(mat, "face_texture_alpha")
296         col.separator()
297         col.prop(mat, "vertex_color_paint")
298         col.prop(mat, "vertex_color_light")
299         col.prop(mat, "object_color")
300
301
302 class MATERIAL_PT_shadow(MaterialButtonsPanel):
303     bl_label = "Shadow"
304     bl_default_closed = True
305     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
306
307     def poll(self, context):
308         mat = active_node_mat(context.material)
309         engine = context.scene.render_data.engine
310         return mat and (mat.type in ('SURFACE', 'WIRE')) and (engine in self.COMPAT_ENGINES)
311
312     def draw(self, context):
313         layout = self.layout
314
315         mat = active_node_mat(context.material)
316         wide_ui = context.region.width > narrowui
317
318         split = layout.split()
319
320         col = split.column()
321         col.prop(mat, "shadows", text="Receive")
322         col.prop(mat, "receive_transparent_shadows", text="Receive Transparent")
323         col.prop(mat, "only_shadow", text="Shadows Only")
324         col.prop(mat, "cast_shadows_only", text="Cast Only")
325         col.prop(mat, "shadow_casting_alpha", text="Casting Alpha")
326
327         if wide_ui:
328             col = split.column()
329         col.prop(mat, "cast_buffer_shadows")
330         sub = col.column()
331         sub.active = mat.cast_buffer_shadows
332         sub.prop(mat, "shadow_buffer_bias", text="Buffer Bias")
333         col.prop(mat, "ray_shadow_bias", text="Auto Ray Bias")
334         sub = col.column()
335         sub.active = (not mat.ray_shadow_bias)
336         sub.prop(mat, "shadow_ray_bias", text="Ray Bias")
337         col.prop(mat, "cast_approximate")
338
339 class MATERIAL_PT_diffuse(MaterialButtonsPanel):
340     bl_label = "Diffuse"
341     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
342
343     def poll(self, context):
344         mat = active_node_mat(context.material)
345         engine = context.scene.render_data.engine
346         return mat and (mat.type in ('SURFACE', 'WIRE')) and (engine in self.COMPAT_ENGINES)
347
348     def draw(self, context):
349         layout = self.layout
350
351         mat = active_node_mat(context.material)
352         wide_ui = context.region.width > narrowui
353
354         split = layout.split()
355
356         col = split.column()
357         col.prop(mat, "diffuse_color", text="")
358         sub = col.column()
359         sub.active = (not mat.shadeless)
360         sub.prop(mat, "diffuse_intensity", text="Intensity")
361
362         if wide_ui:
363             col = split.column()
364         col.active = (not mat.shadeless)
365         col.prop(mat, "diffuse_shader", text="")
366         col.prop(mat, "use_diffuse_ramp", text="Ramp")
367
368         col = layout.column()
369         col.active = (not mat.shadeless)
370         if mat.diffuse_shader == 'OREN_NAYAR':
371             col.prop(mat, "roughness")
372         elif mat.diffuse_shader == 'MINNAERT':
373             col.prop(mat, "darkness")
374         elif mat.diffuse_shader == 'TOON':
375             split = col.split()
376
377             col = split.column()
378             col.prop(mat, "diffuse_toon_size", text="Size")
379
380             if wide_ui:
381                 col = split.column()
382             col.prop(mat, "diffuse_toon_smooth", text="Smooth")
383         elif mat.diffuse_shader == 'FRESNEL':
384             split = col.split()
385
386             col = split.column()
387             col.prop(mat, "diffuse_fresnel", text="Fresnel")
388
389             if wide_ui:
390                 col = split.column()
391             col.prop(mat, "diffuse_fresnel_factor", text="Factor")
392
393         if mat.use_diffuse_ramp:
394             layout.separator()
395             layout.template_color_ramp(mat, "diffuse_ramp", expand=True)
396             layout.separator()
397
398             split = layout.split()
399
400             col = split.column()
401             col.prop(mat, "diffuse_ramp_input", text="Input")
402
403             if wide_ui:
404                 col = split.column()
405             col.prop(mat, "diffuse_ramp_blend", text="Blend")
406             row = layout.row()
407             row.prop(mat, "diffuse_ramp_factor", text="Factor")
408
409
410 class MATERIAL_PT_specular(MaterialButtonsPanel):
411     bl_label = "Specular"
412     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
413
414     def poll(self, context):
415         mat = active_node_mat(context.material)
416         engine = context.scene.render_data.engine
417         return mat and (mat.type in ('SURFACE', 'WIRE')) and (engine in self.COMPAT_ENGINES)
418
419     def draw(self, context):
420         layout = self.layout
421
422         mat = active_node_mat(context.material)
423         wide_ui = context.region.width > narrowui
424
425         layout.active = (not mat.shadeless)
426
427         split = layout.split()
428
429         col = split.column()
430         col.prop(mat, "specular_color", text="")
431         col.prop(mat, "specular_intensity", text="Intensity")
432
433         if wide_ui:
434             col = split.column()
435         col.prop(mat, "specular_shader", text="")
436         col.prop(mat, "use_specular_ramp", text="Ramp")
437
438         col = layout.column()
439         if mat.specular_shader in ('COOKTORR', 'PHONG'):
440             col.prop(mat, "specular_hardness", text="Hardness")
441         elif mat.specular_shader == 'BLINN':
442             split = layout.split()
443
444             col = split.column()
445             col.prop(mat, "specular_hardness", text="Hardness")
446
447             if wide_ui:
448                 col = split.column()
449             col.prop(mat, "specular_ior", text="IOR")
450         elif mat.specular_shader == 'WARDISO':
451             col.prop(mat, "specular_slope", text="Slope")
452         elif mat.specular_shader == 'TOON':
453             split = layout.split()
454
455             col = split.column()
456             col.prop(mat, "specular_toon_size", text="Size")
457
458             if wide_ui:
459                 col = split.column()
460             col.prop(mat, "specular_toon_smooth", text="Smooth")
461
462         if mat.use_specular_ramp:
463             layout.separator()
464             layout.template_color_ramp(mat, "specular_ramp", expand=True)
465             layout.separator()
466             split = layout.split()
467
468             col = split.column()
469             col.prop(mat, "specular_ramp_input", text="Input")
470
471             if wide_ui:
472                 col = split.column()
473             col.prop(mat, "specular_ramp_blend", text="Blend")
474
475             row = layout.row()
476             row.prop(mat, "specular_ramp_factor", text="Factor")
477
478
479 class MATERIAL_PT_sss(MaterialButtonsPanel):
480     bl_label = "Subsurface Scattering"
481     bl_default_closed = True
482     COMPAT_ENGINES = {'BLENDER_RENDER'}
483
484     def poll(self, context):
485         mat = active_node_mat(context.material)
486         engine = context.scene.render_data.engine
487         return mat and (mat.type in ('SURFACE', 'WIRE')) and (engine in self.COMPAT_ENGINES)
488
489     def draw_header(self, context):
490         mat = active_node_mat(context.material)
491         sss = mat.subsurface_scattering
492
493         self.layout.active = (not mat.shadeless)
494         self.layout.prop(sss, "enabled", text="")
495
496     def draw(self, context):
497         layout = self.layout
498
499         mat = active_node_mat(context.material)
500         sss = mat.subsurface_scattering
501         wide_ui = context.region.width > narrowui
502
503         layout.active = (sss.enabled) and (not mat.shadeless)
504
505         row = layout.row().split()
506         sub = row.row(align=True).split(percentage=0.75)
507         sub.menu("MATERIAL_MT_sss_presets", text="Presets")
508         sub.operator("material.sss_preset_add", text="Add")
509
510         split = layout.split()
511
512         col = split.column()
513         col.prop(sss, "ior")
514         col.prop(sss, "scale")
515         col.prop(sss, "color", text="")
516         col.prop(sss, "radius", text="RGB Radius", expand=True)
517
518         if wide_ui:
519             col = split.column()
520         sub = col.column(align=True)
521         sub.label(text="Blend:")
522         sub.prop(sss, "color_factor", text="Color")
523         sub.prop(sss, "texture_factor", text="Texture")
524         sub.label(text="Scattering Weight:")
525         sub.prop(sss, "front")
526         sub.prop(sss, "back")
527         col.separator()
528         col.prop(sss, "error_tolerance", text="Error")
529
530
531 class MATERIAL_PT_mirror(MaterialButtonsPanel):
532     bl_label = "Mirror"
533     bl_default_closed = True
534     COMPAT_ENGINES = {'BLENDER_RENDER'}
535
536     def poll(self, context):
537         mat = active_node_mat(context.material)
538         engine = context.scene.render_data.engine
539         return mat and (mat.type in ('SURFACE', 'WIRE')) and (engine in self.COMPAT_ENGINES)
540
541     def draw_header(self, context):
542         raym = active_node_mat(context.material).raytrace_mirror
543
544         self.layout.prop(raym, "enabled", text="")
545
546     def draw(self, context):
547         layout = self.layout
548
549         mat = active_node_mat(context.material)
550         raym = mat.raytrace_mirror
551         wide_ui = context.region.width > narrowui
552
553         layout.active = raym.enabled
554
555         split = layout.split()
556
557         col = split.column()
558         col.prop(raym, "reflect_factor")
559         col.prop(mat, "mirror_color", text="")
560
561         if wide_ui:
562             col = split.column()
563         col.prop(raym, "fresnel")
564         sub = col.column()
565         sub.active = raym.fresnel > 0
566         sub.prop(raym, "fresnel_factor", text="Blend")
567
568         split = layout.split()
569
570         col = split.column()
571         col.separator()
572         col.prop(raym, "distance", text="Max Dist")
573         col.prop(raym, "depth")
574         col.separator()
575         sub = col.split(percentage=0.4)
576         sub.label(text="Fade To:")
577         sub.prop(raym, "fade_to", text="")
578
579         if wide_ui:
580             col = split.column()
581         col.label(text="Gloss:")
582         col.prop(raym, "gloss_factor", text="Amount")
583         sub = col.column()
584         sub.active = raym.gloss_factor < 1.0
585         sub.prop(raym, "gloss_threshold", text="Threshold")
586         sub.prop(raym, "gloss_samples", text="Samples")
587         sub.prop(raym, "gloss_anisotropic", text="Anisotropic")
588
589
590 class MATERIAL_PT_transp(MaterialButtonsPanel):
591     bl_label = "Transparency"
592     bl_default_closed = True
593     COMPAT_ENGINES = {'BLENDER_RENDER'}
594
595     def poll(self, context):
596         mat = active_node_mat(context.material)
597         engine = context.scene.render_data.engine
598         return mat and (mat.type in ('SURFACE', 'WIRE')) and (engine in self.COMPAT_ENGINES)
599
600     def draw_header(self, context):
601         mat = active_node_mat(context.material)
602
603         self.layout.prop(mat, "transparency", text="")
604
605     def draw(self, context):
606         layout = self.layout
607
608         mat = active_node_mat(context.material)
609         rayt = mat.raytrace_transparency
610         wide_ui = context.region.width > narrowui
611
612         row = layout.row()
613         row.active = mat.transparency and (not mat.shadeless)
614         if wide_ui:
615             row.prop(mat, "transparency_method", expand=True)
616         else:
617             row.prop(mat, "transparency_method", text="")
618
619         split = layout.split()
620
621         col = split.column()
622         col.prop(mat, "alpha")
623         row = col.row()
624         row.active = mat.transparency and (not mat.shadeless)
625         row.prop(mat, "specular_alpha", text="Specular")
626
627         if wide_ui:
628             col = split.column()
629         col.active = (not mat.shadeless)
630         col.prop(rayt, "fresnel")
631         sub = col.column()
632         sub.active = rayt.fresnel > 0
633         sub.prop(rayt, "fresnel_factor", text="Blend")
634
635         if mat.transparency_method == 'RAYTRACE':
636             layout.separator()
637             split = layout.split()
638             split.active = mat.transparency
639
640             col = split.column()
641             col.prop(rayt, "ior")
642             col.prop(rayt, "filter")
643             col.prop(rayt, "falloff")
644             col.prop(rayt, "limit")
645             col.prop(rayt, "depth")
646
647             if wide_ui:
648                 col = split.column()
649             col.label(text="Gloss:")
650             col.prop(rayt, "gloss_factor", text="Amount")
651             sub = col.column()
652             sub.active = rayt.gloss_factor < 1.0
653             sub.prop(rayt, "gloss_threshold", text="Threshold")
654             sub.prop(rayt, "gloss_samples", text="Samples")
655
656
657 class MATERIAL_PT_transp_game(MaterialButtonsPanel):
658     bl_label = "Transparency"
659     bl_default_closed = True
660     COMPAT_ENGINES = {'BLENDER_GAME'}
661
662     def poll(self, context):
663         mat = active_node_mat(context.material)
664         engine = context.scene.render_data.engine
665         return mat  and (engine in self.COMPAT_ENGINES)
666
667     def draw_header(self, context):
668         mat = active_node_mat(context.material)
669
670         self.layout.prop(mat, "transparency", text="")
671
672     def draw(self, context):
673         layout = self.layout
674
675         mat = active_node_mat(context.material)
676         rayt = mat.raytrace_transparency
677         wide_ui = context.region.width > narrowui
678
679         row = layout.row()
680         row.active = mat.transparency and (not mat.shadeless)
681         if wide_ui:
682             row.prop(mat, "transparency_method", expand=True)
683         else:
684             row.prop(mat, "transparency_method", text="")
685
686         split = layout.split()
687
688         col = split.column()
689         col.prop(mat, "alpha")
690
691
692 class MATERIAL_PT_halo(MaterialButtonsPanel):
693     bl_label = "Halo"
694     COMPAT_ENGINES = {'BLENDER_RENDER'}
695
696     def poll(self, context):
697         mat = context.material
698         engine = context.scene.render_data.engine
699         return mat and (mat.type == 'HALO') and (engine in self.COMPAT_ENGINES)
700
701     def draw(self, context):
702         layout = self.layout
703
704         mat = context.material # dont use node material
705         halo = mat.halo
706         wide_ui = context.region.width > narrowui
707
708         split = layout.split()
709
710         col = split.column()
711         col.prop(mat, "diffuse_color", text="")
712         col.prop(halo, "size")
713         col.prop(halo, "hardness")
714         col.prop(halo, "add")
715         col.label(text="Options:")
716         col.prop(halo, "texture")
717         col.prop(halo, "vertex_normal")
718         col.prop(halo, "xalpha")
719         col.prop(halo, "shaded")
720         col.prop(halo, "soft")
721
722         if wide_ui:
723             col = split.column()
724         col.prop(halo, "ring")
725         sub = col.column()
726         sub.active = halo.ring
727         sub.prop(halo, "rings")
728         sub.prop(mat, "mirror_color", text="")
729         col.separator()
730         col.prop(halo, "lines")
731         sub = col.column()
732         sub.active = halo.lines
733         sub.prop(halo, "line_number", text="Lines")
734         sub.prop(mat, "specular_color", text="")
735         col.separator()
736         col.prop(halo, "star")
737         sub = col.column()
738         sub.active = halo.star
739         sub.prop(halo, "star_tips")
740
741
742 class MATERIAL_PT_flare(MaterialButtonsPanel):
743     bl_label = "Flare"
744     COMPAT_ENGINES = {'BLENDER_RENDER'}
745
746     def poll(self, context):
747         mat = context.material
748         engine = context.scene.render_data.engine
749         return mat and (mat.type == 'HALO') and (engine in self.COMPAT_ENGINES)
750
751     def draw_header(self, context):
752         halo = context.material.halo
753
754         self.layout.prop(halo, "flare_mode", text="")
755
756     def draw(self, context):
757         layout = self.layout
758
759         mat = context.material # dont use node material
760         halo = mat.halo
761         wide_ui = context.region.width > narrowui
762
763         layout.active = halo.flare_mode
764
765         split = layout.split()
766
767         col = split.column()
768         col.prop(halo, "flare_size", text="Size")
769         col.prop(halo, "flare_boost", text="Boost")
770         col.prop(halo, "flare_seed", text="Seed")
771         if wide_ui:
772             col = split.column()
773         col.prop(halo, "flares_sub", text="Subflares")
774         col.prop(halo, "flare_subsize", text="Subsize")
775
776
777 class VolumeButtonsPanel(bpy.types.Panel):
778     bl_space_type = 'PROPERTIES'
779     bl_region_type = 'WINDOW'
780     bl_context = "material"
781
782     def poll(self, context):
783         mat = context.material
784         engine = context.scene.render_data.engine
785         return mat and (mat.type == 'VOLUME') and (engine in self.COMPAT_ENGINES)
786
787
788 class MATERIAL_PT_volume_density(VolumeButtonsPanel):
789     bl_label = "Density"
790     bl_default_closed = False
791     COMPAT_ENGINES = {'BLENDER_RENDER'}
792
793     def draw(self, context):
794         layout = self.layout
795
796         vol = context.material.volume # dont use node material
797         wide_ui = context.region.width > narrowui
798
799         split = layout.split()
800         col = split.column()
801         col.prop(vol, "density")
802
803         if wide_ui:
804             col = split.column()
805         col.prop(vol, "density_scale")
806
807
808 class MATERIAL_PT_volume_shading(VolumeButtonsPanel):
809     bl_label = "Shading"
810     bl_default_closed = False
811     COMPAT_ENGINES = {'BLENDER_RENDER'}
812
813     def draw(self, context):
814         layout = self.layout
815
816         vol = context.material.volume # dont use node material
817         wide_ui = context.region.width > narrowui
818
819         split = layout.split()
820
821         col = split.column()
822         col.prop(vol, "scattering")
823         col.prop(vol, "asymmetry")
824         col.prop(vol, "transmission_color")
825
826         if wide_ui:
827             col = split.column()
828         sub = col.column(align=True)
829         sub.prop(vol, "emission")
830         sub.prop(vol, "emission_color", text="")
831         sub = col.column(align=True)
832         sub.prop(vol, "reflection")
833         sub.prop(vol, "reflection_color", text="")
834
835
836 class MATERIAL_PT_volume_lighting(VolumeButtonsPanel):
837     bl_label = "Lighting"
838     bl_default_closed = False
839     COMPAT_ENGINES = {'BLENDER_RENDER'}
840
841     def draw(self, context):
842         layout = self.layout
843
844         vol = context.material.volume # dont use node material
845         wide_ui = context.region.width > narrowui
846
847         split = layout.split()
848
849         col = split.column()
850         col.prop(vol, "lighting_mode", text="")
851
852         if wide_ui:
853             col = split.column()
854
855         if vol.lighting_mode == 'SHADED':
856             col.prop(vol, "external_shadows")
857             col.prop(vol, "light_cache")
858             sub = col.column()
859             sub.active = vol.light_cache
860             sub.prop(vol, "cache_resolution")
861         elif vol.lighting_mode in ('MULTIPLE_SCATTERING', 'SHADED_PLUS_MULTIPLE_SCATTERING'):
862             sub = col.column()
863             sub.enabled = True
864             sub.active = False
865             sub.prop(vol, "light_cache")
866             col.prop(vol, "cache_resolution")
867
868             sub = col.column(align=True)
869             sub.prop(vol, "ms_diffusion")
870             sub.prop(vol, "ms_spread")
871             sub.prop(vol, "ms_intensity")
872
873
874 class MATERIAL_PT_volume_transp(VolumeButtonsPanel):
875     bl_label = "Transparency"
876     COMPAT_ENGINES = {'BLENDER_RENDER'}
877
878     def draw(self, context):
879         layout = self.layout
880
881         mat = context.material # dont use node material
882         wide_ui = context.region.width > narrowui
883
884         if wide_ui:
885             layout.prop(mat, "transparency_method", expand=True)
886         else:
887             layout.prop(mat, "transparency_method", text="")
888
889
890 class MATERIAL_PT_volume_integration(VolumeButtonsPanel):
891     bl_label = "Integration"
892     bl_default_closed = False
893     COMPAT_ENGINES = {'BLENDER_RENDER'}
894
895     def draw(self, context):
896         layout = self.layout
897
898         vol = context.material.volume # dont use node material
899         wide_ui = context.region.width > narrowui
900
901         split = layout.split()
902
903         col = split.column()
904         col.label(text="Step Calculation:")
905         col.prop(vol, "step_calculation", text="")
906         col = col.column(align=True)
907         col.prop(vol, "step_size")
908
909         if wide_ui:
910             col = split.column()
911         col.label()
912         col.prop(vol, "depth_cutoff")
913
914
915 classes = [
916     MATERIAL_PT_context_material,
917     MATERIAL_PT_preview,
918     MATERIAL_PT_diffuse,
919     MATERIAL_PT_specular,
920     MATERIAL_PT_shading,
921     MATERIAL_PT_transp,
922     MATERIAL_PT_mirror,
923     MATERIAL_PT_sss,
924     MATERIAL_PT_halo,
925     MATERIAL_PT_flare,
926     MATERIAL_PT_physics,
927     MATERIAL_PT_strand,
928     MATERIAL_PT_options,
929     MATERIAL_PT_shadow,
930     MATERIAL_PT_transp_game,
931
932     MATERIAL_MT_sss_presets,
933     MATERIAL_MT_specials,
934
935     MATERIAL_PT_volume_density,
936     MATERIAL_PT_volume_shading,
937     MATERIAL_PT_volume_lighting,
938     MATERIAL_PT_volume_transp,
939
940     MATERIAL_PT_volume_integration,
941
942     MATERIAL_PT_custom_props]
943
944
945 def register():
946     register = bpy.types.register
947     for cls in classes:
948         register(cls)
949
950 def unregister():
951     unregister = bpy.types.unregister
952     for cls in classes:
953         unregister(cls)