#!BPY
""" Released under the Blender Artistic Licence (BAL)
Name: 'Animesh Bridge'
Blender: 241
Group: 'Animation'
Tooltip: 'Morphs an animated mesh'
"""
__author__ = "pat"
__version__ = "0.9 - 20060812 -"
__email__ = ('Author, pat:psycho3d*de')
__url__ = ("Author's website, www.psycho3d.de")
__bpydoc__ ="""\
This script creates a surface (like a nurbs surface) from a mesh that is 
animated with shapekeys and object animation (eg IPO, Path)

'No. steps' defines the minimum number of loops to be created. 
Additionally each key set for the shape ipo will create a loop.

Hotkeys:<br>
   [Q]uit
"""

import Blender as b
from Blender.BGL import *
from Blender.Draw import *

iFrames = Create(25) # anzahl frames/edgeloops die das script erzeugen soll
obStartFrame = Create(b.Get('staframe'))
obEndFrame = Create(b.Get('endframe'))

def morph():
	# objekt-init
	try:
		ob = b.Object.GetSelected()[0]
		if ob.getType() != 'Mesh':
			raise TypeError
	except IndexError:
		PupMenu("Error%t|No object selected")
	except TypeError:
		PupMenu("Error%t|Only works with meshes")
	else:
		me = b.NMesh.New()
		
		# var-init
		iCurFrame = 0 # aktueller durchlauf, als counter für edges
		iEdgeCount = 0 # speichert anzahl edges im originalmesh
		iStartFrame = obStartFrame.val
		fFrameIncrease = (obEndFrame.val - iStartFrame + 1.) / iFrames.val # wieviele frames ich weitermuss um die gewünschte anzahl zu erhalten
		
		# keyframes abfragen
		ipo = b.NMesh.GetRaw(ob.getData(1)).getKey().getIpo()
		keys = []
		#print ipo
		for curve in ipo.curves:
			for bez in curve.bezierPoints:
				keys.append((int)(bez.pt[0]))
		
		# andere keys einsetzen
		while (iCurFrame <= iFrames.val):
			keys.append((int)(iCurFrame * fFrameIncrease + iStartFrame))
			iCurFrame += 1
		
		keys.sort()
		lastkey = 0
		
		#
		# durch-schleifen und alle keys als mesh setzen
		#
		iCurFrame = 0
		for key in keys:
			
			# nur keys setzen die noch nicht da waren
			if key != lastkey:

				# frame setzen damit sich was tut
				b.Set('curframe', key)
				
				# aktuelles mesh holen und vertexkoordinaten global machen
				mTemp = b.NMesh.GetRawFromObject( ob.name )
				mTemp.transform( ob.matrix )
				
				# verts an das ergebnismesh anhangen
				if (iEdgeCount == 0):
					# die erste ladung verts und edges
					iEdgeCount = len(mTemp.edges)
					me.verts.extend(mTemp.verts)
					me.edges.extend(mTemp.edges)
				else:
					# sind schon verts da, ich muss also bridgen
					me.verts.extend(mTemp.verts)
					me.edges.extend(mTemp.edges)
					e = 0
					while ( e < iEdgeCount ):
						# alle neuen edges durchlaufen und mit vorhandenen verbinden
						edge1 = me.edges[ (iCurFrame-1)  * iEdgeCount + e ]
						edge2 = me.edges[  iCurFrame     * iEdgeCount + e ]
						v1, v2 = edge1.v1, edge1.v2
						v3, v4 = edge2.v1, edge2.v2
						me.faces.append( b.NMesh.Face( [v1, v2, v4, v3] ))
						e += 1
				
				# frame-nr +1 wenn kein doppelter key
				iCurFrame += 1
			
			# endlosschleife vermeiden
			lastkey = key
			
		b.NMesh.PutRaw(me)
	

def gui():
	global iFrames, obStartFrame, obEndFrame
	col = b.Window.Theme.Get()[0].get("buts").back
	glClearColor(col[0]/255., col[1]/255., col[2]/255., col[3]/255.)
	glClear(GL_COLOR_BUFFER_BIT)
	
	PushButton("Quit", 1, 10, 10, 150, 20)
	PushButton("Morph", 5, 10, 40, 150, 20, "Morphs the selected mesh object")
	iFrames = Number("No. steps: ", 2, 10, 70, 150, 20, iFrames.val, 1, obEndFrame.val - obStartFrame.val, "Number of steps to be created")
	obStartFrame = Number("Startframe: ", 2, 170, 70, 150, 20, obStartFrame.val, 1, 300000)
	obEndFrame = Number("Endframe: ", 2, 170, 40, 150, 20, obEndFrame.val, 1, 300000)

def event(evt, val):
  if (evt == QKEY and not val): Exit()
	
def bevent(evt):
  if (evt == 1): Exit()
  elif evt == 5: 
		f = b.Get('curframe')
		morph()
		b.Set('curframe', f)

Register(gui, event, bevent)