diff --git a/texture_paint_layer_manager.py b/texture_paint_layer_manager.py
new file mode 100644
index 0000000000000000000000000000000000000000..b3f2d088e39a19177bb355009b4c709dcbb45460
--- /dev/null
+++ b/texture_paint_layer_manager.py
@@ -0,0 +1,645 @@
+bl_info = {
+    "name": "Texture Paint Layer Manager",
+    "author": "Michael Wiliamson",
+    "version": (1, 0),
+    "blender": (2, 5, 7),
+    "api": 35964,
+    "location": "Texture paint 'nkey' panel",
+    "description": "Adds a layer manager for image based texture slots in paint and quick add layer tools",
+    "warning": "",
+    "wiki_url": "http://wiki.blender.org/index.php/Extensions:2.5/Py/Scripts/3D_interaction/Texture_paint_layers",
+    "tracker_url": "http://projects.blender.org/tracker/index.php?func=detail&aid=26789",
+    "category": "Texture"}
+        
+        
+import bpy
+from bpy.props import*
+import os
+from io_utils import ImportHelper
+
+
+#-------------------------------------------
+
+def load_a_brush(context, filepath):
+    if os.path.isdir(filepath):
+        return
+        
+    else:
+
+        try:
+            fn = bpy.path.display_name_from_filepath(filepath)
+            #create image and load...
+            img = bpy.data.images.load(filepath)
+            img.use_fake_user =True
+            
+            #create a texture
+            tex = bpy.data.textures.new(name =fn, type='IMAGE')
+            tex.use_fake_user =True
+            #tex.use_calculate_alpha = True
+            
+            #link the img to the texture
+            tex.image = img
+            
+        except:
+            print(f,'is not image?')
+
+    return {'FINISHED'}
+
+
+
+
+class load_single_brush(bpy.types.Operator, ImportHelper):
+    ''' Load an image as a brush texture'''
+    bl_idname = "texture.load_single_brush"  
+    bl_label = "Load Image as Brush"
+
+
+    @classmethod
+    def poll(cls, context):
+        return context.active_object != None
+
+    def execute(self, context):
+        return load_a_brush(context, self.filepath)
+
+#-------------------------------------------
+
+def loadbrushes(context, filepath):
+    if os.path.isdir(filepath):
+        directory = filepath
+        
+    else:
+        #is a file, find parent directory    
+        li = filepath.split(os.sep)
+        directory = filepath.rstrip(li[-1])
+        
+        
+    files = os.listdir(directory)
+    for f in files:
+        try:
+            fn = f[3:]
+            #create image and load...
+            img = bpy.data.images.load(filepath = directory +os.sep + f)
+            img.use_fake_user =True
+            
+            #create a texture
+            tex = bpy.data.textures.new(name =fn, type='IMAGE')
+            tex.use_fake_user =True
+            #tex.use_calculate_alpha = True
+            
+            #link the img to the texture
+            tex.image = img
+            
+        except:
+            print(f,'is not image?')
+            continue
+    return {'FINISHED'}
+
+
+
+
+class ImportBrushes(bpy.types.Operator, ImportHelper):
+    ''' Load a directory of images as brush textures '''
+    bl_idname = "texture.load_brushes"  
+    bl_label = "Load brushes directory"
+
+
+    @classmethod
+    def poll(cls, context):
+        return context.active_object != None
+
+    def execute(self, context):
+        return loadbrushes(context, self.filepath)
+
+#-------------------------------------------------------------------
+
+class OBJECT_PT_LoadBrushes(bpy.types.Panel):
+    bl_label = "Load Brush images"
+    bl_space_type = "VIEW_3D"
+    bl_region_type = "TOOLS"
+    #bl_context = "texturepaint"
+    
+    @classmethod
+    def poll(cls, context):
+        return (context.sculpt_object or context.image_paint_object)
+    
+    def draw(self, context):
+        layout = self.layout
+        row = layout.row()
+        row.operator('texture.load_brushes')
+        row = layout.row()
+        row.operator('texture.load_single_brush')
+
+
+#======================================================================
+
+
+
+
+
+class OBJECT_PT_Texture_paint_layers(bpy.types.Panel):
+    bl_label = "Texture Paint Layers"
+    bl_space_type = "VIEW_3D"
+    bl_region_type = "UI"
+    #bl_context = "texturepaint"
+    
+    @classmethod
+    def poll(cls, context):
+        return (context.image_paint_object)
+    
+    def draw(self, context):
+        layout = self.layout
+
+        ob = bpy.context.image_paint_object
+        if ob:
+            me = ob.data
+            mat = ob.active_material
+            if not mat:
+                row = layout.row() 
+                row.label(' Add a Material first!', icon = 'ERROR')
+            else:
+                row = layout.row()        
+                row.template_list(ob, "material_slots", ob, 
+                    "active_material_index", rows=2 )
+                
+        
+                
+                #list Paintable textures
+                #TODO add filter for channel type
+                i = -1
+                for t in mat.texture_slots:
+                    i+=1
+                    try:
+                        if t.texture.type =='IMAGE':                
+                            row = layout.row(align= True)                
+                            if t.texture == mat.active_texture:
+                                ai =  'BRUSH_DATA'
+                            else:
+                                ai = 'BLANK1'
+                            row.operator('object.set_active_paint_layer', 
+                                text = "", icon = ai).tex_index =i   
+                            row.prop(t.texture,'name', text = "")
+            
+        
+                            #Visibility
+                            if t.use:
+                                ic = 'RESTRICT_VIEW_OFF'
+                            else:
+                                ic = 'RESTRICT_VIEW_ON'
+                            row.prop(t,'use', text = "",icon = ic)
+                    except:
+                         continue
+    
+            
+    
+
+
+            
+            ts = mat.texture_slots[mat.active_texture_index]
+    
+            if ts:
+                row = layout.row()
+
+    
+                
+                
+                col = layout.column(align =True)
+                col.label('Active Properties:', icon = 'BRUSH_DATA') 
+                    
+                #use if rather than elif... can be mapped to multiple things                                   
+                if ts.use_map_diffuse:
+                    col.prop(ts,'diffuse_factor', slider = True)
+                if ts.use_map_color_diffuse:
+                    col.prop(ts,'diffuse_color_factor', slider = True)
+                if ts.use_map_alpha:
+                    col.prop(ts,'alpha_factor', slider = True)
+                if ts.use_map_translucency:
+                    col.prop(ts,'translucency_factor', slider = True)
+                if ts.use_map_specular:
+                    col.prop(ts,'specular_factor', slider = True)
+                if ts.use_map_color_spec:
+                    col.prop(ts,'specular_color_factor', slider = True)
+                if ts.use_map_hardness:
+                    col.prop(ts,'hardness_factor', slider = True)
+                    
+                if ts.use_map_normal:
+                    col.prop(ts,'normal_factor', slider = True)
+                if ts.use_map_warp:
+                    col.prop(ts,'warp_factor', slider = True)
+                if ts.use_map_displacement:
+                    col.prop(ts,'displacement_factor', slider = True)  
+                    
+                if ts.use_map_ambient:
+                    col.prop(ts,'ambient_factor', slider = True)               
+                if ts.use_map_emit:
+                    col.prop(ts,'emit_factor', slider = True)                  
+                if ts.use_map_mirror:
+                    col.prop(ts,'mirror_factor', slider = True)    
+                if ts.use_map_raymir:
+                    col.prop(ts,'raymir_factor', slider = True)    
+                 
+                                    
+                col.prop(ts,'blend_type',text='')   
+        
+            else:
+                row=layout.row()
+                row.label('No paint layers in material', icon = 'ERROR')        
+
+#            
+#        row = layout.row()
+#        row.label('')              
+#        row = layout.row()
+#        row.label('WIP: Use the X to delete!:')                  
+#        row = layout.row()                 
+#        row.template_ID(mat, "active_texture", new="texture.new") 
+
+
+class OBJECT_PT_Texture_paint_add(bpy.types.Panel):
+    bl_label = "Add Paint Layers"
+    bl_space_type = "VIEW_3D"
+    bl_region_type = "UI"
+    #bl_context = "texturepaint"
+    
+    @classmethod
+    def poll(cls, context):
+        return (context.image_paint_object)
+
+    def draw(self, context):
+        layout = self.layout
+
+        ob = bpy.context.image_paint_object
+        if ob:
+            me = ob.data
+            mat = ob.active_material
+            
+            if mat:
+                
+                #row = layout.row()   
+                col = layout.column(align =True)
+        
+        
+                col.operator('object.add_paint_layer',
+                    text = "Add Color").ttype = 'COLOR' 
+                col.operator('object.add_paint_layer',
+                    text = "Add Bump").ttype = 'NORMAL'
+                    
+                col = layout.column(align =True)
+                col.operator('object.add_paint_layer',
+                    text = "Add Specular").ttype = 'SPECULAR'
+                col.operator('object.add_paint_layer',
+                    text = "Add Spec Col").ttype = 'SPEC_COL'
+                col.operator('object.add_paint_layer',
+                    text = "Add Hardness").ttype = 'HARDNESS' 
+                    
+                col = layout.column(align =True)    
+                col.operator('object.add_paint_layer',
+                    text = "Add Alpha").ttype = 'ALPHA' 
+                col.operator('object.add_paint_layer',
+                    text = "Add Translucency").ttype = 'TRANSLUCENCY'
+                    
+#                col = layout.column(align =True)                      
+#                col.operator('object.add_paint_layer',
+#                    text = "Add Mirror").ttype = 'MIRROR' 
+#                col.operator('object.add_paint_layer',
+#                    text = "Add Ray Mirror").ttype = 'RAY_MIRROR'   
+                    
+                col = layout.column(align =True)                      
+                col.operator('object.add_paint_layer',
+                    text = "Add Emit").ttype = 'EMIT' 
+                col.operator('object.add_paint_layer',
+                    text = "Add Diffuse").ttype = 'DIFFUSE'   
+                col.operator('object.add_paint_layer',
+                    text = "Add Ambient").ttype = 'AMBIENT' 
+                                        
+            else:
+                row = layout.row() 
+                row.label(' Add a Material first!', icon = 'ERROR')
+        
+        
+
+def main(context,tn):
+    #tn is the index of the texture in the active material
+    ob = context.active_object
+    me = ob.data
+    mat = ob.active_material
+    mat.active_texture_index = tn    
+    ts = mat.texture_slots[tn]
+
+    #make sure it's visible
+    ts.use = True
+
+    #Mesh use UVs?
+    if not me.uv_textures:
+        bpy.ops.mesh.uv_texture_add()
+        
+    # texture Slot uses UVs?
+    if ts.texture_coords  == 'UV':
+        if ts.uv_layer:
+            uvtex = me.uv_textures[ts.uv_layer]
+        
+        else:
+            uvtex = me.uv_textures.active
+            me.uv_textures.active= uvtex
+    else:
+        ts.texture_coords ='UV'
+        uvtex = me.uv_textures.active
+        
+        
+    uvtex = uvtex.data.values()
+    
+    
+    #get image from texture slot
+    img = ts.texture.image
+    
+    #get material index
+    m_id = ob.active_material_index 
+
+    if img:
+        for f in me.faces:  
+            if f.material_index == m_id:
+                uvtex[f.index].select_uv
+                uvtex[f.index].image = img
+                uvtex[f.index].use_image = True
+            
+
+    else:
+        for f in me.faces:  
+            if f.material_index == m_id:
+                uvtex[f.index].image = img
+                #uvtex[f.index].use_image = False
+    me.update()
+
+
+
+
+
+
+
+class set_active_paint_layer(bpy.types.Operator):
+    ''''''
+    bl_idname = "object.set_active_paint_layer"
+    bl_label = "set_active_paint_layer"
+    tex_index = IntProperty(name = 'tex_index', 
+        description = "", default = 0)
+
+    @classmethod
+    def poll(cls, context):
+        return context.active_object != None
+
+    def execute(self, context):
+        tn = self.tex_index
+        main(context, tn)
+        return {'FINISHED'}
+
+
+
+def add_image_kludge(iname = 'grey', iwidth = 256, iheight = 256, 
+        icolor = (0.5,0.5,0.5,1.0)):
+    #evil kludge to get index of new image created using bpy.ops
+    #store current images
+    tl =[]
+    for i in bpy.data.images:
+        tl.append(i.name)
+    
+    
+    #create a new image
+
+    bpy.ops.image.new(name =iname,width =iwidth,height =iheight, 
+            color = icolor)
+        
+    #find its creation index
+    it = 0
+    for i in bpy.data.images:
+        if i.name not in tl:
+            return(bpy.data.images[it])
+            break
+        it += 1
+        
+    
+def add_paint(context, size =2048, typ = 'NORMAL'):
+    
+    ob = bpy.context.object
+    mat = ob.active_material
+    ts = mat.texture_slots.add()
+
+    if typ =='NORMAL':
+        color =(0.5,0.5,0.5,1.0)
+        iname = 'Bump'
+    elif typ =='COLOR':
+        iname ='Color'
+        color = (1.0,1.0,1.0,0.0)
+
+    elif typ =='ALPHA':
+        iname ='Alpha'
+        color = (1.0,1.0,1.0,0.0)                  
+    else:
+        color =(0.0,0.0,0.0,1.0)
+        iname = typ.capitalize()
+        
+#    bn = bpy.context.blend_data.filepath.split(bpy.utils._os.sep)[-1]
+#    bn = bn.replace('.blend', '')
+    bn = ob.name
+    
+    iname = bn +'_' + iname 
+      
+    tex = bpy.data.textures.new(name = iname, type = 'IMAGE')
+    ts.texture = tex
+    img = add_image_kludge(iname = typ, 
+        iwidth = size,iheight = size, icolor= color )
+    tex.image = img
+    
+    if typ == 'COLOR':
+        ts.use_map_color_diffuse =True
+
+        
+    elif typ == 'NORMAL':
+        ts.use_map_normal = True
+        ts.use_map_color_diffuse =False
+        ts.normal_factor = -1
+        ts.bump_method='BUMP_DEFAULT'
+        ts.bump_objectspace='BUMP_OBJECTSPACE'
+        
+    elif typ == 'SPECULAR':
+        ts.use_map_specular = True
+        ts.use_map_color_diffuse =False
+        ts.use_rgb_to_intensity = True
+        #ts.blend_type = 'MULTIPLY'
+        
+    elif typ == 'EMIT':
+        ts.use_map_emit = True
+        ts.use_map_color_diffuse =False
+        ts.use_rgb_to_intensity = True
+        
+    elif typ == 'ALPHA':
+        mat.use_transparency = True
+        ts.use_map_alpha = True
+        ts.use_map_color_diffuse =False
+        ts.use_rgb_to_intensity = True
+        ts.blend_type = 'MULTIPLY'
+        
+    elif typ == 'SPEC_COL':
+        ts.use_map_color_spec = True
+        ts.use_map_color_diffuse =False
+        ts.use_rgb_to_intensity = True
+        
+    elif typ == 'HARDNESS':
+        ts.use_map_hardness = True
+        ts.use_map_color_diffuse =False
+        ts.use_rgb_to_intensity = True        
+        
+    elif typ == 'DIFFUSE':
+        ts.use_map_diffuse = True
+        ts.use_map_color_diffuse =False
+        ts.use_rgb_to_intensity = True         
+
+    elif typ == 'TRANSLUCENCY':
+        ts.use_map_translucency = True
+        ts.use_map_color_diffuse =False
+        ts.use_rgb_to_intensity = True 
+
+    elif typ == 'AMBIENT':
+        ts.use_map_ambient = True
+        ts.use_map_color_diffuse =False
+        ts.use_rgb_to_intensity = True
+         
+    elif typ == 'MIRROR':
+        ts.use_map_mirror = True
+        ts.use_map_color_diffuse =False
+        ts.use_rgb_to_intensity = True 
+                        
+    elif typ == 'RAY_MIRROR':
+        mat.raytrace_mirror.use = True
+        ts.use_map_ray_mirror = True
+        ts.use_map_color_diffuse =False
+        ts.use_rgb_to_intensity = True 
+                                               
+    #set new texture slot to active
+    i = 0
+    ts_index = None
+    for t in mat.texture_slots:
+        if t == ts:
+            
+            ts_index = i
+            break
+        i += 1
+    if ts_index != None:
+        mat.active_texture_index = ts_index
+    
+    #set the texfaces using this material.
+        main(context,ts_index)
+    
+    
+    
+    
+
+class add_paint_layer(bpy.types.Operator):
+    ''''''
+    bl_idname = "object.add_paint_layer"
+    bl_label = "Add Paint Layer"
+    ttype = StringProperty(name ='ttype',default ='NORMAL')
+    
+    @classmethod
+    def poll(cls, context):
+        return context.active_object != None
+
+    def execute(self, context):
+        ttype = self.ttype
+        add_paint(context,typ= ttype)
+        return 'FINISHED'
+        
+
+
+
+#----------------------------------------------
+def save_painted(ts):
+    #generated images don't  have a path 
+    #so don't get saved with "save_dirty"
+    #ts is a texture slot object.
+    
+    sep = bpy.utils._os.sep
+    if ts:
+        if ts.texture.type =='IMAGE':
+            i = ts.texture.image
+            if i.source =='GENERATED':
+                if i.is_dirty:
+                    name = ts.name
+                    if i.file_format =='PNG':
+                        name = name + '.png'
+                    elif i.file_format =='TARGA':   
+                        name = name +'.tga' 
+                        
+                    bpy.context.scene.render.color_mode = 'RGBA'                          
+                    fp =bpy.path.abspath('//textures' + sep + name)
+                    try:
+                        i.save_render(fp)
+                        i.source = 'FILE'
+                        if bpy.context.user_preferences.filepaths.use_relative_paths:
+                            i.filepath = bpy.path.relpath(fp) 
+                        else:
+                            i.filepath = fp
+                        i.name = name
+                        i.use_premultiply = True
+                    except:
+                        print("something wrong with", fp)
+    #THAT'S THE GENERATED FILES saved, pathed and reloaded
+    #now save other painted textures
+    bpy.ops.image.save_dirty()
+
+
+
+def save_active_paint():
+    #for materials in current object
+    ob = bpy.context.object
+    for m in ob.material_slots:
+        for ts in m.material.texture_slots:
+            save_painted(ts)
+    return('FINISHED')                          
+
+def save_all_paint():
+    #for all materials
+    for m in bpy.data.materials:
+        for ts in m.texture_slots:
+            save_painted(ts)      
+    return('FINISHED')   
+            
+            
+class save_all_generated(bpy.types.Operator):
+    '''Saves painted layers to disc '''
+    bl_idname = "paint.save_all_generated" 
+     
+    bl_label = "SAVE PAINT LAYERS"
+
+
+    @classmethod
+    def poll(cls, context):
+        return context.active_object != None
+
+    def execute(self, context):
+        return save_active_paint()
+
+
+
+
+#-----------------------------------
+class OBJECT_PT_SavePainted(bpy.types.Panel):
+    bl_label = "Save All Painted"
+    bl_space_type = "VIEW_3D"
+    bl_region_type = "UI"
+    #bl_context = "texturepaint"
+    
+    @classmethod
+    def poll(cls, context):
+        return (context.image_paint_object)
+    
+    def draw(self, context):
+        layout = self.layout
+        row = layout.row()
+        row.operator('paint.save_all_generated')        
+        
+def register():
+    bpy.utils.register_module(__name__)
+
+def unregister():
+    bpy.utils.unregister_module(__name__)
+
+if __name__ == "__main__":
+    register()