Mercurial > MadButterfly
diff pyink/tween.py @ 1140:d4dbcb93aee0
Separate the tween from the main module.
Handle the normal tween correctly.
author | wycc |
---|---|
date | Wed, 22 Dec 2010 23:02:46 +0800 |
parents | |
children | 8f0ee167c5b2 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pyink/tween.py Wed Dec 22 23:02:46 2010 +0800 @@ -0,0 +1,271 @@ +# -*- indent-tabs-mode: t; tab-width: 8; python-indent: 4; -*- +# vim: sw=4:ts=8:sts=4 +import traceback +import math +class TweenObject: + def __init__(self,doc,dom): + self.document = doc + self.dom = dom + self.width = float(dom.attribute("width")) + self.height = float(dom.attribute("height")) + + def updateMapping(self): + self.nodeToItem={} + root = self.dom + self.updateMappingNode(root) + def updateMappingNode(self,node): + for c in node.childList(): + self.updateMappingNode(c) + self.nodeToItem[c.getId()] = c + def updateTweenContent(self,obj, typ, source,dest,cur): + """ + Update the content of the duplicate scene group. We will use the (start,end) and cur to calculate the percentage of + the tween motion effect and then use it to update the transform matrix of the duplicated scene group. + """ + + start = source.idx + end = dest.idx + print cur,start,end + percent = (cur-start)*1.0/(end-start) + i = 0 + s = source.ref.firstChild() + d = dest.ref.firstChild() + sources={} + dests={} + + # Collect all objects + while d: + try: + label = d.attribute("inkscape:label") + except: + d = d.getNext() + continue + dests[label] = d + d = d.getNext() + # Check if the object in the source exists in the destination + s = source.ref.firstChild() + d = dest.ref.firstChild() + while s: + print s,d + try: + label = s.attribute("inkscape:label") + # Use i8nkscape:label to identidy the equipvalent objects + if label: + if dests.hasattr(label.value()): + self.updateTweenObject(obj,typ,s,dests[label.value()],percent) + s = s.getNext() + continue + except: + pass + # Search obejcts in the destination + while d: + try: + d.attribute("inkscape:label") + d = d.getNext() + continue + except: + pass + if s.name() == d.name(): + self.updateTweenObject(obj,typ,s,d,percent) + d = d.getNext() + break + d = d.getNext() + s = s.getNext() + + def parseTransform(self,obj): + """ + Return the transform matrix of an object + """ + try: + t = obj.attribute("transform") + print t + if t[0:9] == 'translate': + print "translate" + fields = t[10:].split(',') + x = float(fields[0]) + fields = fields[1].split(')') + y = float(fields[0]) + return [1,0,0,1,x,y] + elif t[0:6] == 'matrix': + print "matrix" + fields=t[7:].split(')') + fields = fields[0].split(',') + return [float(fields[0]),float(fields[1]),float(fields[2]),float(fields[3]),float(fields[4]),float(fields[5])] + except: + #traceback.print_exc() + return [1,0,0,1,0,0] + + def invA(self,m): + d = m[0]*m[3]-m[2]*m[1] + return [m[3]/d, -m[1]/d, -m[2]/d, m[0]/d, (m[1]*m[5]-m[4]*m[3])/d, (m[4]*m[2]-m[0]*m[5])/d] + + def mulA(self,a,b): + return [a[0]*b[0]+a[1]*b[2], + a[0]*b[1]+a[1]*b[3], + a[2]*b[0]+a[3]*b[2], + a[2]*b[1]+a[3]*b[3], + a[0]*b[4]+a[1]*b[5]+a[4], + a[2]*b[4]+a[3]*b[5]+a[5]] + + def decomposition(self,m): + """ + Decompose the affine matrix into production of translation,rotation,shear and scale. + The algorithm is documented at http://lists.w3.org/Archives/Public/www-style/2010Jun/0602.html + """ + if m[0]*m[3] == m[1]*m[2]: + print "The affine matrix is singular" + return [1,0,0,1,0,0] + A=m[0] + B=m[2] + C=m[1] + D=m[3] + E=m[4] + F=m[5] + sx = math.sqrt(A*A+B*B) + A = A/sx + B = B/sx + shear = m[0]*m[1]+m[2]*m[3] + C = C - A*shear + D = D - B*shear + sy = math.sqrt(C*C+D*D) + C = C/sy + D = D/sy + r = A*D-B*C + if r == -1: + shear = -shear + sy = -sy + R = math.atan2(B,A) + return [sx,sy, R, E,F] + + + def updateTweenObject(self,obj,typ,s,d,p): + """ + Generate tweened object in the @obj by using s and d in the @p percent + http://lists.w3.org/Archives/Public/www-style/2010Jun/0602.html + """ + if typ == 'relocate': + newobj = s.duplicate(self.document) + newobj.setAttribute("ref", s.getId()) + top = self.document.createElement("svg:g") + top.appendChild(newobj) + obj.appendChild(top) + if s.name() == 'svg:g': + # Parse the translate or matrix + sm = self.parseTransform(s) + dm = self.parseTransform(d) + top.setAttribute("transform","translate(%g,%g)" % ((dm[2]-sm[2])*p,(dm[5]-sm[5])*p)) + else: + try: + sx = float(s.attribute("x")) + sy = float(s.attribute("y")) + dx = float(d.attribute("x")) + dy = float(d.attribute("y")) + tx = (dx-sx)*p + ty = (dy-sy)*p + print tx,ty + top.setAttribute("transform","translate(%g,%g)" % (tx,ty)) + except: + traceback.print_exc() + pass + pass + elif typ == 'scale': + self.updateTweenObjectScale(obj,s,d,p) + pass + elif typ == 'normal': + newobj = s.duplicate(self.document) + newobj.setAttribute("ref", s.getId()) + top = self.document.createElement("svg:g") + top.appendChild(newobj) + obj.appendChild(top) + pass + + def updateTweenObjectScale(self,obj,s,d,p): + """ + Generate a new group which contains the original group and then + add the transform matrix to generate a tween frame between the + origin and destination scene group. + + We will parse the transform matrix of the @s and @d and then + generate the matrix which is (1-p) of @s and p percent of @d. + """ + newobj = s.duplicate(self.document) + top = self.document.createElement("svg:g") + top.appendChild(newobj) + obj.appendChild(top) + + if s.name() == 'svg:g': + # Parse the translate or matrix + # + # D = B inv(A) + try: + item = self.nodeToItem[s.attribute("id")] + (ox,oy) = item.getCenter() + except: + ox = 0 + oy = 0 + try: + item = self.nodeToItem[d.attribute("id")] + (dx,dy) = item.getCenter() + except: + dx = 0 + dy = 0 + + sm = self.parseTransform(s) + ss = self.decomposition(sm) + dm = self.parseTransform(d) + dd = self.decomposition(dm) + sx = (ss[0]*(1-p)+dd[0]*p)/ss[0] + sy = (ss[1]*(1-p)+dd[1]*p)/ss[0] + a = ss[2]*(1-p)+dd[2]*p-ss[2] + tx = ox*(1-p)+dx*p-ox + ty = oy*(1-p)+dy*p-oy + m = [math.cos(a),math.sin(a),-math.sin(a),math.cos(a),0,0] + m = self.mulA([sx,0,0,sy,0,0],m) + m = self.mulA(m,[1,0,0,1,-ox,oy-self.height]) + m = self.mulA([1,0,0,1,tx,self.height-ty],m) + + top.setAttribute("transform","matrix(%g,%g,%g,%g,%g,%g)" % (m[0],m[2],m[1],m[3],m[4],m[5])) + else: + try: + sw = float(s.attribute("width")) + sh = float(s.attribute("height")) + dw = float(d.attribute("width")) + dh = float(d.attribute("height")) + try: + item = self.nodeToItem[s.attribute("id")] + (ox,oy) = item.getCenter() + except: + ox = 0 + oy = 0 + try: + item = self.nodeToItem[d.attribute("id")] + (dx,dy) = item.getCenter() + except: + dx = 0 + dy = 0 + try: + sm = self.parseTransform(s) + ss = self.decomposition(sm) + except: + ss = [1,1,0,0,0] + pass + try: + dm = self.parseTransform(d) + dd = self.decomposition(dm) + except: + dd = [1,1,0,0,0] + dd[0] = ss[0]*dw/sw + dd[1] = ss[1]*dh/sh + sx = (ss[0]*(1-p)+dd[0]*p)/ss[0] + sy = (ss[1]*(1-p)+dd[1]*p)/ss[1] + a = ss[2]*(1-p)+dd[2]*p-ss[2] + tx = ox*(1-p)+dx*p + ty = oy*(1-p)+dy*p + m = [math.cos(a),math.sin(a),-math.sin(a),math.cos(a),0,0] + m = self.mulA([sx,0,0,sy,0,0],m) + m = self.mulA(m,[1,0,0,1,-ox,oy-self.height]) + m = self.mulA([1,0,0,1,tx,self.height-ty],m) + + top.setAttribute("transform","matrix(%g,%g,%g,%g,%g,%g)" % (m[0],m[2],m[1],m[3],m[4],m[5])) + except: + traceback.print_exc()