#!BPY
"""
Name: '2D_cutout_from _Gimp'
Blender: 248
Group: 'Image'
Tooltip: 'Import layers from gimp and create objects to animate'
"""


__author__= ['Victor Barberan']
__url__ = ('http://blenderartists.org/forum/showthread.php?t=114409')
__version__= '0.1'
__bpydoc__= """\
Import layers from gimp and create objects to animate
This script requires xcftools (http://henning.makholm.net/software).
"""


# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
#
# ***** END GPL LICENCE BLOCK *****
# --------------------------------------------------------------------------

import Blender, commands, os
from Blender import *
from Blender.Mathutils import *

GLOBALS = {}
GLOBALS['mouse'] = None
GLOBALS['event'] = 2
GLOBALS['pack'] = Draw.Create(1)
GLOBALS['save'] = Draw.Create(0)
GLOBALS['pixel_unit'] = Draw.Create(100)
GLOBALS['parented'] = Draw.Create(0)

xcfinfo = 'xcfinfo'
xcf2png = 'xcf2png'

#load xcf file and all the rest of the stuff
def load_gimp(xcf_path):
	
	pu = GLOBALS['pixel_unit'].val
	xcf_file = Blender.sys.basename(xcf_path)
	xcf_dir = Blender.sys.dirname(xcf_path)+os.path.sep
	if GLOBALS['pack'].val:
		parts_dir = Get('tempdir')
	else:	
		parts_dir = xcf_dir+xcf_file[:-4]+'_parts'+os.path.sep
	tempdir = Get('tempdir')
	
	#get info of the xcf file
	info = commands.getoutput(xcfinfo+' '+'"'+xcf_path+'"')
		
	#Origin of layer position based on image dimension
	orig = info.splitlines()[0].split(',')[1].split(' ')[1].split('x')
	origenx = -((int(orig[0]) / pu) / 2)
	origenz = int(orig[1]) / pu
	
	#check if info was generated
	if 'not found' in info:
		Draw.PupMenu('Error importing file...%t| Do you have xcftools instaled??')
		return None
	
	#get number of layers
	layer_num = int(info.splitlines()[0].split(',')[2].strip('layers').strip())
	layers = []
	
	#create directory to save the pngs 
	if layer_num > 1:
		if not os.path.exists(parts_dir):
			os.mkdir(parts_dir)
		
	#get layer names and put in a list
	for n in range(layer_num):
		names = info.splitlines()[n+1].split(' ')[4:]
		name = ''
		for na in names:
				name += na+' '
		
		dims = info.splitlines()[n+1].split(' ')[1]	
		la = [name.rstrip(' '), dims.split('x')[0], dims.split('x')[1].split('+')[0], dims.split('+')[1], dims.split('+')[2]]
				
		layers.append(la)
	
	if GLOBALS['parented'].val:
		#list for store parenting relationship and use it at the end
		parenting = []
	
	#convert every layer to png, and import it
	for layer in layers:
		
		#generate  png image
		layerpng = parts_dir+layer[0].strip('"')+'.png'
		out = commands.getoutput(xcf2png+' "'+xcf_path+'" "'+layer[0]+'" -C -T -o "'+layerpng+'"')
				
		#check if image was generated
		if not os.path.exists(layerpng):
			Draw.PupMenu('Error importing file...%t| Do you have xcftools instaled??')
			return None
		
		#import image
		newImg = Image.Load(layerpng)
		
		#pack and erase image file if pack
		if GLOBALS['pack'].val:
			newImg.pack()
			if os.path.exists(layerpng): os.remove(layerpng)
		
		if GLOBALS['parented'].val:
			#store this layer parent relationship and get names information
			if layer[0].count('_') == 1:
				layername = layer[0].strip(' ').split('_')[0]
				parentname = layer[0].strip(' ').split('_')[1]
				parenting.append([layername.lower(), parentname.lower()])
			else:
				Draw.PupMenu('Error creating layer...%t| Check the layer '+layer[0]+' name.|Remember to separate the layer name and the parent layer name with a "_"| only one "_" character is allowed for parenting.')
				return None
		else:
			layername = layer[0].strip(' ')
		
				
		#put image name (5 letters of xcf filename) and layer name without parenting info
		newImg.name = xcf_file[:-4][:5]+': '+layername
								
		#create plane with dim an pos for each layer
		editmode = Window.EditMode()
		Window.EditMode(0)
		
		#dimensions and positions
		imgx = float(layer[1]) / pu
		imgz = float(layer[2]) / pu
		dx = float(layer[3]) / pu
		dz = float(layer[4]) / pu
		
		#vertex and faces
		verts = [ [-imgx/2,0,imgz/2],[imgx/2,0,imgz/2],[imgx/2,0,-imgz/2],[-imgx/2,0,-imgz/2] ]
		faces = [ [3,2,1,0] ]
		
		#create mesh
		me_plane = Mesh.New(layername)	
		me_plane.verts.extend(verts)
		me_plane.faces.extend(faces)
		
		#create object
		ob_plane = Object.New('Mesh', layername)
		ob_plane.link(me_plane)
		scn = Scene.GetCurrent()
		scn.objects.link(ob_plane)
		
		if editmode: Window.EditMode(1)
		
		#position object (from layer position)
		ob_plane.LocX = origenx + (imgx/2) + dx
		ob_plane.LocZ = origenz - (imgz/2) - dz
		
		#UV mapping and image for viewport
		me_plane.faces[0].image = newImg
		me_plane.faces[0].uv = [Vector(1,1),Vector(0,1),Vector(0,0),Vector(1,0)]
		me_plane.faces[0].transp = Mesh.FaceTranspModes.ALPHA
		
		#create texture
		tex = Texture.New(layername)
		tex.setType('Image')
		#en esta linea marca el error de imagen ????????????????
		tex.setImage(newImg)
		tex.useAlpha = Texture.ImageFlags.USEALPHA
		
		#create and adjust material
		mat = Material.New(layer[0])
		mat.mode |= Material.Modes.ZTRANSP
		mat.mode |= Material.Modes.SHADELESS
		mat.setAlpha(0)
		mat.setTexture(0, tex, Texture.TexCo.UV)
		mat.getTextures()[0].mapto |= Texture.MapTo.ALPHA
		me_plane.materials += [mat]
	
	if GLOBALS['parented'].val:
		#get names of object in scene
		obnames = []
		for o in Object.Get():
			obnames.append(o.name)
			
		#create child parent relations, once all objects are created
		for couple in parenting:
			if not 'none' in couple:
				if not couple[0] in obnames or not couple[1] in obnames:
					Draw.PupMenu('Error parenting objects%t| in '+couple[0]+' or in '+couple[1]+'|  Check your layer names!!')					
					return None 	
				Object.Get(couple[1]).makeParent([Object.Get(couple[0])])
		
		
	newImg.makeCurrent()
	Draw.Redraw()

