Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender-addons.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'texture_paint_layer_manager.py')
-rw-r--r--texture_paint_layer_manager.py645
1 files changed, 645 insertions, 0 deletions
diff --git a/texture_paint_layer_manager.py b/texture_paint_layer_manager.py
new file mode 100644
index 00000000..c431f03f
--- /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 > Properties > Texture Paint Layers Panels",
+ "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": "Paint"}
+
+
+import bpy
+from bpy.props import*
+import os
+from bpy_extras.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()