1
2
3
4
5
6
7
8
9 import math
12 - def __init__(self, duration = 0.5, tween = None):
13 """Tweener
14 This class manages all active tweens, and provides a factory for
15 creating and spawning tween motions."""
16 self.currentTweens = []
17 self.defaultTweenType = tween or Easing.Linear.easeNone
18 self.defaultDuration = duration or 1.0
19
21 return len(self.currentTweens) > 0
22
23 - def addTweenNoArgs(self, obj, function, initial_value, value, **kwargs):
24 "Similar a addTween, solo que se especifica la funcion y el valor de forma explicita."
25 args = {function: value, 'initial_value': initial_value}
26
27 if "tweenTime" in kwargs:
28 t_time = kwargs.pop("tweenTime")
29 else: t_time = self.defaultDuration
30
31 if "tweenType" in kwargs:
32 t_type = kwargs.pop("tweenType")
33 else: t_type = self.defaultTweenType
34
35 if "onCompleteFunction" in kwargs:
36 t_completeFunc = kwargs.pop("onCompleteFunction")
37 else: t_completeFunc = None
38
39 if "onUpdateFunction" in kwargs:
40 t_updateFunc = kwargs.pop("onUpdateFunction")
41 else: t_updateFunc = None
42
43 if "tweenDelay" in kwargs:
44 t_delay = kwargs.pop("tweenDelay")
45 else: t_delay = 0
46
47 if kwargs:
48 raise ValueError("No puede llamar a esta funcion con argumentos nombrados, use addTween en su lugar.")
49
50 tw = Tween(obj, t_time, t_type, t_completeFunc, t_updateFunc, t_delay, **args)
51 if tw:
52 self.currentTweens.append( tw )
53 return tw
54
56 """ addTween( object, **kwargs) -> tweenObject or False
57
58 Example:
59 tweener.addTween( myRocket, throttle=50, setThrust=400, tweenTime=5.0, tweenType=tweener.OUT_QUAD )
60
61 You must first specify an object, and at least one property or function with a corresponding
62 change value. The tween will throw an error if you specify an attribute the object does
63 not possess. Also the data types of the change and the initial value of the tweened item
64 must match. If you specify a 'set' -type function, the tweener will attempt to get the
65 starting value by call the corresponding 'get' function on the object. If you specify a
66 property, the tweener will read the current state as the starting value. You add both
67 functions and property changes to the same tween.
68
69 in addition to any properties you specify on the object, these keywords do additional
70 setup of the tween.
71
72 tweenTime = the duration of the motion
73 tweenType = one of the predefined tweening equations or your own function
74 onCompleteFunction = specify a function to call on completion of the tween
75 onUpdateFunction = specify a function to call every time the tween updates
76 tweenDelay = specify a delay before starting.
77 """
78 if "tweenTime" in kwargs:
79 t_time = kwargs.pop("tweenTime")
80 else: t_time = self.defaultDuration
81
82 if "tweenType" in kwargs:
83 t_type = kwargs.pop("tweenType")
84 else: t_type = self.defaultTweenType
85
86 if "onCompleteFunction" in kwargs:
87 t_completeFunc = kwargs.pop("onCompleteFunction")
88 else: t_completeFunc = None
89
90 if "onUpdateFunction" in kwargs:
91 t_updateFunc = kwargs.pop("onUpdateFunction")
92 else: t_updateFunc = None
93
94 if "tweenDelay" in kwargs:
95 t_delay = kwargs.pop("tweenDelay")
96 else: t_delay = 0
97
98 tw = Tween( obj, t_time, t_type, t_completeFunc, t_updateFunc, t_delay, **kwargs )
99 if tw:
100 self.currentTweens.append( tw )
101 return tw
102
104 if tweenObj in self.currentTweens:
105 tweenObj.complete = True
106
107
109 """Get a list of all tweens acting on the specified object
110 Useful for manipulating tweens on the fly"""
111 tweens = []
112 for t in self.currentTweens:
113 if t.target is obj:
114 tweens.append(t)
115 return tweens
116
118 """Stop tweening an object, without completing the motion
119 or firing the completeFunction"""
120 for t in self.currentTweens:
121 if t.target is obj:
122 t.complete = True
123
125 """Stop tweening an object, without completing the motion
126 or firing the completeFunction"""
127 for t in self.currentTweens:
128 if t.target is obj:
129 for f in t.tFuncs:
130 if f[0] == field:
131 t.complete = True
132
134
135 for t in self.currentTweens:
136 t.update(t.duration)
137 self.currentTweens = []
138
139 - def update(self, timeSinceLastFrame):
140 removable = []
141 for t in self.currentTweens:
142 t.update(timeSinceLastFrame)
143
144 if t.complete:
145 removable.append(t)
146
147 for t in removable:
148 self.currentTweens.remove(t)
149
151 a_eliminar = []
152 for t in self.currentTweens:
153 a_eliminar.append(t)
154
155 for x in a_eliminar:
156 self.currentTweens.remove(x)
157
158
159
160 -class Tween(object):
161 - def __init__(self, obj, tduration, tweenType, completeFunction, updateFunction, delay, **kwargs):
162 """Tween object:
163 Can be created directly, but much more easily using Tweener.addTween( ... )
164 """
165
166 self.duration = tduration
167 self.delay = delay
168 self.target = obj
169 self.tween = tweenType
170 self.tweenables = kwargs
171 self.delta = 0
172 self.completeFunction = completeFunction
173 self.updateFunction = updateFunction
174 self.complete = False
175 self.tProps = []
176 self.tFuncs = []
177 self.paused = self.delay > 0
178 self.decodeArguments()
179
181 """Internal setup procedure to create tweenables and work out
182 how to deal with each"""
183
184 if len(self.tweenables) == 0:
185
186 print "TWEEN ERROR: No Tweenable properties or functions defined"
187 self.complete = True
188 return
189
190 assert(len(self.tweenables) == 2)
191
192 initial_value = self.tweenables.pop('initial_value')
193
194
195 for k, v in self.tweenables.items():
196
197
198 if not hasattr( self.target, k):
199 print "TWEEN ERROR: " + str(self.target) + " has no function " + k
200 self.complete = True
201 break
202
203 prop = func = False
204 startVal = 0
205 newVal = v
206
207 try:
208 startVal = self.target.__dict__[k]
209 prop = k
210 propName = k
211
212 except:
213 func = getattr( self.target, k)
214 funcName = k
215
216 if func:
217 try:
218 getFunc = getattr(self.target, funcName.replace("set", "get") )
219 startVal = getFunc()
220 print getfunc
221 except:
222
223
224
225 startVal = newVal * 0
226
227 startVal = initial_value
228 tweenable = Tweenable( startVal, newVal - startVal)
229 newFunc = [ k, func, tweenable]
230
231
232 self.tFuncs.append( newFunc )
233
234
235 if prop:
236 tweenable = Tweenable( startVal, newVal - startVal)
237 newProp = [ k, prop, tweenable]
238 self.tProps.append( newProp )
239
240 """
241 for k, v in self.tweenables.items():
242
243 # check that its compatible
244 if not hasattr( self.target, k):
245 print "TWEEN ERROR: " + str(self.target) + " has no function " + k
246 self.complete = True
247 break
248
249 prop = func = False
250 startVal = 0
251 newVal = v
252
253 try:
254 startVal = self.target.__dict__[k]
255 prop = k
256 propName = k
257
258 except:
259 func = getattr( self.target, k)
260 funcName = k
261
262 if func:
263 try:
264 getFunc = getattr(self.target, funcName.replace("set", "get") )
265 startVal = getFunc()
266 print getfunc
267 except:
268 # no start value, assume its 0
269 # but make sure the start and change
270 # dataTypes match :)
271 startVal = newVal * 0
272 tweenable = Tweenable( startVal, newVal - startVal)
273 newFunc = [ k, func, tweenable]
274
275 #setattr(self, funcName, newFunc[2])
276 self.tFuncs.append( newFunc )
277
278
279 if prop:
280 tweenable = Tweenable( startVal, newVal - startVal)
281 newProp = [ k, prop, tweenable]
282 self.tProps.append( newProp )
283 """
284
285
286 - def pause( self, numSeconds=-1 ):
287 """Pause this tween
288 do tween.pause( 2 ) to pause for a specific time
289 or tween.pause() which pauses indefinitely."""
290 self.paused = True
291 self.delay = numSeconds
292
294 """Resume from pause"""
295 if self.paused:
296 self.paused=False
297
299 """Update this tween with the time since the last frame
300 if there is an update function, it is always called
301 whether the tween is running or paused"""
302
303 if self.complete:
304 return
305
306 if self.paused:
307 if self.delay > 0:
308 self.delay = max( 0, self.delay - ptime )
309 if self.delay == 0:
310 self.paused = False
311 self.delay = -1
312 if self.updateFunction:
313 self.updateFunction()
314 return
315
316 self.delta = min(self.delta + ptime, self.duration)
317
318
319 for propName, prop, tweenable in self.tProps:
320 self.target.__dict__[prop] = self.tween( self.delta, tweenable.startValue, tweenable.change, self.duration )
321 for funcName, func, tweenable in self.tFuncs:
322 func( self.tween( self.delta, tweenable.startValue, tweenable.change, self.duration ) )
323
324
325 if self.delta == self.duration:
326 self.complete = True
327 if self.completeFunction:
328 self.completeFunction()
329
330 if self.updateFunction:
331 self.updateFunction()
332
333
334
336 """Return the tweenable values corresponding to the name of the original
337 tweening function or property.
338
339 Allows the parameters of tweens to be changed at runtime. The parameters
340 can even be tweened themselves!
341
342 eg:
343
344 # the rocket needs to escape!! - we're already moving, but must go faster!
345 twn = tweener.getTweensAffectingObject( myRocket )[0]
346 tweenable = twn.getTweenable( "thrusterPower" )
347 tweener.addTween( tweenable, change=1000.0, tweenTime=0.4, tweenType=tweener.IN_QUAD )
348
349 """
350 ret = None
351 for n, f, t in self.tFuncs:
352 if n == name:
353 ret = t
354 return ret
355 for n, p, t in self.tProps:
356 if n == name:
357 ret = t
358 return ret
359 return ret
360
362 """Disables and removes this tween
363 without calling the complete function"""
364 self.complete = True
365
369 """Tweenable:
370 Holds values for anything that can be tweened
371 these are normally only created by Tweens"""
372 self.startValue = start
373 self.change = change
374
375
376 """Robert Penner's easing classes ported over from actionscript by Toms Baugis (at gmail com).
377 There certainly is room for improvement, but wanted to keep the readability to some extent.
378
379 ================================================================================
380 Easing Equations
381 (c) 2003 Robert Penner, all rights reserved.
382 This work is subject to the terms in
383 http://www.robertpenner.com/easing_terms_of_use.html.
384 ================================================================================
385
386 TERMS OF USE - EASING EQUATIONS
387
388 Open source under the BSD License.
389
390 All rights reserved.
391
392 Redistribution and use in source and binary forms, with or without modification,
393 are permitted provided that the following conditions are met:
394
395 * Redistributions of source code must retain the above copyright notice,
396 this list of conditions and the following disclaimer.
397 * Redistributions in binary form must reproduce the above copyright notice,
398 this list of conditions and the following disclaimer in the documentation
399 and/or other materials provided with the distribution.
400 * Neither the name of the author nor the names of contributors may be used
401 to endorse or promote products derived from this software without specific
402 prior written permission.
403
404 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
405 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
406 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
407 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
408 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
409 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
410 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
411 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
412 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
413 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
414 """
417 @staticmethod
418 - def easeIn(t, b, c, d, s = 1.70158):
419 t = t / d
420 return c * t**2 * ((s+1) * t - s) + b
421
422 @staticmethod
423 - def easeOut (t, b, c, d, s = 1.70158):
424 t = t / d - 1
425 return c * (t**2 * ((s + 1) * t + s) + 1) + b
426
427 @staticmethod
429 t = t / (d * 0.5)
430 s = s * 1.525
431
432 if t < 1:
433 return c * 0.5 * (t**2 * ((s + 1) * t - s)) + b
434
435 t = t - 2
436 return c / 2 * (t**2 * ((s + 1) * t + s) + 2) + b
437
439 @staticmethod
441 t = t / d
442 if t < 1 / 2.75:
443 return c * (7.5625 * t**2) + b
444 elif t < 2 / 2.75:
445 t = t - 1.5 / 2.75
446 return c * (7.5625 * t**2 + 0.75) + b
447 elif t < 2.5 / 2.75:
448 t = t - 2.25 / 2.75
449 return c * (7.5625 * t**2 + .9375) + b
450 else:
451 t = t - 2.625 / 2.75
452 return c * (7.5625 * t**2 + 0.984375) + b
453
454 @staticmethod
457
458 @staticmethod
464
465
466
468 @staticmethod
470 t = t / d
471 return -c * (math.sqrt(1 - t**2) - 1) + b
472
473 @staticmethod
475 t = t / d - 1
476 return c * math.sqrt(1 - t**2) + b
477
478 @staticmethod
480 t = t / (d * 0.5)
481 if t < 1:
482 return -c * 0.5 * (math.sqrt(1 - t**2) - 1) + b
483
484 t = t - 2
485 return c*0.5 * (math.sqrt(1 - t**2) + 1) + b
486
487
489 @staticmethod
491 t = t / d
492 return c * t**3 + b
493
494 @staticmethod
496 t = t / d - 1
497 return c * (t**3 + 1) + b
498
499 @staticmethod
501 t = t / (d * 0.5)
502 if t < 1:
503 return c * 0.5 * t**3 + b
504
505 t = t - 2
506 return c * 0.5 * (t**3 + 2) + b
507
508
510 @staticmethod
511 - def easeIn (t, b, c, d, a = 0, p = 0):
512 if t==0: return b
513
514 t = t / d
515 if t == 1: return b+c
516
517 if not p: p = d * .3;
518
519 if not a or a < abs(c):
520 a = c
521 s = p / 4
522 else:
523 s = p / (2 * math.pi) * math.asin(c / a)
524
525 t = t - 1
526 return - (a * math.pow(2, 10 * t) * math.sin((t*d-s) * (2 * math.pi) / p)) + b
527
528
529 @staticmethod
530 - def easeOut (t, b, c, d, a = 0, p = 0):
531 if t == 0: return b
532
533 t = t / d
534 if (t == 1): return b + c
535
536 if not p: p = d * .3;
537
538 if not a or a < abs(c):
539 a = c
540 s = p / 4
541 else:
542 s = p / (2 * math.pi) * math.asin(c / a)
543
544 return a * math.pow(2,-10 * t) * math.sin((t * d - s) * (2 * math.pi) / p) + c + b
545
546
547 @staticmethod
549 if t == 0: return b
550
551 t = t / (d * 0.5)
552 if t == 2: return b + c
553
554 if not p: p = d * (.3 * 1.5)
555
556 if not a or a < abs(c):
557 a = c
558 s = p / 4
559 else:
560 s = p / (2 * math.pi) * math.asin(c / a)
561
562 if (t < 1):
563 t = t - 1
564 return -.5 * (a * math.pow(2, 10 * t) * math.sin((t * d - s) * (2 * math.pi) / p)) + b
565
566 t = t - 1
567 return a * math.pow(2, -10 * t) * math.sin((t * d - s) * (2 * math.pi) / p) * .5 + c + b
568
569
571 @staticmethod
573 if t == 0:
574 return b
575 else:
576 return c * math.pow(2, 10 * (t / d - 1)) + b - c * 0.001
577
578 @staticmethod
580 if t == d:
581 return b + c
582 else:
583 return c * (-math.pow(2, -10 * t / d) + 1) + b
584
585 @staticmethod
587 if t==0:
588 return b
589 elif t==d:
590 return b+c
591
592 t = t / (d * 0.5)
593
594 if t < 1:
595 return c * 0.5 * math.pow(2, 10 * (t - 1)) + b
596
597 return c * 0.5 * (-math.pow(2, -10 * (t - 1)) + 2) + b
598
599
601 @staticmethod
604
605 @staticmethod
608
609 @staticmethod
612
613 @staticmethod
616
617
619 @staticmethod
621 t = t / d
622 return c * t**2 + b
623
624 @staticmethod
626 t = t / d
627 return -c * t * (t-2) + b
628
629 @staticmethod
631 t = t / (d * 0.5)
632 if t < 1:
633 return c * 0.5 * t**2 + b
634
635 t = t - 1
636 return -c * 0.5 * (t * (t - 2) - 1) + b
637
638
640 @staticmethod
642 t = t / d
643 return c * t**4 + b
644
645 @staticmethod
647 t = t / d - 1
648 return -c * (t**4 - 1) + b
649
650 @staticmethod
652 t = t / (d * 0.5)
653 if t < 1:
654 return c * 0.5 * t**4 + b
655
656 t = t - 2
657 return -c * 0.5 * (t**4 - 2) + b
658
659
661 @staticmethod
663 t = t / d
664 return c * t**5 + b
665
666 @staticmethod
668 t = t / d - 1
669 return c * (t**5 + 1) + b
670
671 @staticmethod
673 t = t / (d * 0.5)
674 if t < 1:
675 return c * 0.5 * t**5 + b
676
677 t = t - 2
678 return c * 0.5 * (t**5 + 2) + b
679
681 @staticmethod
683 return -c * math.cos(t / d * (math.pi / 2)) + c + b
684
685 @staticmethod
687 return c * math.sin(t / d * (math.pi / 2)) + b
688
689 @staticmethod
691 return -c * 0.5 * (math.cos(math.pi * t / d) - 1) + b
692
693
695 @staticmethod
697 return c * (t/d)**5 + b
698
699 @staticmethod
701 return c * ((t / d - 1)**5 + 1) + b
702
703 @staticmethod
705 t = t / (d * 0.5)
706
707 if t < 1:
708 return c * 0.5 * t**5 + b
709
710 t = t - 2
711 return c * 0.5 * (t**5 + 2) + b
712
717 self.pos = 20
718 self.rot = 50
719
721 print self.pos, self.rot
722
725
728
730 print "I'm done tweening now mommy!"
731
732
733 if __name__=="__main__":
734 import time
735 T = Tweener()
736 tst = TweenTestObject()
737 mt = T.addTween( tst, setRotation=500.0, tweenTime=2.5, tweenType=T.OUT_QUAD,
738 pos=-200, tweenDelay=0.4, onCompleteFunction=tst.complete,
739 onUpdateFunction=tst.update )
740 s = time.clock()
741 changed = False
742 while T.hasTweens():
743 tm = time.clock()
744 d = tm - s
745 s = tm
746 T.update( d )
747 if mt.delta > 1.0 and not changed:
748
749 tweenable = mt.getTweenable( "setRotation" )
750
751 T.addTween( tweenable, change=-1000, tweenTime=0.7 )
752 T.addTween( mt, duration=-0.2, tweenTime=0.2 )
753 changed = True
754
755 print tst.getRotation(), tst.pos
756 time.sleep(0.06)
757 print tst.getRotation(), tst.pos
758