def file_selecc(e,v):
	print '\nstart********************\n'
	Window.FileSelector(load_gimp, 'Import Gimp', '*.xcf')
	GLOBALS['event'] = e

def do_pack(e,v):
	GLOBALS['save'].val = 0
	GLOBALS['pack'].val = 1
	GLOBALS['event'] = e

def do_save(e,v):
	GLOBALS['save'].val = 1
	GLOBALS['pack'].val = 0
	GLOBALS['event'] = e

def redraw(e,v):
	GLOBALS['event'] = e

EVENT_EXIT = 1
EVENT_REDRAW = 2
def ui():
	x, y = GLOBALS['mouse']
	x-=50
	y-=5

	GLOBALS['pack'] = Draw.Toggle('Pack Layers', EVENT_REDRAW, x, y+50, 100, 20, GLOBALS['pack'].val,'Pack generated images (one for each layer) in blend file',do_pack)
	GLOBALS['save'] = Draw.Toggle('Save Layers', EVENT_REDRAW, x+100, y+50, 100, 20, GLOBALS['save'].val,'Save generated images (in a sub directory)',do_save)
	Draw.Label('Pixels per Blender Unit',x,y+25,200,20)
	GLOBALS['pixel_unit'] = Draw.Slider('Pixels  ', EVENT_REDRAW, x, y+5, 200, 20, GLOBALS['pixel_unit'].val, 1, 1000, 1, ' Number of pixels in the image to be considered a Blender unit (small value = big model)', redraw)
	GLOBALS['parented'] = Draw.Toggle('Create child-parent relations', EVENT_REDRAW, x, y-30, 200, 20, GLOBALS['parented'].val,'Create parent relations based on layer names. You should name your layers: "layername_parentlayername" ',redraw)
 	Draw.PushButton('Import Gimp Image...', EVENT_EXIT, x+30, y-100, 150, 40, '', file_selecc)
	
	GLOBALS['event'] = 1
	 
			
def main():
	GLOBALS['mouse'] = Window.GetMouseCoords()
	
	while GLOBALS['event'] == EVENT_REDRAW:
		Draw.UIBlock(ui)
			
			
if __name__=='__main__':
	main()

