changeset 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 593a418ed8bf
children 8f0ee167c5b2
files pyink/MBScene.py pyink/primitive_test.svg pyink/tween.py
diffstat 3 files changed, 289 insertions(+), 279 deletions(-) [+]
line wrap: on
line diff
--- a/pyink/MBScene.py	Tue Dec 21 14:36:50 2010 +0800
+++ b/pyink/MBScene.py	Wed Dec 22 23:02:46 2010 +0800
@@ -11,6 +11,7 @@
 import time
 import pybInkscape
 import math
+from tween import TweenObject
 
 # Please refer to
 # http://www.assembla.com/wiki/show/MadButterfly/Inkscape_extention
@@ -132,29 +133,11 @@
 	pybInkscape.inkscape.connect('change_selection', self.show_selection)
 	self.last_select = None
 	self.lockui=False
+	self.tween=None
+	self.document = None
+	self.dom = None
 	pass
 
-    def startPolling(self):
-	objs =  self.desktop.selection.list()
-	if len(objs) != 1: 
-	    glib.timeout_add(500,self.startPolling)
-	    try:
-		self.nameEditor.set_text('')
-	    except:
-		traceback.print_exc()
-		pass
-	    return
-	o = objs[0]
-	if o == self.last_select: 
-            glib.timeout_add(500,self.startPolling)
-	    return
-	self.last_select = o
-	try:
-	    self.nameEditor.set_text(o.repr.attribute("inkscape:label"))
-	except:
-	    self.nameEditor.set_text('')
-	    pass
-        glib.timeout_add(500,self.startPolling)
     def show_selection(self,w,obj):
 	objs =  self.desktop.selection.list()
 	try:
@@ -502,15 +485,6 @@
 	    pass
 	pass
 
-    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
-	    print "Add",c.getId()
 
     
     def setCurrentScene(self,nth):
@@ -528,7 +502,7 @@
 	    available.
 	"""
 	self.current = nth
-	self.updateMapping()
+	self.tween.updateMapping()
 	for layer in self._framelines:
 	    i=0
 
@@ -564,258 +538,21 @@
 			    layer.duplicateGroup.setAttribute("sodipodi:insensitive","1")
 			    s.ref.setAttribute("style","display:none")
 			    s.ref.parent().appendChild(layer.duplicateGroup)
-			    self.updateTweenContent(layer.duplicateGroup, layer.get_tween_type(s.idx),s, layer._keys[i+2], nth)
+			    self.tween.updateTweenContent(layer.duplicateGroup, layer.get_tween_type(s.idx),s, layer._keys[i+2], nth)
+			else:
+			    layer.duplicateGroup = s.ref.duplicate(self.document)
+			    layer.duplicateGroup.setAttribute("style","")
+			    layer.duplicateGroup.setAttribute("inkscape:label","dup")
+			    layer.duplicateGroup.setAttribute("sodipodi:insensitive","1")
+			    s.ref.setAttribute("style","display:none")
+			    s.ref.parent().appendChild(layer.duplicateGroup)
 		    else:
 		        s.ref.setAttribute("style","display:none")
 		i = i + 2
 		pass
 	    pass
 	pass
-    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 parseMatrix(self,m):
-        d = (1-m[0])*(1-m[3])-m[1]*m[2]
-	if d == 0:
-	    return [1,0,0,1,m[4],m[5]]
-	else:
-            return [m[0],m[1],m[2],m[3],(m[4]-m[3]*m[4]+m[1]*m[5])/d,(m[5]-m[0]*m[5]+m[2]*m[4])/d]
-
-    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
-	"""
-	print 'compare',s,d
-	if typ == 'relocate':
-	    print "percent",p
-	    newobj = s.duplicate(self.document)
-	    newobj.setAttribute("ref", s.getId())
-	    top = self.document.createElement("svg:g")
-	    top.appendChild(newobj)
-	    obj.appendChild(top)
-	    print s.name()
-	    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':
-	    newobj = s.duplicate(self.document)
-	    top = self.document.createElement("svg:g")
-	    top.appendChild(newobj)
-	    obj.appendChild(top)
-	        
-	    print s,d
-	    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]
-		        pass
-		    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()
-		    pass
-	    pass
-	    
-	pass
     def enterGroup(self,obj):
         for l in self.layers:
 	    for s in l.node.childList():
@@ -1122,6 +859,7 @@
 	self.OK = True
 	self.dom = self.desktop.doc().root()
 	self.document = self.desktop.doc().rdoc
+	self.tween = TweenObject(self.document,self.dom)
 	self.parseScene()
 	self._create_framelines()
 	self._update_framelines()
--- a/pyink/primitive_test.svg	Tue Dec 21 14:36:50 2010 +0800
+++ b/pyink/primitive_test.svg	Wed Dec 22 23:02:46 2010 +0800
@@ -15,7 +15,7 @@
    id="svg2"
    version="1.1"
    inkscape:version="0.48+devel r9774 custom"
-   sodipodi:docname="aa.svg">
+   sodipodi:docname="primitive_test.svg">
   <defs
      id="defs4" />
   <sodipodi:namedview
@@ -56,6 +56,7 @@
       <ns0:scene
          start="21"
          ref="Layer 1s8009"
+         end="24"
          type="normal" />
     </ns0:scenes>
   </metadata>
@@ -84,8 +85,8 @@
          id="rect3431"
          height="432.13434"
          width="64.699173"
-         y="213.35323"
-         x="9.338623" />
+         y="220.30684"
+         x="3.5009925" />
     </g>
   </g>
 </svg>
--- /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()