Mercurial > MadButterfly
comparison 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 |
comparison
equal
deleted
inserted
replaced
1138:593a418ed8bf | 1140:d4dbcb93aee0 |
---|---|
1 # -*- indent-tabs-mode: t; tab-width: 8; python-indent: 4; -*- | |
2 # vim: sw=4:ts=8:sts=4 | |
3 import traceback | |
4 import math | |
5 class TweenObject: | |
6 def __init__(self,doc,dom): | |
7 self.document = doc | |
8 self.dom = dom | |
9 self.width = float(dom.attribute("width")) | |
10 self.height = float(dom.attribute("height")) | |
11 | |
12 def updateMapping(self): | |
13 self.nodeToItem={} | |
14 root = self.dom | |
15 self.updateMappingNode(root) | |
16 def updateMappingNode(self,node): | |
17 for c in node.childList(): | |
18 self.updateMappingNode(c) | |
19 self.nodeToItem[c.getId()] = c | |
20 def updateTweenContent(self,obj, typ, source,dest,cur): | |
21 """ | |
22 Update the content of the duplicate scene group. We will use the (start,end) and cur to calculate the percentage of | |
23 the tween motion effect and then use it to update the transform matrix of the duplicated scene group. | |
24 """ | |
25 | |
26 start = source.idx | |
27 end = dest.idx | |
28 print cur,start,end | |
29 percent = (cur-start)*1.0/(end-start) | |
30 i = 0 | |
31 s = source.ref.firstChild() | |
32 d = dest.ref.firstChild() | |
33 sources={} | |
34 dests={} | |
35 | |
36 # Collect all objects | |
37 while d: | |
38 try: | |
39 label = d.attribute("inkscape:label") | |
40 except: | |
41 d = d.getNext() | |
42 continue | |
43 dests[label] = d | |
44 d = d.getNext() | |
45 # Check if the object in the source exists in the destination | |
46 s = source.ref.firstChild() | |
47 d = dest.ref.firstChild() | |
48 while s: | |
49 print s,d | |
50 try: | |
51 label = s.attribute("inkscape:label") | |
52 # Use i8nkscape:label to identidy the equipvalent objects | |
53 if label: | |
54 if dests.hasattr(label.value()): | |
55 self.updateTweenObject(obj,typ,s,dests[label.value()],percent) | |
56 s = s.getNext() | |
57 continue | |
58 except: | |
59 pass | |
60 # Search obejcts in the destination | |
61 while d: | |
62 try: | |
63 d.attribute("inkscape:label") | |
64 d = d.getNext() | |
65 continue | |
66 except: | |
67 pass | |
68 if s.name() == d.name(): | |
69 self.updateTweenObject(obj,typ,s,d,percent) | |
70 d = d.getNext() | |
71 break | |
72 d = d.getNext() | |
73 s = s.getNext() | |
74 | |
75 def parseTransform(self,obj): | |
76 """ | |
77 Return the transform matrix of an object | |
78 """ | |
79 try: | |
80 t = obj.attribute("transform") | |
81 print t | |
82 if t[0:9] == 'translate': | |
83 print "translate" | |
84 fields = t[10:].split(',') | |
85 x = float(fields[0]) | |
86 fields = fields[1].split(')') | |
87 y = float(fields[0]) | |
88 return [1,0,0,1,x,y] | |
89 elif t[0:6] == 'matrix': | |
90 print "matrix" | |
91 fields=t[7:].split(')') | |
92 fields = fields[0].split(',') | |
93 return [float(fields[0]),float(fields[1]),float(fields[2]),float(fields[3]),float(fields[4]),float(fields[5])] | |
94 except: | |
95 #traceback.print_exc() | |
96 return [1,0,0,1,0,0] | |
97 | |
98 def invA(self,m): | |
99 d = m[0]*m[3]-m[2]*m[1] | |
100 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] | |
101 | |
102 def mulA(self,a,b): | |
103 return [a[0]*b[0]+a[1]*b[2], | |
104 a[0]*b[1]+a[1]*b[3], | |
105 a[2]*b[0]+a[3]*b[2], | |
106 a[2]*b[1]+a[3]*b[3], | |
107 a[0]*b[4]+a[1]*b[5]+a[4], | |
108 a[2]*b[4]+a[3]*b[5]+a[5]] | |
109 | |
110 def decomposition(self,m): | |
111 """ | |
112 Decompose the affine matrix into production of translation,rotation,shear and scale. | |
113 The algorithm is documented at http://lists.w3.org/Archives/Public/www-style/2010Jun/0602.html | |
114 """ | |
115 if m[0]*m[3] == m[1]*m[2]: | |
116 print "The affine matrix is singular" | |
117 return [1,0,0,1,0,0] | |
118 A=m[0] | |
119 B=m[2] | |
120 C=m[1] | |
121 D=m[3] | |
122 E=m[4] | |
123 F=m[5] | |
124 sx = math.sqrt(A*A+B*B) | |
125 A = A/sx | |
126 B = B/sx | |
127 shear = m[0]*m[1]+m[2]*m[3] | |
128 C = C - A*shear | |
129 D = D - B*shear | |
130 sy = math.sqrt(C*C+D*D) | |
131 C = C/sy | |
132 D = D/sy | |
133 r = A*D-B*C | |
134 if r == -1: | |
135 shear = -shear | |
136 sy = -sy | |
137 R = math.atan2(B,A) | |
138 return [sx,sy, R, E,F] | |
139 | |
140 | |
141 def updateTweenObject(self,obj,typ,s,d,p): | |
142 """ | |
143 Generate tweened object in the @obj by using s and d in the @p percent | |
144 http://lists.w3.org/Archives/Public/www-style/2010Jun/0602.html | |
145 """ | |
146 if typ == 'relocate': | |
147 newobj = s.duplicate(self.document) | |
148 newobj.setAttribute("ref", s.getId()) | |
149 top = self.document.createElement("svg:g") | |
150 top.appendChild(newobj) | |
151 obj.appendChild(top) | |
152 if s.name() == 'svg:g': | |
153 # Parse the translate or matrix | |
154 sm = self.parseTransform(s) | |
155 dm = self.parseTransform(d) | |
156 top.setAttribute("transform","translate(%g,%g)" % ((dm[2]-sm[2])*p,(dm[5]-sm[5])*p)) | |
157 else: | |
158 try: | |
159 sx = float(s.attribute("x")) | |
160 sy = float(s.attribute("y")) | |
161 dx = float(d.attribute("x")) | |
162 dy = float(d.attribute("y")) | |
163 tx = (dx-sx)*p | |
164 ty = (dy-sy)*p | |
165 print tx,ty | |
166 top.setAttribute("transform","translate(%g,%g)" % (tx,ty)) | |
167 except: | |
168 traceback.print_exc() | |
169 pass | |
170 pass | |
171 elif typ == 'scale': | |
172 self.updateTweenObjectScale(obj,s,d,p) | |
173 pass | |
174 elif typ == 'normal': | |
175 newobj = s.duplicate(self.document) | |
176 newobj.setAttribute("ref", s.getId()) | |
177 top = self.document.createElement("svg:g") | |
178 top.appendChild(newobj) | |
179 obj.appendChild(top) | |
180 pass | |
181 | |
182 def updateTweenObjectScale(self,obj,s,d,p): | |
183 """ | |
184 Generate a new group which contains the original group and then | |
185 add the transform matrix to generate a tween frame between the | |
186 origin and destination scene group. | |
187 | |
188 We will parse the transform matrix of the @s and @d and then | |
189 generate the matrix which is (1-p) of @s and p percent of @d. | |
190 """ | |
191 newobj = s.duplicate(self.document) | |
192 top = self.document.createElement("svg:g") | |
193 top.appendChild(newobj) | |
194 obj.appendChild(top) | |
195 | |
196 if s.name() == 'svg:g': | |
197 # Parse the translate or matrix | |
198 # | |
199 # D = B inv(A) | |
200 try: | |
201 item = self.nodeToItem[s.attribute("id")] | |
202 (ox,oy) = item.getCenter() | |
203 except: | |
204 ox = 0 | |
205 oy = 0 | |
206 try: | |
207 item = self.nodeToItem[d.attribute("id")] | |
208 (dx,dy) = item.getCenter() | |
209 except: | |
210 dx = 0 | |
211 dy = 0 | |
212 | |
213 sm = self.parseTransform(s) | |
214 ss = self.decomposition(sm) | |
215 dm = self.parseTransform(d) | |
216 dd = self.decomposition(dm) | |
217 sx = (ss[0]*(1-p)+dd[0]*p)/ss[0] | |
218 sy = (ss[1]*(1-p)+dd[1]*p)/ss[0] | |
219 a = ss[2]*(1-p)+dd[2]*p-ss[2] | |
220 tx = ox*(1-p)+dx*p-ox | |
221 ty = oy*(1-p)+dy*p-oy | |
222 m = [math.cos(a),math.sin(a),-math.sin(a),math.cos(a),0,0] | |
223 m = self.mulA([sx,0,0,sy,0,0],m) | |
224 m = self.mulA(m,[1,0,0,1,-ox,oy-self.height]) | |
225 m = self.mulA([1,0,0,1,tx,self.height-ty],m) | |
226 | |
227 top.setAttribute("transform","matrix(%g,%g,%g,%g,%g,%g)" % (m[0],m[2],m[1],m[3],m[4],m[5])) | |
228 else: | |
229 try: | |
230 sw = float(s.attribute("width")) | |
231 sh = float(s.attribute("height")) | |
232 dw = float(d.attribute("width")) | |
233 dh = float(d.attribute("height")) | |
234 try: | |
235 item = self.nodeToItem[s.attribute("id")] | |
236 (ox,oy) = item.getCenter() | |
237 except: | |
238 ox = 0 | |
239 oy = 0 | |
240 try: | |
241 item = self.nodeToItem[d.attribute("id")] | |
242 (dx,dy) = item.getCenter() | |
243 except: | |
244 dx = 0 | |
245 dy = 0 | |
246 try: | |
247 sm = self.parseTransform(s) | |
248 ss = self.decomposition(sm) | |
249 except: | |
250 ss = [1,1,0,0,0] | |
251 pass | |
252 try: | |
253 dm = self.parseTransform(d) | |
254 dd = self.decomposition(dm) | |
255 except: | |
256 dd = [1,1,0,0,0] | |
257 dd[0] = ss[0]*dw/sw | |
258 dd[1] = ss[1]*dh/sh | |
259 sx = (ss[0]*(1-p)+dd[0]*p)/ss[0] | |
260 sy = (ss[1]*(1-p)+dd[1]*p)/ss[1] | |
261 a = ss[2]*(1-p)+dd[2]*p-ss[2] | |
262 tx = ox*(1-p)+dx*p | |
263 ty = oy*(1-p)+dy*p | |
264 m = [math.cos(a),math.sin(a),-math.sin(a),math.cos(a),0,0] | |
265 m = self.mulA([sx,0,0,sy,0,0],m) | |
266 m = self.mulA(m,[1,0,0,1,-ox,oy-self.height]) | |
267 m = self.mulA([1,0,0,1,tx,self.height-ty],m) | |
268 | |
269 top.setAttribute("transform","matrix(%g,%g,%g,%g,%g,%g)" % (m[0],m[2],m[1],m[3],m[4],m[5])) | |
270 except: | |
271 traceback.print_exc() |